211 lines
No EOL
8.8 KiB
C#
211 lines
No EOL
8.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Npgsql;
|
|
using PhoenixLib.Logging;
|
|
using PhoenixLib.MultiLanguage;
|
|
using WingsAPI.Data.GameData;
|
|
using WingsEmu.DTOs.Buffs;
|
|
using WingsEmu.DTOs.Items;
|
|
using WingsEmu.DTOs.NpcMonster;
|
|
using WingsEmu.DTOs.Quests;
|
|
using WingsEmu.DTOs.Skills;
|
|
using WingsEmu.Game._i18n;
|
|
|
|
namespace Plugin.ResourceLoader.Loaders
|
|
{
|
|
public class GameDataLanguageFileLoader : IResourceLoader<GameDataTranslationDto>
|
|
{
|
|
private static readonly List<(string, GameDataType)> _fileNames = new()
|
|
{
|
|
new ValueTuple<string, GameDataType>("_code_{0}_Card.txt", GameDataType.Card),
|
|
new ValueTuple<string, GameDataType>("_code_{0}_monster.txt", GameDataType.NpcMonster),
|
|
new ValueTuple<string, GameDataType>("_code_{0}_Item.txt", GameDataType.Item),
|
|
new ValueTuple<string, GameDataType>("_code_{0}_quest.txt", GameDataType.QuestName),
|
|
new ValueTuple<string, GameDataType>("_code_{0}_Skill.txt", GameDataType.Skill)
|
|
};
|
|
|
|
private readonly IResourceLoader<CardDTO> _cardLoader;
|
|
|
|
private readonly ResourceLoadingConfiguration _config;
|
|
private readonly IResourceLoader<ItemDTO> _itemLoader;
|
|
private readonly IResourceLoader<NpcMonsterDto> _npcLoader;
|
|
private readonly IResourceLoader<QuestDto> _questLoader;
|
|
private readonly IResourceLoader<SkillDTO> _skillLoader;
|
|
|
|
public GameDataLanguageFileLoader(ResourceLoadingConfiguration config, IResourceLoader<ItemDTO> itemLoader, IResourceLoader<CardDTO> cardLoader, IResourceLoader<SkillDTO> skillLoader,
|
|
IResourceLoader<QuestDto> questLoader, IResourceLoader<NpcMonsterDto> npcLoader)
|
|
{
|
|
_config = config;
|
|
_itemLoader = itemLoader;
|
|
_cardLoader = cardLoader;
|
|
_skillLoader = skillLoader;
|
|
_questLoader = questLoader;
|
|
_npcLoader = npcLoader;
|
|
}
|
|
|
|
public async Task<IReadOnlyList<GameDataTranslationDto>> LoadAsync()
|
|
{
|
|
var translations = new List<GameDataTranslationDto>();
|
|
|
|
foreach ((string fileName, GameDataType dataType) in _fileNames)
|
|
{
|
|
translations.AddRange(await LoadAsync(fileName, dataType));
|
|
}
|
|
|
|
return translations;
|
|
}
|
|
|
|
private static string ToNostaleRegionKey(RegionLanguageType type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case RegionLanguageType.FR:
|
|
return "fr";
|
|
case RegionLanguageType.EN:
|
|
return "uk";
|
|
case RegionLanguageType.DE:
|
|
return "de";
|
|
case RegionLanguageType.PL:
|
|
return "pl";
|
|
case RegionLanguageType.IT:
|
|
return "it";
|
|
case RegionLanguageType.ES:
|
|
return "es";
|
|
case RegionLanguageType.CZ:
|
|
return "cz";
|
|
case RegionLanguageType.TR:
|
|
return "tr";
|
|
default:
|
|
return "uk";
|
|
}
|
|
}
|
|
|
|
public static Encoding GetEncoding(RegionLanguageType key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case RegionLanguageType.EN:
|
|
case RegionLanguageType.FR:
|
|
case RegionLanguageType.ES:
|
|
return Encoding.GetEncoding(1252);
|
|
case RegionLanguageType.DE:
|
|
case RegionLanguageType.PL:
|
|
case RegionLanguageType.IT:
|
|
case RegionLanguageType.CZ:
|
|
return Encoding.GetEncoding(1250);
|
|
case RegionLanguageType.TR:
|
|
return Encoding.GetEncoding(1254);
|
|
default:
|
|
throw new ArgumentOutOfRangeException(nameof(key), key, null);
|
|
}
|
|
}
|
|
|
|
private async Task<IReadOnlyList<GameDataTranslationDto>> LoadAsync(string fileToParse, GameDataType dataType)
|
|
{
|
|
var translations = new List<GameDataTranslationDto>();
|
|
HashSet<string> _hashSet = dataType switch
|
|
{
|
|
GameDataType.Item => (await _itemLoader.LoadAsync()).Select(s => s.Name).ToHashSet(),
|
|
GameDataType.Card => (await _cardLoader.LoadAsync()).Select(s => s.Name).ToHashSet(),
|
|
GameDataType.NpcMonster => (await _npcLoader.LoadAsync()).Select(s => s.Name).ToHashSet(),
|
|
GameDataType.Skill => (await _skillLoader.LoadAsync()).Select(s => s.Name).ToHashSet(),
|
|
GameDataType.QuestName => (await _questLoader.LoadAsync()).Select(s => s.Name).ToHashSet(),
|
|
_ => new HashSet<string>()
|
|
};
|
|
|
|
foreach (RegionLanguageType lang in Enum.GetValues<RegionLanguageType>())
|
|
{
|
|
if (lang == RegionLanguageType.RU)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string fileName = string.Format(fileToParse, ToNostaleRegionKey(lang));
|
|
string fileLang = $"{_config.GameLanguagePath}/{fileName}";
|
|
|
|
bool dbFirst = string.Equals(Environment.GetEnvironmentVariable("DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(Environment.GetEnvironmentVariable("RESOURCE_DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase);
|
|
|
|
IEnumerable<string> lines = null;
|
|
|
|
if (File.Exists(fileLang))
|
|
{
|
|
lines = await File.ReadAllLinesAsync(fileLang, GetEncoding(lang));
|
|
}
|
|
else if (dbFirst)
|
|
{
|
|
lines = TryLoadLangLinesFromDatabase(fileName, GetEncoding(lang));
|
|
}
|
|
|
|
if (lines == null)
|
|
{
|
|
Log.Warn($"[DB_FIRST] Missing language source '{fileLang}', skipping.");
|
|
continue;
|
|
}
|
|
|
|
foreach (string line in lines)
|
|
{
|
|
string[] lineSave = line.Split('\t');
|
|
if (lineSave.Length <= 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!_hashSet.Contains(lineSave[0]))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
translations.Add(new GameDataTranslationDto
|
|
{
|
|
DataType = dataType,
|
|
Language = lang,
|
|
Key = lineSave[0],
|
|
Value = lineSave[1]
|
|
});
|
|
}
|
|
}
|
|
|
|
Log.Info($"[RESOURCE_LOADER] Loaded {translations.Count} Game Data translations of {dataType.ToString()}");
|
|
|
|
return translations;
|
|
}
|
|
|
|
private IEnumerable<string> TryLoadLangLinesFromDatabase(string langFileName, Encoding encoding)
|
|
{
|
|
try
|
|
{
|
|
string host = Environment.GetEnvironmentVariable("DATABASE_IP") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_IP") ?? "127.0.0.1";
|
|
string port = Environment.GetEnvironmentVariable("DATABASE_PORT") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PORT") ?? "5432";
|
|
string db = Environment.GetEnvironmentVariable("DATABASE_NAME") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_NAME") ?? "game";
|
|
string user = Environment.GetEnvironmentVariable("DATABASE_USER") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_USER") ?? "postgres";
|
|
string pass = Environment.GetEnvironmentVariable("DATABASE_PASSWORD") ?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PASSWORD") ?? "postgres";
|
|
|
|
using var conn = new NpgsqlConnection($"Host={host};Port={port};Database={db};Username={user};Password={pass}");
|
|
conn.Open();
|
|
|
|
using var cmd = new NpgsqlCommand("SELECT content FROM resource_files WHERE category='lang' AND (relative_path=@path OR lower(relative_path)=lower(@path) OR lower(relative_path) LIKE lower('%/' || @name)) LIMIT 1;", conn);
|
|
cmd.Parameters.AddWithValue("path", $"lang/{langFileName}");
|
|
cmd.Parameters.AddWithValue("name", langFileName);
|
|
object result = cmd.ExecuteScalar();
|
|
|
|
if (result is byte[] bytes && bytes.Length > 0)
|
|
{
|
|
string text = encoding.GetString(bytes);
|
|
Log.Info($"[DB_FIRST] Loaded lang file {langFileName} from database");
|
|
return text.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error($"[DB_FIRST] Could not load lang file {langFileName} from database", ex);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
} |