117 lines
5 KiB
C#
117 lines
5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Npgsql;
|
|
using PhoenixLib.Logging;
|
|
|
|
namespace Plugin.ResourceLoader.Services
|
|
{
|
|
public class DbFirstResourceHydratorService : IHostedService
|
|
{
|
|
private readonly ResourceLoadingConfiguration _configuration;
|
|
|
|
public DbFirstResourceHydratorService(ResourceLoadingConfiguration configuration)
|
|
{
|
|
_configuration = configuration;
|
|
}
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
bool dbFirst = string.Equals(Environment.GetEnvironmentVariable("DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(Environment.GetEnvironmentVariable("RESOURCE_DB_FIRST"), "true", StringComparison.OrdinalIgnoreCase);
|
|
if (!dbFirst)
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
bool strictDbOnly = string.Equals(Environment.GetEnvironmentVariable("STRICT_DB_ONLY"), "true", StringComparison.OrdinalIgnoreCase);
|
|
|
|
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();
|
|
|
|
var counters = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase)
|
|
{
|
|
["dat"] = 0,
|
|
["lang"] = 0,
|
|
["maps"] = 0,
|
|
["config_scripts"] = 0
|
|
};
|
|
|
|
using var cmd = new NpgsqlCommand("SELECT category, relative_path, content FROM resource_files;", conn);
|
|
using var reader = cmd.ExecuteReader();
|
|
while (reader.Read())
|
|
{
|
|
string category = reader.GetString(0);
|
|
string relativePath = reader.GetString(1).Replace('/', Path.DirectorySeparatorChar);
|
|
byte[] content = (byte[])reader[2];
|
|
|
|
string? destination = category switch
|
|
{
|
|
"dat" => Path.Combine(_configuration.ResourcePaths, relativePath),
|
|
"lang" => Path.Combine(_configuration.ResourcePaths, relativePath),
|
|
"maps" => Path.Combine(_configuration.ResourcePaths, relativePath),
|
|
"config_scripts" => Path.Combine(Directory.GetCurrentDirectory(), relativePath),
|
|
_ => null
|
|
};
|
|
|
|
if (destination == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
string? dir = Path.GetDirectoryName(destination);
|
|
if (!string.IsNullOrWhiteSpace(dir))
|
|
{
|
|
Directory.CreateDirectory(dir);
|
|
}
|
|
|
|
File.WriteAllBytes(destination, content);
|
|
if (counters.ContainsKey(category))
|
|
{
|
|
counters[category]++;
|
|
}
|
|
}
|
|
|
|
if (strictDbOnly && (counters["dat"] == 0 || counters["lang"] == 0 || counters["maps"] == 0))
|
|
{
|
|
throw new InvalidOperationException("STRICT_DB_ONLY enabled but one or more required resource categories are missing in resource_files.");
|
|
}
|
|
|
|
Log.Info($"[DB_FIRST] Hydrated files from DB: dat={counters["dat"]} lang={counters["lang"]} maps={counters["maps"]} scripts={counters["config_scripts"]}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error("[DB_FIRST] Failed to hydrate resources from database", ex);
|
|
if (strictDbOnly)
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
}
|
|
}
|