Commit 08a8d2c2 authored by ElderLich's avatar ElderLich

Bug Fix: Intermittent cards.cdb load failure shows cards as UNKNOWN on low-spec devices

On mobile and low-end PCs/laptops, the card database sometimes does not fully load (especially during startup or language reload), so valid card IDs resolve as UNKNOWN. Players can temporarily recover by switching UI/card language, restarting, and switching back.
parent 74b04375
...@@ -63,83 +63,55 @@ namespace MDPro3.Duel.YGOSharp ...@@ -63,83 +63,55 @@ namespace MDPro3.Duel.YGOSharp
{ {
nullName = InterString.Get("未知卡片"); nullName = InterString.Get("未知卡片");
nullString = string.Empty; nullString = string.Empty;
; IDictionary<int, Card> previousCards = _cards;
string language = Language.GetConfig(); IDictionary<int, Card> previousRenderCards = _cardsForRender;
string databaseFullPath = Program.PATH_LOCALES + language + "/cards.cdb";
if (!File.Exists(databaseFullPath)) var loadedCards = new Dictionary<int, Card>(Math.Max(previousCards?.Count ?? 0, 16384));
databaseFullPath = Program.PATH_LOCALES + "zh-CN/cards.cdb"; var loadedRenderCards = new Dictionary<int, Card>(Math.Max(previousRenderCards?.Count ?? 0, 16384));
_cards.Clear();
LoadCDB(databaseFullPath); bool loadedMain = TryLoadCardsForLanguage(loadedCards, Language.GetConfig(), render: false);
if (Config.Get("Expansions", "1") == "1") bool loadedRender = TryLoadCardsForLanguage(loadedRenderCards, Language.GetCardConfig(), render: true);
if (!loadedMain || loadedCards.Count == 0)
{ {
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb")) if (string.IsNullOrEmpty(MDPro3.MessageManager.messageFromSubString))
LoadCDB(cdb);
foreach (var zip in ZipHelper.zips)
{ {
if (zip.Name.ToLower().EndsWith("script.zip")) MDPro3.MessageManager.messageFromSubString =
continue; InterString.Get("Failed to load card database. Some cards may be shown as unknown.");
foreach (var file in zip.EntryFileNames)
{
if (file.ToLower().EndsWith(".cdb"))
{
var e = zip[file];
if (!Directory.Exists(Program.PATH_TEMP_FOLDER))
Directory.CreateDirectory(Program.PATH_TEMP_FOLDER);
var tempFile = Path.Combine(Path.GetFullPath(Program.PATH_TEMP_FOLDER), file);
e.Extract(Path.GetFullPath(Program.PATH_TEMP_FOLDER), ExtractExistingFileAction.OverwriteSilently);
LoadCDB(tempFile, isPreCards : Path.GetFileName(zip.Name) == "ygopro-super-pre.ypk" && file.ToLower().StartsWith("test-release"));
File.Delete(tempFile);
}
}
} }
}
UpdateSetNames(); if (previousCards != null && previousCards.Count > 0)
PacksManager.Initialize(); _cards = previousCards;
else
_cards = loadedCards;
_cardsForRender.Clear(); if (previousRenderCards != null && previousRenderCards.Count > 0)
var cardLanguage = Language.GetCardConfig(); _cardsForRender = previousRenderCards;
databaseFullPath = Program.PATH_LOCALES + cardLanguage + "/cards.cdb"; else
if (!File.Exists(databaseFullPath)) _cardsForRender = loadedRenderCards;
databaseFullPath = Program.PATH_LOCALES + "zh-CN/cards.cdb";
LoadCDB(databaseFullPath, true); return;
if (Config.Get("Expansions", "1") == "1") }
if (!loadedRender)
{ {
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb")) if (previousRenderCards != null && previousRenderCards.Count > 0)
LoadCDB(cdb, true); loadedRenderCards = new Dictionary<int, Card>(previousRenderCards);
foreach (var zip in ZipHelper.zips) else
{ loadedRenderCards = new Dictionary<int, Card>(loadedCards);
if (zip.Name.ToLower().EndsWith("script.zip"))
continue;
foreach (var file in zip.EntryFileNames)
{
if (file.ToLower().EndsWith(".cdb"))
{
var e = zip[file];
if (!Directory.Exists(Program.PATH_TEMP_FOLDER))
Directory.CreateDirectory(Program.PATH_TEMP_FOLDER);
var tempFile = Path.Combine(Path.GetFullPath(Program.PATH_TEMP_FOLDER), file);
e.Extract(Path.GetFullPath(Program.PATH_TEMP_FOLDER), ExtractExistingFileAction.OverwriteSilently);
LoadCDB(tempFile, true, isPreCards: Path.GetFileName(zip.Name) == "ygopro-super-pre.ypk");
File.Delete(tempFile);
}
}
}
} }
_cards = loadedCards;
_cardsForRender = loadedRenderCards;
UpdateSetNames();
PacksManager.Initialize();
} }
internal static void LoadCDB(string databaseFullPath, bool render = false, bool isPreCards = false) internal static void LoadCDB(string databaseFullPath, bool render = false, bool isPreCards = false)
{ {
using SqliteConnection connection = new("Data Source=" + databaseFullPath); var targetCards = render ? _cardsForRender : _cards;
connection.Open(); TryLoadCDB(databaseFullPath, targetCards, isPreCards, render, optionalDatabase: false);
using IDbCommand command =
new SqliteCommand("SELECT datas.*, texts.* FROM datas,texts WHERE datas.id=texts.id;", connection);
using IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
LoadCard(reader, render, isPreCards);
}
} }
internal static void UpdateSetNames() internal static void UpdateSetNames()
...@@ -216,26 +188,117 @@ namespace MDPro3.Duel.YGOSharp ...@@ -216,26 +188,117 @@ namespace MDPro3.Duel.YGOSharp
return returnValue; return returnValue;
} }
private static void LoadCard(IDataRecord reader, bool render = false, bool isPreCards = false) private static bool TryLoadCardsForLanguage(IDictionary<int, Card> targetCards, string language, bool render)
{ {
Card card = new(reader) string databaseFullPath = ResolveCardsDatabasePath(language);
if (!TryLoadCDB(databaseFullPath, targetCards, isPreCards: false, render, optionalDatabase: false))
return false;
if (Config.Get("Expansions", "1") != "1")
return true;
foreach (var cdb in Directory.GetFiles("Expansions", "*.cdb"))
TryLoadCDB(cdb, targetCards, isPreCards: false, render, optionalDatabase: true);
foreach (var zip in ZipHelper.zips)
{ {
isPre = isPreCards if (zip.Name.ToLower().EndsWith("script.zip"))
}; continue;
if (!render)
foreach (var file in zip.EntryFileNames)
{
if (!file.ToLower().EndsWith(".cdb"))
continue;
string tempRoot = Path.GetFullPath(Program.PATH_TEMP_FOLDER);
string tempFile = Path.Combine(tempRoot, file);
bool isPreCards = false;
try
{
if (!Directory.Exists(tempRoot))
Directory.CreateDirectory(tempRoot);
zip[file].Extract(tempRoot, ExtractExistingFileAction.OverwriteSilently);
bool fromPrereleasePack = Path.GetFileName(zip.Name)
.Equals("ygopro-super-pre.ypk", StringComparison.OrdinalIgnoreCase);
isPreCards = fromPrereleasePack && (render || file.ToLower().StartsWith("test-release"));
TryLoadCDB(tempFile, targetCards, isPreCards, render, optionalDatabase: true);
}
catch (Exception)
{
}
finally
{
try
{
if (File.Exists(tempFile))
File.Delete(tempFile);
}
catch (Exception)
{
}
}
}
}
return true;
}
private static string ResolveCardsDatabasePath(string language)
{
string databaseFullPath = Program.PATH_LOCALES + language + "/cards.cdb";
if (!File.Exists(databaseFullPath))
databaseFullPath = Program.PATH_LOCALES + Language.SimplifiedChinese + "/cards.cdb";
return databaseFullPath;
}
private static bool TryLoadCDB(
string databaseFullPath,
IDictionary<int, Card> targetCards,
bool isPreCards,
bool render,
bool optionalDatabase)
{
try
{ {
//if (!_cards.ContainsKey(card.Id)) using SqliteConnection connection = new("Data Source=" + databaseFullPath);
// _cards.Add(card.Id, card); connection.Open();
_cards[card.Id] = card;
using IDbCommand command =
new SqliteCommand("SELECT datas.*, texts.* FROM datas,texts WHERE datas.id=texts.id;", connection);
using IDataReader reader = command.ExecuteReader();
while (reader.Read())
{
try
{
LoadCard(reader, targetCards, isPreCards);
}
catch (Exception)
{
}
}
return true;
} }
else catch (Exception)
{ {
//if (!_cardsForRender.ContainsKey(card.Id)) return false;
// _cardsForRender.Add(card.Id, card);
_cardsForRender[card.Id] = card;
} }
} }
private static void LoadCard(IDataRecord reader, IDictionary<int, Card> targetCards, bool isPreCards = false)
{
Card card = new(reader)
{
isPre = isPreCards
};
targetCards[card.Id] = card;
}
public static List<string> GetMiddleStrings(string str, string start, string end) public static List<string> GetMiddleStrings(string str, string start, string end)
{ {
List<string> returnValue = new List<string>(); List<string> returnValue = new List<string>();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment