From 2e784ba8a571a6c4f898fe5b01ceb9820b89b34e Mon Sep 17 00:00:00 2001 From: CheapManga Date: Sun, 30 Aug 2026 11:08:40 +0200 Subject: [PATCH] Add page: offer the game's fixes right after a Fetch Fetching a game showed its manifest sources and stopped there, even when the game had published fixes a page away. A Fetch now also looks the game up in the fix listing and, when there is one, the page shows a banner naming what is waiting - "This game has 2 fix(es) available: SteamTools Achievements Fix, voices38 (crack)" - with a button that opens the Fixes page on that game. The kinds are named on purpose. The listing endpoint is called /api/denuvo/listings, but of the 1759 games it returns, 1621 are tagged "Online Fix" and no tag named "Denuvo" exists at all, so calling them Denuvo fixes would be wrong nearly every time. The tags come from the same field the Fixes page already renders as pills; a game whose fixes carry no tag falls back to a plain sentence. - FixLookupService loads the listing once per session and keeps an appid -> summary map, so the check costs nothing after the first lookup. A failed load isn't cached and shows no banner: it is never an error. - The lookup runs alongside the source check, not before it. Whether a fix exists has no bearing on fetching manifests, and the fetch shouldn't wait. - A result that lands after the user moved to another game is dropped, so the banner can't advertise the previous game's fixes. - Games only: a DLC's fetch is about its depots, and a fix belongs to the base game. - Both wordings are translated in all 29 languages. --- src/LuaToolsGui/App.xaml.cs | 8 +++ src/LuaToolsGui/Resources/Strings.Designer.cs | 3 + src/LuaToolsGui/Resources/Strings.ar.resx | 3 + src/LuaToolsGui/Resources/Strings.bg.resx | 3 + src/LuaToolsGui/Resources/Strings.cs.resx | 3 + src/LuaToolsGui/Resources/Strings.da.resx | 3 + src/LuaToolsGui/Resources/Strings.de.resx | 3 + src/LuaToolsGui/Resources/Strings.el.resx | 3 + src/LuaToolsGui/Resources/Strings.es-419.resx | 3 + src/LuaToolsGui/Resources/Strings.es.resx | 3 + src/LuaToolsGui/Resources/Strings.fi.resx | 3 + src/LuaToolsGui/Resources/Strings.fr.resx | 3 + src/LuaToolsGui/Resources/Strings.hu.resx | 3 + src/LuaToolsGui/Resources/Strings.id.resx | 3 + src/LuaToolsGui/Resources/Strings.it.resx | 3 + src/LuaToolsGui/Resources/Strings.ja.resx | 3 + src/LuaToolsGui/Resources/Strings.ko.resx | 3 + src/LuaToolsGui/Resources/Strings.nb.resx | 3 + src/LuaToolsGui/Resources/Strings.nl.resx | 3 + src/LuaToolsGui/Resources/Strings.pl.resx | 3 + src/LuaToolsGui/Resources/Strings.pt-BR.resx | 3 + src/LuaToolsGui/Resources/Strings.pt-PT.resx | 3 + src/LuaToolsGui/Resources/Strings.resx | 3 + src/LuaToolsGui/Resources/Strings.ro.resx | 3 + src/LuaToolsGui/Resources/Strings.ru.resx | 3 + src/LuaToolsGui/Resources/Strings.sv.resx | 3 + src/LuaToolsGui/Resources/Strings.th.resx | 3 + src/LuaToolsGui/Resources/Strings.tr.resx | 3 + src/LuaToolsGui/Resources/Strings.uk.resx | 3 + src/LuaToolsGui/Resources/Strings.vi.resx | 3 + .../Resources/Strings.zh-Hans.resx | 3 + .../Resources/Strings.zh-Hant.resx | 3 + src/LuaToolsGui/Services/FixLookupService.cs | 69 ++++++++++++++++++ .../ViewModels/DownloadViewModel.cs | 71 ++++++++++++++++++- src/LuaToolsGui/Views/DownloadView.xaml | 36 ++++++++++ 35 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 src/LuaToolsGui/Services/FixLookupService.cs diff --git a/src/LuaToolsGui/App.xaml.cs b/src/LuaToolsGui/App.xaml.cs index 41374c1..8197e09 100644 --- a/src/LuaToolsGui/App.xaml.cs +++ b/src/LuaToolsGui/App.xaml.cs @@ -28,6 +28,7 @@ public App() services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); @@ -375,6 +376,13 @@ protected override async void OnStartup(StartupEventArgs e) _host.Services.GetRequiredService().RevealItem = _ => window.NavigateToAdd(); download.NavigateToGame = openInManage; + + // Add page → the post-fetch "this game has a fix" banner opens it straight in the Fixes page. + download.OpenFixesForGame = appId => Dispatcher.Invoke(() => + { + window.NavigateToFixes(); + _ = _host.Services.GetRequiredService().OpenForAppIdAsync(appId); + }); builds.NavigateToManage = openInManage; // Builds "Manage" button: the reverse of "Manage Build" // Depot download queues one item covering the whole selection; show the user where it went. builds.RequestShowDownloads = () => Dispatcher.Invoke(window.NavigateToDownloads); diff --git a/src/LuaToolsGui/Resources/Strings.Designer.cs b/src/LuaToolsGui/Resources/Strings.Designer.cs index 199186b..4240dd5 100644 --- a/src/LuaToolsGui/Resources/Strings.Designer.cs +++ b/src/LuaToolsGui/Resources/Strings.Designer.cs @@ -340,6 +340,9 @@ public static class Strings public static string Add_FastFetch_Hint => Get(nameof(Add_FastFetch_Hint)); public static string Add_FastFetch_NoSource => Get(nameof(Add_FastFetch_NoSource)); public static string Add_FastFetch_Via => Get(nameof(Add_FastFetch_Via)); + public static string Add_Fix_Available => Get(nameof(Add_Fix_Available)); + public static string Add_Fix_Available_Tags => Get(nameof(Add_Fix_Available_Tags)); + public static string Add_Fix_Open => Get(nameof(Add_Fix_Open)); // ── Confirm overlay ── public static string Confirm_OpenSteamDb => Get(nameof(Confirm_OpenSteamDb)); diff --git a/src/LuaToolsGui/Resources/Strings.ar.resx b/src/LuaToolsGui/Resources/Strings.ar.resx index 8bb97b8..dcabaa8 100644 --- a/src/LuaToolsGui/Resources/Strings.ar.resx +++ b/src/LuaToolsGui/Resources/Strings.ar.resx @@ -396,6 +396,9 @@ التنزيل التلقائي من أول مصدر متاح لم يتم العثور على مصادر متاحة لهذه اللعبة · عبر {0} + تتوفر لهذه اللعبة {0} إصلاح. + تتوفر لهذه اللعبة {0} إصلاح: {1}. + عرض الإصلاحات إضافة LuaTools إضافة LuaTools لمتجر Steam! — تستخدم الآن LuaLoader بدلًا من Shittenium الحالة diff --git a/src/LuaToolsGui/Resources/Strings.bg.resx b/src/LuaToolsGui/Resources/Strings.bg.resx index bf12f47..9a4cd59 100644 --- a/src/LuaToolsGui/Resources/Strings.bg.resx +++ b/src/LuaToolsGui/Resources/Strings.bg.resx @@ -370,6 +370,9 @@ Автоматично изтегляне от първия наличен източник Няма намерени налични източници за тази игра · чрез {0} + Тази игра има налични корекции: {0}. + Тази игра има налични корекции: {0} ({1}). + Виж корекциите LuaTools плъгин Плъгинът LuaTools за Steam! — Вече използва LuaLoader вместо Shittenium Състояние diff --git a/src/LuaToolsGui/Resources/Strings.cs.resx b/src/LuaToolsGui/Resources/Strings.cs.resx index 1163975..1ae55ab 100644 --- a/src/LuaToolsGui/Resources/Strings.cs.resx +++ b/src/LuaToolsGui/Resources/Strings.cs.resx @@ -370,6 +370,9 @@ Tím se smažou soubory .lua ze Steam\config\stplug-in. Automatické stažení z prvního dostupného zdroje Pro tuto hru nebyly nalezeny žádné dostupné zdroje · přes {0} + Pro tuto hru jsou k dispozici opravy: {0}. + Pro tuto hru jsou k dispozici opravy: {0} ({1}). + Zobrazit opravy Plugin LuaTools Plugin LuaTools pro Steam! — Nyní používá LuaLoader místo Shittenium Stav diff --git a/src/LuaToolsGui/Resources/Strings.da.resx b/src/LuaToolsGui/Resources/Strings.da.resx index 57129a4..bcc999b 100644 --- a/src/LuaToolsGui/Resources/Strings.da.resx +++ b/src/LuaToolsGui/Resources/Strings.da.resx @@ -370,6 +370,9 @@ Dette sletter .lua-filerne fra Steam\config\stplug-in. Automatisk download fra den første tilgængelige kilde Ingen tilgængelige kilder fundet til dette spil · via {0} + Dette spil har {0} rettelser tilgængelige. + Dette spil har {0} rettelser tilgængelige: {1}. + Se rettelser LuaTools-plugin LuaTools Steam-pluginet! — Bruger nu LuaLoader i stedet for Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.de.resx b/src/LuaToolsGui/Resources/Strings.de.resx index 3054c0d..3c44a29 100644 --- a/src/LuaToolsGui/Resources/Strings.de.resx +++ b/src/LuaToolsGui/Resources/Strings.de.resx @@ -370,6 +370,9 @@ Dies löscht die .lua-Dateien aus Steam\config\stplug-in. Automatisch von der ersten verfügbaren Quelle herunterladen Keine verfügbaren Quellen für dieses Spiel gefunden · über {0} + Für dieses Spiel gibt es {0} Fixes. + Für dieses Spiel gibt es {0} Fixes: {1}. + Fixes ansehen LuaTools-Plugin Das LuaTools-Steam-Plugin! — Nutzt jetzt LuaLoader statt Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.el.resx b/src/LuaToolsGui/Resources/Strings.el.resx index 4850027..1e88776 100644 --- a/src/LuaToolsGui/Resources/Strings.el.resx +++ b/src/LuaToolsGui/Resources/Strings.el.resx @@ -370,6 +370,9 @@ Αυτόματη λήψη από την πρώτη διαθέσιμη πηγή Δεν βρέθηκαν διαθέσιμες πηγές για αυτό το παιχνίδι · μέσω {0} + Αυτό το παιχνίδι έχει διαθέσιμες διορθώσεις: {0}. + Αυτό το παιχνίδι έχει διαθέσιμες διορθώσεις: {0} ({1}). + Δες τις διορθώσεις Πρόσθετο LuaTools Το πρόσθετο LuaTools για το Steam! — Χρησιμοποιεί πλέον LuaLoader αντί για Shittenium Κατάσταση diff --git a/src/LuaToolsGui/Resources/Strings.es-419.resx b/src/LuaToolsGui/Resources/Strings.es-419.resx index 9f24190..0a17ffc 100644 --- a/src/LuaToolsGui/Resources/Strings.es-419.resx +++ b/src/LuaToolsGui/Resources/Strings.es-419.resx @@ -370,6 +370,9 @@ Esto elimina los archivos .lua de Steam\config\stplug-in. Descargar automáticamente desde la primera fuente disponible No se encontraron fuentes disponibles para este juego · a través de {0} + Este juego tiene {0} parche(s) disponible(s). + Este juego tiene {0} parche(s) disponible(s): {1}. + Ver parches Complemento LuaTools ¡El plugin de LuaTools para Steam! — Ahora usa LuaLoader en vez de Shittenium Estado diff --git a/src/LuaToolsGui/Resources/Strings.es.resx b/src/LuaToolsGui/Resources/Strings.es.resx index f49178d..577fced 100644 --- a/src/LuaToolsGui/Resources/Strings.es.resx +++ b/src/LuaToolsGui/Resources/Strings.es.resx @@ -370,6 +370,9 @@ Esto elimina los archivos .lua de Steam\config\stplug-in. Descargar automáticamente desde la primera fuente disponible No se encontraron fuentes disponibles para este juego · a través de {0} + Este juego tiene {0} parche(s) disponible(s). + Este juego tiene {0} parche(s) disponible(s): {1}. + Ver parches Complemento LuaTools ¡El plugin de LuaTools para Steam! — Ahora usa LuaLoader en lugar de Shittenium Estado diff --git a/src/LuaToolsGui/Resources/Strings.fi.resx b/src/LuaToolsGui/Resources/Strings.fi.resx index 98f667a..4b33ba2 100644 --- a/src/LuaToolsGui/Resources/Strings.fi.resx +++ b/src/LuaToolsGui/Resources/Strings.fi.resx @@ -370,6 +370,9 @@ Tämä poistaa .lua-tiedostot kansiosta Steam\config\stplug-in. Automaattinen lataus ensimmäisestä saatavilla olevasta lähteestä Tälle pelille ei löytynyt saatavilla olevia lähteitä · kautta {0} + Tälle pelille on saatavilla {0} korjausta. + Tälle pelille on saatavilla {0} korjausta: {1}. + Näytä korjaukset LuaTools-laajennus LuaTools-Steam-laajennus! — Käyttää nyt LuaLoaderia Shitteniumin sijaan Tila diff --git a/src/LuaToolsGui/Resources/Strings.fr.resx b/src/LuaToolsGui/Resources/Strings.fr.resx index 9bd3003..d1b320f 100644 --- a/src/LuaToolsGui/Resources/Strings.fr.resx +++ b/src/LuaToolsGui/Resources/Strings.fr.resx @@ -370,6 +370,9 @@ Cela supprime les fichiers .lua de Steam\config\stplug-in. Téléchargement automatique depuis la première source disponible Aucune source disponible pour ce jeu · via {0} + Ce jeu a {0} correctif(s) disponible(s). + Ce jeu a {0} correctif(s) disponible(s) : {1}. + Voir les correctifs Extension LuaTools Le plugin LuaTools pour Steam ! — Utilise désormais LuaLoader au lieu de Shittenium État diff --git a/src/LuaToolsGui/Resources/Strings.hu.resx b/src/LuaToolsGui/Resources/Strings.hu.resx index 184a58e..cb27588 100644 --- a/src/LuaToolsGui/Resources/Strings.hu.resx +++ b/src/LuaToolsGui/Resources/Strings.hu.resx @@ -370,6 +370,9 @@ Ez törli a .lua fájlokat a Steam\config\stplug-in mappából. Automatikus letöltés az első elérhető forrásból Nem található elérhető forrás ehhez a játékhoz · innen: {0} + Ehhez a játékhoz {0} javítás érhető el. + Ehhez a játékhoz {0} javítás érhető el: {1}. + Javítások megtekintése LuaTools bővítmény A LuaTools Steam bővítmény! — Mostantól LuaLoader a Shittenium helyett Állapot diff --git a/src/LuaToolsGui/Resources/Strings.id.resx b/src/LuaToolsGui/Resources/Strings.id.resx index 2bff851..7e4f05c 100644 --- a/src/LuaToolsGui/Resources/Strings.id.resx +++ b/src/LuaToolsGui/Resources/Strings.id.resx @@ -370,6 +370,9 @@ Ini menghapus berkas .lua dari Steam\config\stplug-in. Unduh otomatis dari sumber pertama yang tersedia Tidak ada sumber tersedia yang ditemukan untuk game ini · melalui {0} + Game ini punya {0} perbaikan. + Game ini punya {0} perbaikan: {1}. + Lihat perbaikan Plugin LuaTools Plugin LuaTools untuk Steam! — Kini memakai LuaLoader alih-alih Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.it.resx b/src/LuaToolsGui/Resources/Strings.it.resx index 3d89b23..1c85302 100644 --- a/src/LuaToolsGui/Resources/Strings.it.resx +++ b/src/LuaToolsGui/Resources/Strings.it.resx @@ -370,6 +370,9 @@ Questo elimina i file .lua da Steam\config\stplug-in. Scarica automaticamente dalla prima fonte disponibile Nessuna fonte disponibile trovata per questo gioco · tramite {0} + Questo gioco ha {0} fix disponibili. + Questo gioco ha {0} fix disponibili: {1}. + Vedi i fix Plugin LuaTools Il plugin LuaTools per Steam! — Ora usa LuaLoader invece di Merdennium Stato diff --git a/src/LuaToolsGui/Resources/Strings.ja.resx b/src/LuaToolsGui/Resources/Strings.ja.resx index f59f34d..49a55a1 100644 --- a/src/LuaToolsGui/Resources/Strings.ja.resx +++ b/src/LuaToolsGui/Resources/Strings.ja.resx @@ -370,6 +370,9 @@ Steam\config\stplug-in から .lua ファイルを削除します。最初の利用可能なソースから自動ダウンロード このゲームで利用可能なソースが見つかりません · ソース:{0} + このゲームには {0} 件の修正があります。 + このゲームには {0} 件の修正があります:{1} + 修正を見る LuaTools プラグイン LuaTools の Steam プラグイン! — Shittenium に代わり LuaLoader を使用 ステータス diff --git a/src/LuaToolsGui/Resources/Strings.ko.resx b/src/LuaToolsGui/Resources/Strings.ko.resx index a2294a5..600f4b1 100644 --- a/src/LuaToolsGui/Resources/Strings.ko.resx +++ b/src/LuaToolsGui/Resources/Strings.ko.resx @@ -370,6 +370,9 @@ Steam\config\stplug-in에서 .lua 파일을 삭제합니다. 사용 가능한 첫 번째 소스에서 자동 다운로드 이 게임에 사용 가능한 소스를 찾을 수 없습니다 · 출처: {0} + 이 게임에는 수정 {0}개가 있습니다. + 이 게임에는 수정 {0}개가 있습니다: {1} + 수정 보기 LuaTools 플러그인 LuaTools Steam 플러그인! — 이제 Shittenium 대신 LuaLoader 사용 상태 diff --git a/src/LuaToolsGui/Resources/Strings.nb.resx b/src/LuaToolsGui/Resources/Strings.nb.resx index 5c61f94..411346c 100644 --- a/src/LuaToolsGui/Resources/Strings.nb.resx +++ b/src/LuaToolsGui/Resources/Strings.nb.resx @@ -370,6 +370,9 @@ Dette sletter .lua-filene fra Steam\config\stplug-in. Automatisk nedlasting fra første tilgjengelige kilde Ingen tilgjengelige kilder funnet for dette spillet · via {0} + Dette spillet har {0} fikser tilgjengelig. + Dette spillet har {0} fikser tilgjengelig: {1}. + Se fikser LuaTools-programtillegg LuaTools Steam-programtillegget! — Bruker nå LuaLoader i stedet for Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.nl.resx b/src/LuaToolsGui/Resources/Strings.nl.resx index 1821279..1b9c17d 100644 --- a/src/LuaToolsGui/Resources/Strings.nl.resx +++ b/src/LuaToolsGui/Resources/Strings.nl.resx @@ -370,6 +370,9 @@ Dit verwijdert de .lua-bestanden uit Steam\config\stplug-in. Automatisch downloaden van de eerste beschikbare bron Geen beschikbare bronnen gevonden voor dit spel · via {0} + Voor dit spel zijn {0} fixes beschikbaar. + Voor dit spel zijn {0} fixes beschikbaar: {1}. + Fixes bekijken LuaTools-plug-in De LuaTools Steam-plugin! — Gebruikt nu LuaLoader in plaats van Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.pl.resx b/src/LuaToolsGui/Resources/Strings.pl.resx index cfd84fa..2021b97 100644 --- a/src/LuaToolsGui/Resources/Strings.pl.resx +++ b/src/LuaToolsGui/Resources/Strings.pl.resx @@ -370,6 +370,9 @@ Spowoduje to usunięcie plików .lua z Steam\config\stplug-in. Automatyczne pobieranie z pierwszego dostępnego źródła Nie znaleziono dostępnych źródeł dla tej gry · przez {0} + Ta gra ma dostępne poprawki: {0}. + Ta gra ma dostępne poprawki: {0} ({1}). + Zobacz poprawki Wtyczka LuaTools Wtyczka LuaTools do Steam! — Teraz używa LuaLoader zamiast Shittenium Stan diff --git a/src/LuaToolsGui/Resources/Strings.pt-BR.resx b/src/LuaToolsGui/Resources/Strings.pt-BR.resx index c5801cd..363c2ca 100644 --- a/src/LuaToolsGui/Resources/Strings.pt-BR.resx +++ b/src/LuaToolsGui/Resources/Strings.pt-BR.resx @@ -370,6 +370,9 @@ Isso exclui os arquivos .lua de Steam\config\stplug-in. Baixar automaticamente da primeira fonte disponível Nenhuma fonte disponível encontrada para este jogo · via {0} + Este jogo tem {0} correção(ões) disponível(is). + Este jogo tem {0} correção(ões) disponível(is): {1}. + Ver correções Plugin LuaTools O plugin LuaTools para Steam! — Agora usando LuaLoader em vez de Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.pt-PT.resx b/src/LuaToolsGui/Resources/Strings.pt-PT.resx index 0835d98..8388142 100644 --- a/src/LuaToolsGui/Resources/Strings.pt-PT.resx +++ b/src/LuaToolsGui/Resources/Strings.pt-PT.resx @@ -370,6 +370,9 @@ Isto elimina os ficheiros .lua de Steam\config\stplug-in. Transferir automaticamente da primeira fonte disponível Nenhuma fonte disponível encontrada para este jogo · via {0} + Este jogo tem {0} correção(ões) disponível(is). + Este jogo tem {0} correção(ões) disponível(is): {1}. + Ver correções Plugin LuaTools O plugin LuaTools para Steam! — Agora a usar LuaLoader em vez de Shittenium Estado diff --git a/src/LuaToolsGui/Resources/Strings.resx b/src/LuaToolsGui/Resources/Strings.resx index 340b033..39d1c0d 100644 --- a/src/LuaToolsGui/Resources/Strings.resx +++ b/src/LuaToolsGui/Resources/Strings.resx @@ -392,6 +392,9 @@ This deletes the .lua files from Steam\config\stplug-in. Auto-download from the first available source No available sources found for this game · via {0} + This game has {0} fix(es) available. + This game has {0} fix(es) available: {1}. + See fixes Open on SteamDB diff --git a/src/LuaToolsGui/Resources/Strings.ro.resx b/src/LuaToolsGui/Resources/Strings.ro.resx index 5c8d6c8..5997760 100644 --- a/src/LuaToolsGui/Resources/Strings.ro.resx +++ b/src/LuaToolsGui/Resources/Strings.ro.resx @@ -370,6 +370,9 @@ Aceasta șterge fișierele .lua din Steam\config\stplug-in. Descărcare automată de la prima sursă disponibilă Nu s-au găsit surse disponibile pentru acest joc · prin {0} + Acest joc are {0} remedieri disponibile. + Acest joc are {0} remedieri disponibile: {1}. + Vezi remedierile Plugin LuaTools Pluginul LuaTools pentru Steam! — Acum folosește LuaLoader în loc de Shittenium Stare diff --git a/src/LuaToolsGui/Resources/Strings.ru.resx b/src/LuaToolsGui/Resources/Strings.ru.resx index e43eb9c..67e5ba6 100644 --- a/src/LuaToolsGui/Resources/Strings.ru.resx +++ b/src/LuaToolsGui/Resources/Strings.ru.resx @@ -370,6 +370,9 @@ Автоматическая загрузка из первого доступного источника Для этой игры не найдено доступных источников · через {0} + Для этой игры есть фиксы: {0}. + Для этой игры есть фиксы: {0} ({1}). + Открыть фиксы Плагин LuaTools Плагин LuaTools для Steam! — Теперь использует LuaLoader вместо Shittenium Статус diff --git a/src/LuaToolsGui/Resources/Strings.sv.resx b/src/LuaToolsGui/Resources/Strings.sv.resx index 4ea7e47..497b532 100644 --- a/src/LuaToolsGui/Resources/Strings.sv.resx +++ b/src/LuaToolsGui/Resources/Strings.sv.resx @@ -370,6 +370,9 @@ Detta raderar .lua-filerna från Steam\config\stplug-in. Automatisk nedladdning från första tillgängliga källan Inga tillgängliga källor hittades för detta spel · via {0} + Det här spelet har {0} fixar tillgängliga. + Det här spelet har {0} fixar tillgängliga: {1}. + Visa fixar LuaTools-tillägg LuaTools Steam-tillägget! — Använder nu LuaLoader istället för Shittenium Status diff --git a/src/LuaToolsGui/Resources/Strings.th.resx b/src/LuaToolsGui/Resources/Strings.th.resx index f45496a..a2fe794 100644 --- a/src/LuaToolsGui/Resources/Strings.th.resx +++ b/src/LuaToolsGui/Resources/Strings.th.resx @@ -370,6 +370,9 @@ ดาวน์โหลดอัตโนมัติจากแหล่งแรกที่พร้อมใช้งาน ไม่พบแหล่งที่พร้อมใช้งานสำหรับเกมนี้ · ผ่าน {0} + เกมนี้มีการแก้ไข {0} รายการ + เกมนี้มีการแก้ไข {0} รายการ: {1} + ดูการแก้ไข ปลั๊กอิน LuaTools ปลั๊กอิน LuaTools สำหรับ Steam! — ตอนนี้ใช้ LuaLoader แทน Shittenium สถานะ diff --git a/src/LuaToolsGui/Resources/Strings.tr.resx b/src/LuaToolsGui/Resources/Strings.tr.resx index bfeb407..5b2e816 100644 --- a/src/LuaToolsGui/Resources/Strings.tr.resx +++ b/src/LuaToolsGui/Resources/Strings.tr.resx @@ -370,6 +370,9 @@ Bu, .lua dosyalarını Steam\config\stplug-in konumundan siler. İlk kullanılabilir kaynaktan otomatik indir Bu oyun için kullanılabilir kaynak bulunamadı · {0} aracılığıyla + Bu oyun için {0} düzeltme mevcut. + Bu oyun için {0} düzeltme mevcut: {1}. + Düzeltmeleri gör LuaTools Eklentisi LuaTools Steam eklentisi! — Artık Shittenium yerine LuaLoader kullanıyor Durum diff --git a/src/LuaToolsGui/Resources/Strings.uk.resx b/src/LuaToolsGui/Resources/Strings.uk.resx index 8e9a528..e0a9d23 100644 --- a/src/LuaToolsGui/Resources/Strings.uk.resx +++ b/src/LuaToolsGui/Resources/Strings.uk.resx @@ -370,6 +370,9 @@ Автоматичне завантаження з першого доступного джерела Для цієї гри не знайдено доступних джерел · через {0} + Для цієї гри є фікси: {0}. + Для цієї гри є фікси: {0} ({1}). + Відкрити фікси Плагін LuaTools Плагін LuaTools для Steam! — Тепер використовує LuaLoader замість Shittenium Статус diff --git a/src/LuaToolsGui/Resources/Strings.vi.resx b/src/LuaToolsGui/Resources/Strings.vi.resx index e8ce5f5..e1d424f 100644 --- a/src/LuaToolsGui/Resources/Strings.vi.resx +++ b/src/LuaToolsGui/Resources/Strings.vi.resx @@ -370,6 +370,9 @@ Thao tác này xóa các tệp .lua khỏi Steam\config\stplug-in.Tự động tải xuống từ nguồn có sẵn đầu tiên Không tìm thấy nguồn khả dụng cho trò chơi này · qua {0} + Trò chơi này có {0} bản sửa lỗi. + Trò chơi này có {0} bản sửa lỗi: {1}. + Xem bản sửa lỗi Plugin LuaTools Plugin LuaTools cho Steam! — Giờ đây dùng LuaLoader thay cho Shittenium Trạng thái diff --git a/src/LuaToolsGui/Resources/Strings.zh-Hans.resx b/src/LuaToolsGui/Resources/Strings.zh-Hans.resx index 39890c0..d9f91c3 100644 --- a/src/LuaToolsGui/Resources/Strings.zh-Hans.resx +++ b/src/LuaToolsGui/Resources/Strings.zh-Hans.resx @@ -390,6 +390,9 @@ 自动从首个可用源下载 未找到此游戏的可用源 · 来源:{0} + 这款游戏有 {0} 个修复可用。 + 这款游戏有 {0} 个修复可用:{1} + 查看修复 LuaTools 插件 LuaTools 的 Steam 插件! — 现已改用 LuaLoader 代替 Shittenium 状态 diff --git a/src/LuaToolsGui/Resources/Strings.zh-Hant.resx b/src/LuaToolsGui/Resources/Strings.zh-Hant.resx index 0d70526..893b7e0 100644 --- a/src/LuaToolsGui/Resources/Strings.zh-Hant.resx +++ b/src/LuaToolsGui/Resources/Strings.zh-Hant.resx @@ -370,6 +370,9 @@ 自動從首個可用來源下載 未找到此遊戲的可用來源 · 來源:{0} + 這款遊戲有 {0} 個修正可用。 + 這款遊戲有 {0} 個修正可用:{1} + 查看修正 LuaTools 外掛 LuaTools 的 Steam 外掛! — 現已改用 LuaLoader 取代 Shittenium 狀態 diff --git a/src/LuaToolsGui/Services/FixLookupService.cs b/src/LuaToolsGui/Services/FixLookupService.cs new file mode 100644 index 0000000..58b9e02 --- /dev/null +++ b/src/LuaToolsGui/Services/FixLookupService.cs @@ -0,0 +1,69 @@ +namespace LuaToolsGui.Services; + +/// What the fix listing knows about one game: how many fixes, and what kind they are. +/// +/// The fixes' categories as the listing names them ("Online Fix", "Ubisoft", …). Worth showing, +/// because the endpoint is called "denuvo" but the listing is overwhelmingly not: of the games it +/// returns, the vast majority are Online Fixes and no tag named "Denuvo" exists at all. +/// +public record GameFixSummary(int Count, IReadOnlyList Tags); + +/// +/// Answers one question for the Add page: does this game have fixes, how many, and of what kind? +/// +/// +/// The listing endpoint returns every game that has a fix in one shot, so it is fetched once per +/// session and kept as an appid → summary map. That keeps "did the game I just fetched have a fix?" +/// free after the first lookup, instead of a per-game request while the user types. +/// +/// +/// +/// Best-effort by design: no listing (offline, API down) means no banner, never an error. A failed +/// load isn't cached, so the next lookup tries again. +/// +/// +public class FixLookupService(LuaToolsApiClient api) +{ + private readonly SemaphoreSlim _gate = new(1, 1); + private IReadOnlyDictionary? _summaries; + + /// What the listing has for this appid, or null when it has nothing for it — which also + /// covers "the listing couldn't be loaded" (the caller can't tell, and doesn't need to). + public async Task GetFixSummaryAsync(long appId, CancellationToken ct = default) + { + var summaries = await EnsureLoadedAsync(ct); + return summaries is not null && summaries.TryGetValue(appId, out var summary) ? summary : null; + } + + private async Task?> EnsureLoadedAsync(CancellationToken ct) + { + if (_summaries is not null) return _summaries; + + await _gate.WaitAsync(ct); + try + { + if (_summaries is not null) return _summaries; // won the race elsewhere + + var listing = await api.GetDenuvoListingsAsync(ct); + if (listing is null) return null; // don't cache a failure. Retry on the next lookup + + var summaries = new Dictionary(); + foreach (var game in listing.Games) + if (long.TryParse(game.AppId, out long id) && game.FixCount > 0) + summaries[id] = new GameFixSummary( + game.FixCount, + game.Tags.Select(t => t.Name).Where(n => !string.IsNullOrWhiteSpace(n)).ToList()); + + return _summaries = summaries; + } + catch (OperationCanceledException) { throw; } + catch + { + return null; // same as above: silence, and try again next time + } + finally + { + _gate.Release(); + } + } +} diff --git a/src/LuaToolsGui/ViewModels/DownloadViewModel.cs b/src/LuaToolsGui/ViewModels/DownloadViewModel.cs index 1e6e4ec..9a63576 100644 --- a/src/LuaToolsGui/ViewModels/DownloadViewModel.cs +++ b/src/LuaToolsGui/ViewModels/DownloadViewModel.cs @@ -89,6 +89,7 @@ public partial class DownloadViewModel : ObservableObject private readonly HardwareAppIdService _hardware; private readonly DownloadQueue _queue; private readonly ManifestJobFactory _jobs; + private readonly FixLookupService _fixes; private CancellationTokenSource? _searchCts; private CancellationTokenSource? _detailsCts; @@ -101,6 +102,9 @@ public partial class DownloadViewModel : ObservableObject /// Set by App: navigate to Manage and open this appid's detail (the install banner's "Reveal"). public Action? NavigateToGame { get; set; } + /// Set by App: navigate to Fixes and open this appid's fixes (the post-fetch banner). + public Action? OpenFixesForGame { get; set; } + public ObservableCollection SearchResults { get; } = []; public ObservableCollection Sources { get; } = []; public ObservableCollection DlcDepots { get; } = []; @@ -132,6 +136,31 @@ public partial class DownloadViewModel : ObservableObject [NotifyCanExecuteChangedFor(nameof(FetchCommand))] private GameDetails? _details; + /// + /// Number of published fixes for the fetched game, filled in by after + /// a Fetch. 0 hides the banner, which is also what a failed lookup leaves behind. + /// + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(HasFix))] + [NotifyPropertyChangedFor(nameof(FixBannerText))] + private int _fixCount; + + /// What kind of fixes they are ("Online Fix", "Ubisoft", …), straight from the listing. + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(FixBannerText))] + private string _fixTags = ""; + + public bool HasFix => FixCount > 0; + + /// + /// The banner sentence. The kinds are named when the listing gives them, because "a fix" says very + /// little: the same listing covers Online Fixes, Ubisoft and Rockstar fixes, achievement fixes and + /// more, and telling the user which one is waiting is the whole point of the banner. + /// + public string FixBannerText => FixTags.Length > 0 + ? string.Format(Resources.Strings.Add_Fix_Available_Tags, FixCount, FixTags) + : string.Format(Resources.Strings.Add_Fix_Available, FixCount); + public bool HasDetails => Details is not null; public string GenresText => Details is null ? "" : string.Join(", ", Details.Genres); @@ -323,7 +352,7 @@ public Task DownloadSourceByNameAsync(string name) public DownloadViewModel(LuaToolsApiClient api, HubcapService hubcap, SettingsService settings, AuthService auth, ToastService toast, LuaInstaller installer, SteamAppListCache appList, SteamAppInfoCache appInfo, SteamDepotInfo depotInfo, - HardwareAppIdService hardware, DropInstallViewModel drop, + HardwareAppIdService hardware, FixLookupService fixes, DropInstallViewModel drop, DownloadQueue queue, ManifestJobFactory jobs) { _api = api; @@ -338,6 +367,7 @@ public DownloadViewModel(LuaToolsApiClient api, HubcapService hubcap, SettingsSe _hardware = hardware; _queue = queue; _jobs = jobs; + _fixes = fixes; Drop = drop; _fastFetch = settings.FastFetch; } @@ -533,6 +563,11 @@ private async Task FetchAsync() } else { + // Independent of the source check, and deliberately not awaited: whether the game has a + // Denuvo fix has no bearing on fetching its manifest sources, and the banner showing a + // moment later is better than holding up the fetch. + _ = CheckFixesAsync(Details.AppId); + var statuses = await _api.CheckSourcesAsync(Details.AppId.ToString()); // The manifest backend no longer reports the Hubcap/Morrenus source. Synthesize it @@ -577,6 +612,38 @@ private async Task FetchAsync() } } + /// + /// Look up how many Denuvo fixes exist for the game that was just fetched, and surface the banner. + /// + /// + /// The result is dropped if the user has moved on to another game in the meantime: the lookup can + /// outlive the fetch that started it, and a banner advertising fixes for the previous game would be + /// worse than no banner at all. + /// + /// + private async Task CheckFixesAsync(long appId) + { + try + { + var summary = await _fixes.GetFixSummaryAsync(appId); + if (Details?.AppId != appId) return; // user moved on. Drop it + + FixCount = summary?.Count ?? 0; + FixTags = summary is null ? "" : string.Join(", ", summary.Tags); + } + catch + { + // Offline / API down. The banner just doesn't appear. + } + } + + /// Banner action: jump to the Fixes page with this game already open. + [RelayCommand] + private void OpenFixes() + { + if (Details is { } details) OpenFixesForGame?.Invoke(details.AppId); + } + /// The Hubcap source name as the website/source-meta keys it. private const string HubcapSourceName = "Sadie (Morrenus)"; @@ -949,6 +1016,8 @@ private void ResetResults() Error = null; LastDownload = null; _fastFetchSource = null; + FixCount = 0; + FixTags = ""; } /// diff --git a/src/LuaToolsGui/Views/DownloadView.xaml b/src/LuaToolsGui/Views/DownloadView.xaml index cd9bdec..28c4bae 100644 --- a/src/LuaToolsGui/Views/DownloadView.xaml +++ b/src/LuaToolsGui/Views/DownloadView.xaml @@ -373,6 +373,42 @@ TextWrapping="Wrap" Visibility="{Binding Error, Converter={StaticResource NullToCollapsed}}" /> + + + + + + + + + + + + + +