初步支持导出db_graphics、db_localize、db_scripts、db_sounds内容为sqlite

This commit is contained in:
Chenx221 2024-10-13 21:53:10 +08:00
parent b853aaeffc
commit 1ef8568ba2
4 changed files with 185 additions and 14 deletions

View File

@ -1,4 +1,5 @@
using System.Reflection; using Microsoft.Data.Sqlite;
using System.Reflection;
using System.Text; using System.Text;
namespace EscudeTools namespace EscudeTools
@ -105,8 +106,8 @@ namespace EscudeTools
uint textOffset = BitConverter.ToUInt32(sheet_data, offset); uint textOffset = BitConverter.ToUInt32(sheet_data, offset);
if (sheet_text.Length < textOffset) if (sheet_text.Length < textOffset)
{ {
record.values[j] = textOffset.ToString("X"); //let you go, i will fix you later Console.WriteLine($"Invalid text offset: {textOffset:X}, sheet: {debugInfo1}, recordNum: {i}, type: {j}");
Console.WriteLine($"Invalid text offset: {textOffset:X}, sheet: {debugInfo1}, recordNum: {i}, type: {j}"); //Not Supported, May be a script specific value throw new Exception("Invalid text offset"); //应该不会再发生这种情况了
} }
else else
{ {
@ -148,13 +149,22 @@ namespace EscudeTools
switch (outputType) switch (outputType)
{ {
case 0: //sqlite case 0: //sqlite
return SqliteProcess(db, Path.Combine(storePath, dbName + ".sqlite")); string targetFile = Path.Combine(storePath, dbName + ".db");
ExtractEmbeddedDatabase(targetFile);
return SqliteProcess(db, targetFile);
case 1: //csv case 1: //csv
foreach (var s in db) foreach (var s in db)
{ {
bool status = CsvProcess(s, Path.Combine(storePath, dbName + "_" + s.name + ".csv")); bool status = CsvProcess(s, Path.Combine(storePath, dbName + "_" + s.name + ".csv"));
if (!status) if (!status)
throw new IOException($"Failed to export sheet: {s.name}"); {
throw new IOException($"Failed to export {s.name} CSV file.");
}
else
{
Console.WriteLine($"{s.name} CSV file exported successfully.");
}
} }
return true; return true;
default: default:
@ -162,12 +172,155 @@ namespace EscudeTools
} }
} }
private bool SqliteProcess(Sheet[] db, string path) private static void ExtractEmbeddedDatabase(string outputPath)
{ {
if (File.Exists(outputPath))
{
Console.WriteLine($"File {outputPath} already exists. Do you want to overwrite it? (y/n)");
string? input = Console.ReadLine();
if (input?.ToLower() != "y")
{
Console.WriteLine("Task cancelled, Exporting database aborted.");
return;
}
}
var assembly = Assembly.GetExecutingAssembly();
//foreach (var rn in assembly.GetManifestResourceNames())
//{
// Console.WriteLine(rn);
//}
string resourceName = "EscudeTools.empty.db";
using Stream stream = assembly.GetManifestResourceStream(resourceName) ?? throw new Exception($"Error, No resource with name {resourceName} found.");
using FileStream fileStream = new(outputPath, FileMode.Create, FileAccess.Write);
stream.CopyTo(fileStream);
}
private static bool SqliteProcess(Sheet[] db, string path)
{
//db含有多个sheet每个sheet中col存放标题对应数据库中应该是字段records存放数据对应数据库中应该是记录
using (SqliteConnection connection = new($"Data Source={path};"))
{
connection.Open();
foreach (var sheet in db)
{
using (SqliteCommand createTableCommand = connection.CreateCommand())
{
StringBuilder createTableQuery = new();
createTableQuery.Append($"CREATE TABLE IF NOT EXISTS {sheet.name} (");
// Add columns to the create table query
foreach (var column in sheet.col)
{
createTableQuery.Append($"{column.name} {GetSQLiteColumnType(column.type)}, ");
}
createTableQuery.Remove(createTableQuery.Length - 2, 2); // Remove the last comma and space
createTableQuery.Append(");");
createTableCommand.CommandText = createTableQuery.ToString();
createTableCommand.ExecuteNonQuery();
}
using SqliteCommand insertDataCommand = connection.CreateCommand();
StringBuilder insertDataQuery = new();
insertDataQuery.Append($"INSERT INTO {sheet.name} (");
// Add column names to the insert data query
foreach (var column in sheet.col)
{
insertDataQuery.Append($"{column.name}, ");
}
insertDataQuery.Remove(insertDataQuery.Length - 2, 2); // Remove the last comma and space
insertDataQuery.Append(") VALUES (");
// Add parameter placeholders to the insert data query
for (int i = 0; i < sheet.cols; i++)
{
insertDataQuery.Append($"@param{i}, ");
}
insertDataQuery.Remove(insertDataQuery.Length - 2, 2); // Remove the last comma and space
insertDataQuery.Append(");");
insertDataCommand.CommandText = insertDataQuery.ToString();
// Add data parameters to the insert data command
for (int i = 0; i < sheet.records.values.Length; i++)
{
var record = (Record)sheet.records.values[i];
for (int j = 0; j < sheet.cols; j++)
{
var parameter = new SqliteParameter($"@param{j}", record.values[j]);
insertDataCommand.Parameters.Add(parameter);
}
insertDataCommand.ExecuteNonQuery();
insertDataCommand.Parameters.Clear();
}
}
}
return true;
//throw new NotImplementedException();
}
private static string GetSQLiteColumnType(ushort type)
{
return type switch
{
// int
0x1 => "INTEGER",
// float
0x2 => "REAL",
// string
0x3 => "TEXT",
// bool
0x4 => "INTEGER",
_ => throw new NotSupportedException($"Unsupported column type: {type}"),
};
throw new NotImplementedException(); throw new NotImplementedException();
} }
private bool CsvProcess(Sheet s, string path) private static bool CsvProcess(Sheet s, string path)
{ {
//s是单张表col存放标题对应csv应该是标题records存放数据对应数据库中应该是数据
if (string.IsNullOrEmpty(path))
throw new ArgumentException("File path cannot be null or empty.", nameof(path));
// 创建一个StringBuilder来构建CSV内容
StringBuilder csvContent = new();
// 写入列标题
foreach (Column column in s.col)
{
csvContent.Append(column.name);
csvContent.Append(',');
}
csvContent.AppendLine(); // 换行
// 写入记录数据
foreach (Record record in s.records.values.Cast<Record>())
{
foreach (object value in record.values)
{
csvContent.Append(value);
csvContent.Append(',');
}
csvContent.AppendLine(); // 换行
}
// 将CSV内容写入文件
try
{
File.WriteAllText(path, csvContent.ToString());
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Failed to export CSV file: {ex.Message}");
return false;
}
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }

View File

@ -7,11 +7,21 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Remove="empty.db" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="14.0.0" /> <PackageReference Include="Magick.NET-Q16-AnyCPU" Version="14.0.0" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.10" /> <PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.10" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" /> <PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="System.Threading.Tasks" Version="4.3.0" /> <PackageReference Include="System.Threading.Tasks" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="empty.db">
<CopyToOutputDirectory></CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project> </Project>

View File

@ -10,16 +10,24 @@
DatabaseManager dm = new(); DatabaseManager dm = new();
foreach (string file in files) foreach (string file in files)
{ {
if (!dm.LoadDatabase(file)) if (dm.LoadDatabase(file))
{ {
Console.WriteLine($"Failed to load {file}"); Console.WriteLine($"Load {file} Success");
}
else
{
Console.WriteLine($"Load {file} Failed");
return;
}
if (dm.ExportDatabase(0, Path.GetDirectoryName(args[0])))
Console.WriteLine("Export Database Success");
else
{
Console.WriteLine("Export Database Failed");
return; return;
} }
//if (dm.ExportDatabase(0, Path.GetDirectoryName(args[0])))
// Console.WriteLine("Export Database Success");
//else
// Console.WriteLine("Export Database Failed");
} }
} }

BIN
EscudeTools/empty.db Normal file

Binary file not shown.