172 lines
No EOL
6.9 KiB
C#
172 lines
No EOL
6.9 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 WingsAPI.Data.GameData;
|
|
using WingsEmu.DTOs.Maps;
|
|
|
|
namespace Plugin.ResourceLoader.Loaders
|
|
{
|
|
public class MapResourceFileLoader : IResourceLoader<MapDataDTO>
|
|
{
|
|
private readonly ResourceLoadingConfiguration _config;
|
|
|
|
|
|
public MapResourceFileLoader(ResourceLoadingConfiguration config) => _config = config;
|
|
|
|
public async Task<IReadOnlyList<MapDataDTO>> LoadAsync()
|
|
{
|
|
string filePath = Path.Combine(_config.GameDataPath, "MapIDData.dat");
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
bool dbFirst = string.Equals(Environment.GetEnvironmentVariable("DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(Environment.GetEnvironmentVariable("RESOURCE_DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase);
|
|
if (dbFirst)
|
|
{
|
|
TryHydrateDatFileFromDatabase("MapIDData.dat", filePath);
|
|
TryHydrateMapFilesFromDatabase();
|
|
}
|
|
}
|
|
|
|
if (!File.Exists(filePath))
|
|
{
|
|
throw new FileNotFoundException($"{filePath} should be present");
|
|
}
|
|
|
|
var maps = new List<MapDataDTO>();
|
|
var dictionaryId = new Dictionary<int, string>();
|
|
|
|
int i = 0;
|
|
using (var mapIdStream = new StreamReader(filePath, Encoding.GetEncoding(1252)))
|
|
{
|
|
string line;
|
|
while ((line = await mapIdStream.ReadLineAsync()) != null)
|
|
{
|
|
string[] values = line.Split(' ');
|
|
if (values.Length <= 1)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!int.TryParse(values[0], out int mapId))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!dictionaryId.ContainsKey(mapId))
|
|
{
|
|
dictionaryId.Add(mapId, values[4]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!Directory.Exists(_config.GameMapsPath) || !new DirectoryInfo(_config.GameMapsPath).GetFiles().Any())
|
|
{
|
|
bool dbFirst = string.Equals(Environment.GetEnvironmentVariable("DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(Environment.GetEnvironmentVariable("RESOURCE_DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase);
|
|
if (dbFirst)
|
|
{
|
|
TryHydrateMapFilesFromDatabase();
|
|
}
|
|
}
|
|
|
|
foreach (FileInfo file in new DirectoryInfo(_config.GameMapsPath).GetFiles())
|
|
{
|
|
string name = string.Empty;
|
|
|
|
if (dictionaryId.TryGetValue(int.Parse(file.Name), out string value))
|
|
{
|
|
name = value;
|
|
}
|
|
|
|
|
|
byte[] data = await File.ReadAllBytesAsync(file.FullName);
|
|
short width = BitConverter.ToInt16(data, 0);
|
|
short height = BitConverter.ToInt16(data, 2);
|
|
|
|
maps.Add(new MapDataDTO
|
|
{
|
|
Id = short.Parse(file.Name),
|
|
Name = name,
|
|
Width = width,
|
|
Height = height,
|
|
Grid = data.Skip(4).ToArray()
|
|
});
|
|
i++;
|
|
}
|
|
|
|
Log.Info($"[RESOURCE_LOADER] {maps.Count} Maps loaded");
|
|
return maps;
|
|
}
|
|
|
|
private void TryHydrateDatFileFromDatabase(string datFileName, string targetPath)
|
|
{
|
|
try
|
|
{
|
|
using var conn = OpenConnection();
|
|
using var cmd = new NpgsqlCommand("SELECT content FROM resource_files WHERE category='dat' AND relative_path=@path LIMIT 1;", conn);
|
|
cmd.Parameters.AddWithValue("path", $"dat/{datFileName}");
|
|
object result = cmd.ExecuteScalar();
|
|
|
|
if (result is byte[] bytes && bytes.Length > 0)
|
|
{
|
|
Directory.CreateDirectory(Path.GetDirectoryName(targetPath) ?? _config.GameDataPath);
|
|
File.WriteAllBytes(targetPath, bytes);
|
|
Log.Info($"[DB_FIRST] Hydrated {datFileName} from resource_files");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error($"[DB_FIRST] Could not hydrate {datFileName} from database", ex);
|
|
}
|
|
}
|
|
|
|
private void TryHydrateMapFilesFromDatabase()
|
|
{
|
|
try
|
|
{
|
|
Directory.CreateDirectory(_config.GameMapsPath);
|
|
using var conn = OpenConnection();
|
|
using var cmd = new NpgsqlCommand("SELECT relative_path, content FROM resource_files WHERE category='maps';", conn);
|
|
using var reader = cmd.ExecuteReader();
|
|
int count = 0;
|
|
while (reader.Read())
|
|
{
|
|
string relative = reader.GetString(0).Replace('/', Path.DirectorySeparatorChar);
|
|
byte[] content = (byte[])reader[1];
|
|
string path = Path.Combine(_config.ResourcePaths, relative);
|
|
Directory.CreateDirectory(Path.GetDirectoryName(path) ?? _config.GameMapsPath);
|
|
File.WriteAllBytes(path, content);
|
|
count++;
|
|
}
|
|
|
|
if (count > 0)
|
|
{
|
|
Log.Info($"[DB_FIRST] Hydrated {count} map files from resource_files");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error("[DB_FIRST] Could not hydrate map files from database", ex);
|
|
}
|
|
}
|
|
|
|
private static NpgsqlConnection OpenConnection()
|
|
{
|
|
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";
|
|
|
|
var conn = new NpgsqlConnection($"Host={host};Port={port};Database={db};Username={user};Password={pass}");
|
|
conn.Open();
|
|
return conn;
|
|
}
|
|
}
|
|
} |