From db7511d10b2578d369c4bd78ab06c78603b564f9 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 25 Jan 2026 23:54:44 -0500 Subject: [PATCH 01/20] add build attestation --- docs/release-notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index d2b881fe..0afb6b05 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -2,7 +2,7 @@ # Release notes ## 4.5.1 -Released 25 January 2026 for Stardew Valley 1.6.14 or later. +Released 25 January 2026 for Stardew Valley 1.6.14 or later. See [build attestation](https://github.com/Pathoschild/SMAPI/attestations/17385144). * For players: * Fixed error installing SMAPI 4.5.0 on Linux/macOS. From b5f099aa0bf5694b0b8f796f3a767e014a98da1f Mon Sep 17 00:00:00 2001 From: Quentium Date: Thu, 29 Jan 2026 10:02:07 +0100 Subject: [PATCH 02/20] Fix typo in developer mode description --- src/SMAPI/i18n/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMAPI/i18n/fr.json b/src/SMAPI/i18n/fr.json index 7fa876e4..059e4842 100644 --- a/src/SMAPI/i18n/fr.json +++ b/src/SMAPI/i18n/fr.json @@ -28,7 +28,7 @@ "config.section.console-window": "Console window", "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.desc": "Whether to show much more info in the SMAPI console window, intended for mod developers. Not recommended for most players.", "config.color-scheme.name": "Color scheme", "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", From 42d0ba500eed7651fcceb37acd08611db647421b Mon Sep 17 00:00:00 2001 From: Quentium Date: Thu, 29 Jan 2026 10:02:29 +0100 Subject: [PATCH 03/20] Fix typo in developer mode description --- src/SMAPI/i18n/default.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMAPI/i18n/default.json b/src/SMAPI/i18n/default.json index 356fee76..4771f858 100644 --- a/src/SMAPI/i18n/default.json +++ b/src/SMAPI/i18n/default.json @@ -27,7 +27,7 @@ "config.section.console-window": "Console window", "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.desc": "Whether to show much more info in the SMAPI console window, intended for mod developers. Not recommended for most players.", "config.color-scheme.name": "Color scheme", "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", From 07a6dc647e4cfefa7445bdb6da2ce43db1f06b27 Mon Sep 17 00:00:00 2001 From: Quentium Date: Thu, 29 Jan 2026 10:02:50 +0100 Subject: [PATCH 04/20] Translate SMAPI configuration strings to French --- src/SMAPI/i18n/fr.json | 51 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/src/SMAPI/i18n/fr.json b/src/SMAPI/i18n/fr.json index 059e4842..1d8ec1d2 100644 --- a/src/SMAPI/i18n/fr.json +++ b/src/SMAPI/i18n/fr.json @@ -11,45 +11,44 @@ /********* ** Generic Mod Config Menu UI *********/ - // TODO // 'SMAPI features' section - "config.section.features": "SMAPI features", + "config.section.features": "Fonctionnalités de SMAPI", - "config.check-for-updates.name": "Check for updates", - "config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.", + "config.check-for-updates.name": "Vérifier les mises à jour", + "config.check-for-updates.desc": "Permet de vérifier automatiquement si de nouvelles versions de SMAPI et de mods sont disponibles lorsque vous chargez le jeu. Si de nouvelles versions sont disponibles, une alerte s'affichera dans la console. Cela n'affecte pas le temps de chargement, même si votre connexion est hors ligne ou lente, car cela se produit en arrière-plan.", - "config.check-content-integrity.name": "Check content integrity", - "config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.", + "config.check-content-integrity.name": "Vérifier l'intégrité du contenu", + "config.check-content-integrity.desc": "SMAPI doit-il vérifier si les fichiers de contenu du jeu sont présents et n'ont pas été modifiés ? Cette option doit de préférence être activée. Si elle est désactivée, SMAPI écrira un avertissement pour plus de visibilité lorsque quelqu'un vous aidera à résoudre des problèmes liés au jeu.", - "config.read-console-input.name": "Read console input", - "config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.", + "config.read-console-input.name": "Lire les entrées de la console", + "config.read-console-input.desc": "Permet à SMAPI de lire les entrées de la console. La désactivation de cette option vous empêchera d'utiliser les commandes de la console. Sur certains systèmes Linux spécifiques, la désactivation de cette option peut réduire l'utilisation du processeur.", // 'Console window' section - "config.section.console-window": "Console window", + "config.section.console-window": "Fenêtre de la console", - "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI console window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.name": "Mode développeur", + "config.developer-mode.desc": "Afficher davantage d'informations dans la fenêtre de la console SMAPI, destinée aux développeurs de mods. Non recommandé pour la plupart des joueurs.", - "config.color-scheme.name": "Color scheme", - "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", - "config.color-scheme.options.AutoDetect": "Auto-detect", - "config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)", - "config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)", - "config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)", - "config.color-scheme.options.None": "No colors", + "config.color-scheme.name": "Schéma de couleurs", + "config.color-scheme.desc": "Le schéma de couleurs à appliquer au texte dans la fenêtre de la console SMAPI. Cela n'a aucun effet sur le jeu, les mods ou le fichier journal SMAPI.", + "config.color-scheme.options.AutoDetect": "Détection automatique", + "config.color-scheme.options.AutoDetect.on-windows": "Détection automatique (recommandé)", + "config.color-scheme.options.DarkBackground": "Texte plus clair (pour les arrière-plans sombres)", + "config.color-scheme.options.LightBackground": "Texte plus foncé (pour les arrière-plans clairs)", + "config.color-scheme.options.None": "Pas de couleurs", // 'Verbose logging' section - "config.section.verbose-logs": "Verbose logs", - "config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.", + "config.section.verbose-logs": "Journaux détaillés", + "config.section.verbose-logs.explanation": "Pour aider à résoudre les problèmes, SMAPI et de nombreux mods peuvent envoyer des informations supplémentaires au journal SMAPI (appelé 'journalisation détaillée'). Cela peut causer des problèmes de performance et devrait généralement être désactivé.", - "config.enable-for.name": "Enable for", - "config.enable-for.desc": "Choose which mods have verbose logging enabled.", - "config.enable-for.options.all": "All (not recommended)", - "config.enable-for.options.selected": "Mods selected below", + "config.enable-for.name": "Activé pour", + "config.enable-for.desc": "Choisissez les mods pour lesquels la journalisation détaillée est activée.", + "config.enable-for.options.all": "Tous (non recommandé)", + "config.enable-for.options.selected": "Mods sélectionnés ci-dessous", "config.enable-for-smapi.name": "SMAPI", - "config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.", + "config.enable-for-smapi.desc": "Activer ou non les journaux détaillés pour SMAPI lui-même.", "config.enable-for-mod.name": "{{modName}}", - "config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod." + "config.enable-for-mod.desc": "Activer ou non les journaux détaillés pour le mod '{{modName}}'." } From d94f6ea5b5e55e6c6ca4be9281158b26bdefe9ac Mon Sep 17 00:00:00 2001 From: dew <57487611+dewanggatrustha@users.noreply.github.com> Date: Thu, 29 Jan 2026 17:48:43 +0700 Subject: [PATCH 05/20] Update Indonesian translations Provides an updated Indonesian localization for SMAPI. The translation aims to be natural for Indonesian players while maintaining technical clarity for troubleshooting. --- src/SMAPI/i18n/id.json | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/SMAPI/i18n/id.json b/src/SMAPI/i18n/id.json index 18a78da2..30716527 100644 --- a/src/SMAPI/i18n/id.json +++ b/src/SMAPI/i18n/id.json @@ -13,43 +13,43 @@ *********/ // TODO // 'SMAPI features' section - "config.section.features": "SMAPI features", + "config.section.features": "Fitur SMAPI", - "config.check-for-updates.name": "Check for updates", - "config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.", + "config.check-for-updates.name": "Periksa pembaruan", + "config.check-for-updates.desc": "Menentukan apakah akan memeriksa versi terbaru SMAPI dan mod secara otomatis saat Anda memuat permainan. Jika versi terbaru tersedia, peringatan akan ditampilkan di konsol. Ini tidak memengaruhi waktu pemuatan meskipun koneksi Anda luring atau lambat, karena ini terjadi di latar belakang.", - "config.check-content-integrity.name": "Check content integrity", - "config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.", + "config.check-content-integrity.name": "Periksa integritas konten", + "config.check-content-integrity.desc": "Menentukan apakah SMAPI harus memeriksa apakah berkas konten permainan tersedia dan tidak dimodifikasi. Ini hampir selalu harus diaktifkan. Jika dinonaktifkan, SMAPI akan mencatat peringatan agar terlihat saat seseorang membantu Anda memecahkan masalah permainan.", - "config.read-console-input.name": "Read console input", - "config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.", + "config.read-console-input.name": "Baca input konsol", + "config.read-console-input.desc": "Menentukan apakah SMAPI harus mendengarkan input konsol. Menonaktifkan ini akan mencegah Anda menggunakan perintah konsol. Pada beberapa sistem Linux tertentu, menonaktifkan ini dapat mengurangi penggunaan CPU.", // 'Console window' section - "config.section.console-window": "Console window", + "config.section.console-window": "Jendela konsol", - "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.name": "Mode pengembang", + "config.developer-mode.desc": "Menentukan apakah akan menampilkan lebih banyak info di jendela konsol SMAPI, ditujukan untuk pengembang mod. Tidak disarankan bagi sebagian besar pemain.", - "config.color-scheme.name": "Color scheme", - "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", - "config.color-scheme.options.AutoDetect": "Auto-detect", - "config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)", - "config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)", - "config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)", - "config.color-scheme.options.None": "No colors", + "config.color-scheme.name": "Skema warna", + "config.color-scheme.desc": "Skema warna yang diterapkan pada teks di jendela konsol SMAPI. Ini tidak memengaruhi permainan, mod, atau berkas log SMAPI.", + "config.color-scheme.options.AutoDetect": "Deteksi otomatis", + "config.color-scheme.options.AutoDetect.on-windows": "Deteksi otomatis (disarankan)", + "config.color-scheme.options.DarkBackground": "Teks lebih terang (untuk latar belakang gelap)", + "config.color-scheme.options.LightBackground": "Teks lebih gelap (untuk latar belakang terang)", + "config.color-scheme.options.None": "Tanpa warna", // 'Verbose logging' section - "config.section.verbose-logs": "Verbose logs", - "config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.", + "config.section.verbose-logs": "Log terperinci", + "config.section.verbose-logs.explanation": "Untuk membantu pemecahan masalah, SMAPI dan banyak mod dapat mengirimkan info tambahan ke log SMAPI (disebut 'log terperinci'). Ini dapat menyebabkan masalah performa, dan biasanya harus dinonaktifkan.", - "config.enable-for.name": "Enable for", - "config.enable-for.desc": "Choose which mods have verbose logging enabled.", - "config.enable-for.options.all": "All (not recommended)", - "config.enable-for.options.selected": "Mods selected below", + "config.enable-for.name": "Aktifkan untuk", + "config.enable-for.desc": "Pilih mod mana yang akan mengaktifkan log terperinci.", + "config.enable-for.options.all": "Semua (tidak disarankan)", + "config.enable-for.options.selected": "Mod yang dipilih di bawah", "config.enable-for-smapi.name": "SMAPI", - "config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.", + "config.enable-for-smapi.desc": "Menentukan apakah akan mengaktifkan log terperinci untuk SMAPI itu sendiri.", "config.enable-for-mod.name": "{{modName}}", - "config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod." + "config.enable-for-mod.desc": "Menentukan apakah akan mengaktifkan log terperinci untuk mod '{{modName}}'." } From bbac0ae0321dfd4c8cf17dc4b29b66824212d7d8 Mon Sep 17 00:00:00 2001 From: Timur1324 Date: Thu, 29 Jan 2026 19:26:05 +0600 Subject: [PATCH 06/20] Russian translation for SMAPI --- docs/README.md | 2 +- src/SMAPI/i18n/ru.json | 51 +++++++++++++++++++++--------------------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/docs/README.md b/docs/README.md index 17d9dd87..4a721cef 100644 --- a/docs/README.md +++ b/docs/README.md @@ -69,7 +69,7 @@ Japanese | ↻ [partly translated](../src/SMAPI/i18n/ja.json) Korean | ↻ [partly translated](../src/SMAPI/i18n/ko.json) [Polish] | ↻ [partly translated](../src/SMAPI/i18n/pl.json) Portuguese | ✓ [fully translated](../src/SMAPI/i18n/pt.json) -Russian | ↻ [partly translated](../src/SMAPI/i18n/ru.json) +Russian | ✓ [fully translated](../src/SMAPI/i18n/ru.json) Spanish | ↻ [partly translated](../src/SMAPI/i18n/es.json) [Thai] | ↻ [partly translated](../src/SMAPI/i18n/th.json) Turkish | ↻ [partly translated](../src/SMAPI/i18n/tr.json) diff --git a/src/SMAPI/i18n/ru.json b/src/SMAPI/i18n/ru.json index 1ac64673..4ef64af5 100644 --- a/src/SMAPI/i18n/ru.json +++ b/src/SMAPI/i18n/ru.json @@ -11,45 +11,44 @@ /********* ** Generic Mod Config Menu UI *********/ - // TODO // 'SMAPI features' section - "config.section.features": "SMAPI features", + "config.section.features": "Настройки SMAPI", - "config.check-for-updates.name": "Check for updates", - "config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.", + "config.check-for-updates.name": "Проверять обновления", + "config.check-for-updates.desc": "Проверять ли наличие новой версии SMAPI и модов, пока запускается игра. Если будет доступна новая версия, то в консоль будет выведено уведомление. Эта опция никак не должна влиять на скорость запуска игры, так как проверка происходит на фоне, даже если соединение медленное или отсутствует вовсе.", - "config.check-content-integrity.name": "Check content integrity", - "config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.", + "config.check-content-integrity.name": "Проверять целостность файлов игры", + "config.check-content-integrity.desc": "Эта настройка определяет будет ли SMAPI проверять наличие и целостность файлов (контента) игры. Желательно, чтобы это опция была всегда включена. Если вдруг с игрой будет что-то не так, то это может помочь решить проблему быстрее. Если эта опция будет выключена, SMAPI запишет в журнал (лог файл) об этом.", - "config.read-console-input.name": "Read console input", - "config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.", + "config.read-console-input.name": "Консольные команды", + "config.read-console-input.desc": "Определят, будет ли SMAPI ожидать ввод консольных команд. Если эту настройку отключить, то вводить консольные команды будет нельзя. На некоторых Linux системах отключение этой опции может снизить использование ЦПУ (процессора).", // 'Console window' section - "config.section.console-window": "Console window", + "config.section.console-window": "Окно консоли", - "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.name": "Режим разработчика", + "config.developer-mode.desc": "Показывать ли больше информации в консоли SMAPI, опция предназначена для разработчиков. Не рекомендуется включать большинству игроков.", - "config.color-scheme.name": "Color scheme", - "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", - "config.color-scheme.options.AutoDetect": "Auto-detect", - "config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)", - "config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)", - "config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)", - "config.color-scheme.options.None": "No colors", + "config.color-scheme.name": "Цветовая схема", + "config.color-scheme.desc": "Цветовая схема, которая будет применена к тексту в консольном окне SMAPI. Никак не влияет на игру, моды или файл журнала (лог файл) SMAPI.", + "config.color-scheme.options.AutoDetect": "Автоматически", + "config.color-scheme.options.AutoDetect.on-windows": "Автоматически (рекомендуется)", + "config.color-scheme.options.DarkBackground": "Светлый текст (для тёмного фона)", + "config.color-scheme.options.LightBackground": "Тёмный текст (для светлого фона)", + "config.color-scheme.options.None": "Без цвета", // 'Verbose logging' section - "config.section.verbose-logs": "Verbose logs", - "config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.", + "config.section.verbose-logs": "Более подробное журналирование", + "config.section.verbose-logs.explanation": "Чтобы было проще решать возникающие проблемы, SMAPI и многим другим модам может потребоваться записать больше информации в журнал (так же известный как лог-файл, эта информация ещё обычно выводится в консоль). Оно может влиять на производительность игры, поэтому обычно не стоит включать это без надобности.", - "config.enable-for.name": "Enable for", - "config.enable-for.desc": "Choose which mods have verbose logging enabled.", - "config.enable-for.options.all": "All (not recommended)", - "config.enable-for.options.selected": "Mods selected below", + "config.enable-for.name": "Включить для", + "config.enable-for.desc": "Определяет, для чего будет включено подробное журналирование.", + "config.enable-for.options.all": "Всех модов (не рекомендуется)", + "config.enable-for.options.selected": "Модов выбранных ниже", "config.enable-for-smapi.name": "SMAPI", - "config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.", + "config.enable-for-smapi.desc": "Определяет, включать ли подробное журналирование для самого SMAPI.", "config.enable-for-mod.name": "{{modName}}", - "config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod." + "config.enable-for-mod.desc": "Определяет, включать ли подробное журналирование для мода '{{modName}}'." } From 850e99cb45f03ea1a64a677c1dbc0781775c5203 Mon Sep 17 00:00:00 2001 From: Casey W Date: Wed, 28 Jan 2026 19:25:05 -0500 Subject: [PATCH 07/20] Allow controller input overrides to apply even without connected controller --- src/SMAPI/Framework/Input/GamePadStateBuilder.cs | 12 ------------ src/SMAPI/Framework/Input/SInputState.cs | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs index 0f6e99ae..2d2b485c 100644 --- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -55,9 +55,6 @@ internal class GamePadStateBuilder : IInputStateBuilder public GamePadStateBuilder OverrideButtons(IDictionary overrides) { - if (!this.IsConnected) - return this; - foreach (var pair in overrides) { bool changed = true; @@ -155,9 +149,6 @@ internal class GamePadStateBuilder : IInputStateBuilder public IEnumerable GetPressedButtons() { - if (!this.IsConnected) - yield break; - // buttons foreach (Buttons button in this.GetPressedGamePadButtons()) yield return button.ToSButton(); @@ -213,9 +204,6 @@ internal class GamePadStateBuilder : IInputStateBuilderGet the pressed gamepad buttons. private IEnumerable GetPressedGamePadButtons() { - if (!this.IsConnected) - yield break; - foreach (var pair in this.ButtonStates) { if (pair.Value == ButtonState.Pressed && pair.Key.TryGetController(out Buttons button)) diff --git a/src/SMAPI/Framework/Input/SInputState.cs b/src/SMAPI/Framework/Input/SInputState.cs index 44276b7c..d41279e4 100644 --- a/src/SMAPI/Framework/Input/SInputState.cs +++ b/src/SMAPI/Framework/Input/SInputState.cs @@ -238,14 +238,14 @@ internal sealed class SInputState : InputState mouseOverrides[button] = newState; else if (button.TryGetKeyboard(out Keys _)) keyboardOverrides[button] = newState; - else if (controller.IsConnected && button.TryGetController(out Buttons _)) + else if (button.TryGetController(out Buttons _)) controllerOverrides[button] = newState; } // override states if (keyboardOverrides.Any()) keyboard.OverrideButtons(keyboardOverrides); - if (controller.IsConnected && controllerOverrides.Any()) + if (controllerOverrides.Any()) controller.OverrideButtons(controllerOverrides); if (mouseOverrides.Any()) mouse.OverrideButtons(mouseOverrides); From 5fc8e806c21db2d6f58db9813b53c125308d067b Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 16:59:08 -0500 Subject: [PATCH 08/20] avoid querying controller state if it's not connected --- .../Framework/Input/GamePadStateBuilder.cs | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs index 2d2b485c..2c20c226 100644 --- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Input; @@ -22,7 +21,7 @@ internal class GamePadStateBuilder : IInputStateBuilderThe current button states. - private readonly IDictionary? ButtonStates; + private readonly Dictionary ButtonStates; /// The left trigger value. private float LeftTrigger; @@ -41,7 +40,6 @@ internal class GamePadStateBuilder : IInputStateBuilderWhether the gamepad is currently connected. - [MemberNotNullWhen(true, nameof(GamePadStateBuilder.ButtonStates))] public bool IsConnected { get; } @@ -55,33 +53,38 @@ internal class GamePadStateBuilder : IInputStateBuilder + if (this.IsConnected) { - [SButton.DPadUp] = pad.Up, - [SButton.DPadDown] = pad.Down, - [SButton.DPadLeft] = pad.Left, - [SButton.DPadRight] = pad.Right, + GamePadDPad pad = state.DPad; + GamePadButtons buttons = state.Buttons; + GamePadTriggers triggers = state.Triggers; + GamePadThumbSticks sticks = state.ThumbSticks; + this.ButtonStates = new Dictionary + { + [SButton.DPadUp] = pad.Up, + [SButton.DPadDown] = pad.Down, + [SButton.DPadLeft] = pad.Left, + [SButton.DPadRight] = pad.Right, - [SButton.ControllerA] = buttons.A, - [SButton.ControllerB] = buttons.B, - [SButton.ControllerX] = buttons.X, - [SButton.ControllerY] = buttons.Y, - [SButton.LeftStick] = buttons.LeftStick, - [SButton.RightStick] = buttons.RightStick, - [SButton.LeftShoulder] = buttons.LeftShoulder, - [SButton.RightShoulder] = buttons.RightShoulder, - [SButton.ControllerBack] = buttons.Back, - [SButton.ControllerStart] = buttons.Start, - [SButton.BigButton] = buttons.BigButton - }; - this.LeftTrigger = triggers.Left; - this.RightTrigger = triggers.Right; - this.LeftStickPos = sticks.Left; - this.RightStickPos = sticks.Right; + [SButton.ControllerA] = buttons.A, + [SButton.ControllerB] = buttons.B, + [SButton.ControllerX] = buttons.X, + [SButton.ControllerY] = buttons.Y, + [SButton.LeftStick] = buttons.LeftStick, + [SButton.RightStick] = buttons.RightStick, + [SButton.LeftShoulder] = buttons.LeftShoulder, + [SButton.RightShoulder] = buttons.RightShoulder, + [SButton.ControllerBack] = buttons.Back, + [SButton.ControllerStart] = buttons.Start, + [SButton.BigButton] = buttons.BigButton + }; + this.LeftTrigger = triggers.Left; + this.RightTrigger = triggers.Right; + this.LeftStickPos = sticks.Left; + this.RightStickPos = sticks.Right; + } + else + this.ButtonStates = []; } /// @@ -132,10 +135,7 @@ internal class GamePadStateBuilder : IInputStateBuilder Date: Sun, 1 Feb 2026 17:00:47 -0500 Subject: [PATCH 09/20] remove now-unneeded IsConnected property --- src/SMAPI/Framework/Input/GamePadStateBuilder.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs index 2c20c226..25993d6e 100644 --- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -36,13 +36,6 @@ internal class GamePadStateBuilder : IInputStateBuilderWhether the gamepad is currently connected. - public bool IsConnected { get; } - - /********* ** Public methods *********/ @@ -51,9 +44,8 @@ internal class GamePadStateBuilder : IInputStateBuilder Date: Sun, 1 Feb 2026 17:15:49 -0500 Subject: [PATCH 10/20] update release notes & translation docs --- docs/README.md | 4 ++-- docs/release-notes.md | 9 +++++++++ src/SMAPI/i18n/id.json | 1 - 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index 4a721cef..c60970f3 100644 --- a/docs/README.md +++ b/docs/README.md @@ -60,10 +60,10 @@ locale | status ----------- | :---------------- default | ↻ [partly translated](../src/SMAPI/i18n/default.json) Chinese | ↻ [partly translated](../src/SMAPI/i18n/zh.json) -French | ↻ [partly translated](../src/SMAPI/i18n/fr.json) +French | ✓ [fully translated](../src/SMAPI/i18n/fr.json) German | ↻ [partly translated](../src/SMAPI/i18n/de.json) Hungarian | ↻ [partly translated](../src/SMAPI/i18n/hu.json) -Indonesian | ↻ [partly translated](../src/SMAPI/i18n/id.json) +Indonesian | ✓ [fully translated](../src/SMAPI/i18n/id.json) Italian | ↻ [partly translated](../src/SMAPI/i18n/it.json) Japanese | ↻ [partly translated](../src/SMAPI/i18n/ja.json) Korean | ↻ [partly translated](../src/SMAPI/i18n/ko.json) diff --git a/docs/release-notes.md b/docs/release-notes.md index 0afb6b05..debc1f8a 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,6 +1,15 @@ ← [README](README.md) # Release notes +## Upcoming release +* For players: + * Fixed typo in config UI text (thanks to QuentiumYT!). + * Improved translations. Thanks to dewanggatrustha (updated Indonesian), QuentiumYT (updated French), and Timur13240 + (updated Russian)! + +* For mod authors: + * Fixed input API ignoring controller overrides when there's no controller plugged in (thanks to spacechase0!). + ## 4.5.1 Released 25 January 2026 for Stardew Valley 1.6.14 or later. See [build attestation](https://github.com/Pathoschild/SMAPI/attestations/17385144). diff --git a/src/SMAPI/i18n/id.json b/src/SMAPI/i18n/id.json index 30716527..b5f1d1ef 100644 --- a/src/SMAPI/i18n/id.json +++ b/src/SMAPI/i18n/id.json @@ -11,7 +11,6 @@ /********* ** Generic Mod Config Menu UI *********/ - // TODO // 'SMAPI features' section "config.section.features": "Fitur SMAPI", From 295da0957c6a354b5690084dfd69decc44861543 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 18:17:24 -0500 Subject: [PATCH 11/20] remove draft GitHub release in build workflow The draft releases caused issues for SMAPI's update flow, because... 1. Updates are releases to Nexus first, since that doesn't trigger update alerts. If there are no major issues, they're released to GitHub a few days later. 2. Update alerts work by fetching the last two SMAPI GitHub releases. The GitHub API doesn't allow ignoring drafts, so SMAPI just ignores any drafts in those top two slots. 3. The new build workflow created a draft release for each version tag. That meant that releasing a second SMAPI update to Nexus before the GitHub release (like 4.5.0 + 4.5.1) would break update alerts for all players with a "Found no GitHub release for this ID" error, since the two latest releases were both ignored. --- .github/workflows/build-smapi.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/.github/workflows/build-smapi.yml b/.github/workflows/build-smapi.yml index b026fcc8..81b034c4 100644 --- a/.github/workflows/build-smapi.yml +++ b/.github/workflows/build-smapi.yml @@ -94,18 +94,6 @@ jobs: path: 'bin/SMAPI-${{env.VERSION}}-installer.zip' if-no-files-found: 'error' - - name: Create GitHub release - uses: ncipollo/release-action@v1 - if: github.ref_type == 'tag' - with: - artifacts: 'bin/SMAPI-${{env.VERSION}}-installer.zip' - token: '${{secrets.GITHUB_TOKEN}}' - tag: '${{github.ref_name}}' - name: '${{env.VERSION}}' - body: | - Draft. - draft: true - - name: Generate artifact attestations uses: actions/attest-build-provenance@v2 if: github.ref_type == 'tag' From ee55254221a179b1f5eb41fec2698ed712aeda1d Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 18:17:24 -0500 Subject: [PATCH 12/20] remove unused import in build script --- build/scripts/prepare-install-package.ps1 | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/scripts/prepare-install-package.ps1 b/build/scripts/prepare-install-package.ps1 index 8cd2c646..74222b58 100644 --- a/build/scripts/prepare-install-package.ps1 +++ b/build/scripts/prepare-install-package.ps1 @@ -7,8 +7,6 @@ # # -. "$PSScriptRoot/lib/in-place-regex.ps1" - ########## ## Read arguments From 8b0936cf5ba0a118e0dd8f75cf0130c8ef3654e5 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 18:17:24 -0500 Subject: [PATCH 13/20] fix hardcoded path when editing settings files --- .../Integrations/GenericModConfigMenu/JsonSettingsWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMAPI/Integrations/GenericModConfigMenu/JsonSettingsWrapper.cs b/src/SMAPI/Integrations/GenericModConfigMenu/JsonSettingsWrapper.cs index f2302c55..b06d43e5 100644 --- a/src/SMAPI/Integrations/GenericModConfigMenu/JsonSettingsWrapper.cs +++ b/src/SMAPI/Integrations/GenericModConfigMenu/JsonSettingsWrapper.cs @@ -60,7 +60,7 @@ internal class JsonSettingsWrapper public void SaveOrDeleteFile() { if (this.Properties.Count == 0) - File.Delete(Constants.ApiUserConfigPath); + File.Delete(this.FilePath); else { string json = JsonConvert.SerializeObject(this.Properties, Formatting.Indented); From 81d62147294f7bc9a9c44114011cd1782ed14e74 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 18:17:24 -0500 Subject: [PATCH 14/20] update Linux/macOS installer color scheme logic for 4.5.0+ changes The selected color scheme should now be set in `config.user.json` instead of `config.json`, and the field was renamed. --- docs/release-notes.md | 1 + src/SMAPI.Installer/InteractiveInstaller.cs | 37 ++++++++++++++++++--- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index debc1f8a..61c9652a 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -3,6 +3,7 @@ # Release notes ## Upcoming release * For players: + * Fixed the Linux/macOS installer not saving the color scheme correctly in 4.5.0+. * Fixed typo in config UI text (thanks to QuentiumYT!). * Improved translations. Thanks to dewanggatrustha (updated Indonesian), QuentiumYT (updated French), and Timur13240 (updated Russian)! diff --git a/src/SMAPI.Installer/InteractiveInstaller.cs b/src/SMAPI.Installer/InteractiveInstaller.cs index 714809fc..306a17ad 100644 --- a/src/SMAPI.Installer/InteractiveInstaller.cs +++ b/src/SMAPI.Installer/InteractiveInstaller.cs @@ -6,6 +6,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Reflection; +using Newtonsoft.Json.Linq; using StardewModdingApi.Installer.Enums; using StardewModdingAPI.Installer.Framework; using StardewModdingAPI.Internal.ConsoleWriting; @@ -13,6 +14,7 @@ using StardewModdingAPI.Toolkit; using StardewModdingAPI.Toolkit.Framework; using StardewModdingAPI.Toolkit.Framework.GameScanning; using StardewModdingAPI.Toolkit.Framework.ModScanning; +using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Toolkit.Utilities; namespace StardewModdingApi.Installer; @@ -501,10 +503,10 @@ internal class InteractiveInstaller // set SMAPI's color scheme if defined if (scheme != MonitorColorScheme.AutoDetect) { - string text = File - .ReadAllText(paths.ApiConfigPath) - .Replace(@"""UseScheme"": ""AutoDetect""", $@"""UseScheme"": ""{scheme}"""); - File.WriteAllText(paths.ApiConfigPath, text); + this.SaveUserSettings(paths.ApiUserConfigPath, new Dictionary + { + ["ConsoleColorScheme"] = scheme.ToString() + }); } } } @@ -559,6 +561,33 @@ internal class InteractiveInstaller } } + /// Save the given options to a SMAPI internal config file. + /// The file path to edit. + /// The settings to add or overwrite. + [SuppressMessage("Trimming", "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code", Justification = "This isn't an issue here, since we're only using JToken and object.")] + private void SaveUserSettings(string filePath, Dictionary settings) + { + JsonHelper jsonHelper = new(); + + // merge into existing settings + Dictionary saveSettings = settings.ToDictionary(p => p.Key, p => JToken.FromObject(p.Value)); + try + { + if (jsonHelper.ReadJsonFileIfExists(filePath, out Dictionary? fileSettings)) + { + foreach ((string key, JToken value) in fileSettings) + saveSettings.TryAdd(key, value); + } + } + catch (Exception ex) + { + this.PrintWarning($"Couldn't parse your SMAPI settings file. Replacing it with a default version.\n\nTechnical details:\n{ex}"); + } + + // save file + jsonHelper.WriteJsonFile(filePath, saveSettings); + } + /// Print a message without formatting. /// The text to print. private void PrintPlain(string text) From 3bb18fcdaf76ca214db0dda6f95ae37dc576fe89 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 1 Feb 2026 18:17:24 -0500 Subject: [PATCH 15/20] reduce allocations in input handling This reuses the input builders instead of creating new ones each time we build input. --- docs/release-notes.md | 1 + .../Framework/Input/GamePadStateBuilder.cs | 52 +++++++++++-------- .../Framework/Input/IInputStateBuilder.cs | 4 ++ .../Framework/Input/KeyboardStateBuilder.cs | 5 +- .../Framework/Input/MouseStateBuilder.cs | 29 +++++------ src/SMAPI/Framework/Input/SInputState.cs | 30 ++++++++--- 6 files changed, 74 insertions(+), 47 deletions(-) diff --git a/docs/release-notes.md b/docs/release-notes.md index 61c9652a..6efa5650 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -3,6 +3,7 @@ # Release notes ## Upcoming release * For players: + * Minor performance optimizations. * Fixed the Linux/macOS installer not saving the color scheme correctly in 4.5.0+. * Fixed typo in config UI text (thanks to QuentiumYT!). * Improved translations. Thanks to dewanggatrustha (updated Indonesian), QuentiumYT (updated French), and Timur13240 diff --git a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs index 25993d6e..e5ca1b1c 100644 --- a/src/SMAPI/Framework/Input/GamePadStateBuilder.cs +++ b/src/SMAPI/Framework/Input/GamePadStateBuilder.cs @@ -21,7 +21,7 @@ internal class GamePadStateBuilder : IInputStateBuilderThe current button states. - private readonly Dictionary ButtonStates; + private readonly Dictionary ButtonStates = []; /// The left trigger value. private float LeftTrigger; @@ -39,9 +39,8 @@ internal class GamePadStateBuilder : IInputStateBuilderConstruct an instance. - /// The initial state. - public GamePadStateBuilder(GamePadState state) + /// + public void Reset(GamePadState state) { this.State = state; @@ -51,32 +50,39 @@ internal class GamePadStateBuilder : IInputStateBuilder - { - [SButton.DPadUp] = pad.Up, - [SButton.DPadDown] = pad.Down, - [SButton.DPadLeft] = pad.Left, - [SButton.DPadRight] = pad.Right, - [SButton.ControllerA] = buttons.A, - [SButton.ControllerB] = buttons.B, - [SButton.ControllerX] = buttons.X, - [SButton.ControllerY] = buttons.Y, - [SButton.LeftStick] = buttons.LeftStick, - [SButton.RightStick] = buttons.RightStick, - [SButton.LeftShoulder] = buttons.LeftShoulder, - [SButton.RightShoulder] = buttons.RightShoulder, - [SButton.ControllerBack] = buttons.Back, - [SButton.ControllerStart] = buttons.Start, - [SButton.BigButton] = buttons.BigButton - }; + var states = this.ButtonStates; + states.Clear(); + states[SButton.DPadUp] = pad.Up; + states[SButton.DPadDown] = pad.Down; + states[SButton.DPadLeft] = pad.Left; + states[SButton.DPadRight] = pad.Right; + states[SButton.ControllerA] = buttons.A; + states[SButton.ControllerB] = buttons.B; + states[SButton.ControllerX] = buttons.X; + states[SButton.ControllerY] = buttons.Y; + states[SButton.LeftStick] = buttons.LeftStick; + states[SButton.RightStick] = buttons.RightStick; + states[SButton.LeftShoulder] = buttons.LeftShoulder; + states[SButton.RightShoulder] = buttons.RightShoulder; + states[SButton.ControllerBack] = buttons.Back; + states[SButton.ControllerStart] = buttons.Start; + states[SButton.BigButton] = buttons.BigButton; + this.LeftTrigger = triggers.Left; this.RightTrigger = triggers.Right; this.LeftStickPos = sticks.Left; this.RightStickPos = sticks.Right; } else - this.ButtonStates = []; + { + this.ButtonStates.Clear(); + + this.LeftTrigger = 0; + this.RightTrigger = 0; + this.LeftStickPos = Vector2.Zero; + this.RightStickPos = Vector2.Zero; + } } /// diff --git a/src/SMAPI/Framework/Input/IInputStateBuilder.cs b/src/SMAPI/Framework/Input/IInputStateBuilder.cs index f56e910e..221bffcc 100644 --- a/src/SMAPI/Framework/Input/IInputStateBuilder.cs +++ b/src/SMAPI/Framework/Input/IInputStateBuilder.cs @@ -12,6 +12,10 @@ internal interface IInputStateBuilder /********* ** Methods *********/ + /// Reset the state. + /// The initial state before any overrides are applied. + void Reset(TState state); + /// Override the states for a set of buttons. /// The button state overrides. THandler OverrideButtons(IDictionary overrides); diff --git a/src/SMAPI/Framework/Input/KeyboardStateBuilder.cs b/src/SMAPI/Framework/Input/KeyboardStateBuilder.cs index 6bf52de4..66e67f74 100644 --- a/src/SMAPI/Framework/Input/KeyboardStateBuilder.cs +++ b/src/SMAPI/Framework/Input/KeyboardStateBuilder.cs @@ -20,9 +20,8 @@ internal class KeyboardStateBuilder : IInputStateBuilderConstruct an instance. - /// The initial state. - public KeyboardStateBuilder(KeyboardState state) + /// + public void Reset(KeyboardState state) { this.State = state; diff --git a/src/SMAPI/Framework/Input/MouseStateBuilder.cs b/src/SMAPI/Framework/Input/MouseStateBuilder.cs index 8b34ac0a..17bac8e8 100644 --- a/src/SMAPI/Framework/Input/MouseStateBuilder.cs +++ b/src/SMAPI/Framework/Input/MouseStateBuilder.cs @@ -13,39 +13,38 @@ internal class MouseStateBuilder : IInputStateBuilderThe current button states. - private readonly IDictionary ButtonStates; + private readonly Dictionary ButtonStates = []; /// The mouse wheel scroll value. - private readonly int ScrollWheelValue; + private int ScrollWheelValue; /********* ** Accessors *********/ /// The X cursor position. - public int X { get; } + public int X { get; private set; } /// The Y cursor position. - public int Y { get; } + public int Y { get; private set; } /********* ** Public methods *********/ - /// Construct an instance. - /// The initial state. - public MouseStateBuilder(MouseState state) + /// + public void Reset(MouseState state) { this.State = state; - this.ButtonStates = new Dictionary - { - [SButton.MouseLeft] = state.LeftButton, - [SButton.MouseMiddle] = state.MiddleButton, - [SButton.MouseRight] = state.RightButton, - [SButton.MouseX1] = state.XButton1, - [SButton.MouseX2] = state.XButton2 - }; + var states = this.ButtonStates; + states.Clear(); + states[SButton.MouseLeft] = state.LeftButton; + states[SButton.MouseMiddle] = state.MiddleButton; + states[SButton.MouseRight] = state.RightButton; + states[SButton.MouseX1] = state.XButton1; + states[SButton.MouseX2] = state.XButton2; + this.X = state.X; this.Y = state.Y; this.ScrollWheelValue = state.ScrollWheelValue; diff --git a/src/SMAPI/Framework/Input/SInputState.cs b/src/SMAPI/Framework/Input/SInputState.cs index d41279e4..0ba361a6 100644 --- a/src/SMAPI/Framework/Input/SInputState.cs +++ b/src/SMAPI/Framework/Input/SInputState.cs @@ -29,6 +29,15 @@ internal sealed class SInputState : InputState /// Whether there are new overrides in or that haven't been applied to the previous state. private bool HasNewOverrides; + /// The builder which reads the game pad state and applies overrides. + private readonly GamePadStateBuilder ControllerStateBuilder = new(); + + /// The builder which reads the keyboard state and applies overrides. + private readonly KeyboardStateBuilder KeyboardStateBuilder = new(); + + /// The builder which reads the mouse state and applies overrides. + private readonly MouseStateBuilder MouseStateBuilder = new(); + /********* ** Accessors @@ -68,10 +77,15 @@ internal sealed class SInputState : InputState { float zoomMultiplier = (1f / Game1.options.zoomLevel); + // get builders + GamePadStateBuilder controller = this.ControllerStateBuilder; + KeyboardStateBuilder keyboard = this.KeyboardStateBuilder; + MouseStateBuilder mouse = this.MouseStateBuilder; + // get real values - var controller = new GamePadStateBuilder(base.GetGamePadState()); - var keyboard = new KeyboardStateBuilder(base.GetKeyboardState()); - var mouse = new MouseStateBuilder(base.GetMouseState()); + controller.Reset(base.GetGamePadState()); + keyboard.Reset(base.GetKeyboardState()); + mouse.Reset(base.GetMouseState()); Vector2 cursorAbsolutePos = new((mouse.X * zoomMultiplier) + Game1.viewport.X, (mouse.Y * zoomMultiplier) + Game1.viewport.Y); Vector2? playerTilePos = Context.IsPlayerFree ? Game1.player.Tile : null; HashSet reallyDown = new(this.GetPressedButtons(keyboard, mouse, controller)); @@ -159,9 +173,13 @@ internal sealed class SInputState : InputState { if (this.HasNewOverrides) { - var controller = new GamePadStateBuilder(this.ControllerState); - var keyboard = new KeyboardStateBuilder(this.KeyboardState); - var mouse = new MouseStateBuilder(this.MouseState); + GamePadStateBuilder controller = this.ControllerStateBuilder; + KeyboardStateBuilder keyboard = this.KeyboardStateBuilder; + MouseStateBuilder mouse = this.MouseStateBuilder; + + controller.Reset(this.ControllerState); + keyboard.Reset(this.KeyboardState); + mouse.Reset(this.MouseState); if (this.ApplyOverrides(pressed: this.CustomPressedKeys, released: this.CustomReleasedKeys, controller, keyboard, mouse)) { From eaebabfc26b50501c1dc0d625ce2975e19f2f44d Mon Sep 17 00:00:00 2001 From: vic <62157755+vlcoo@users.noreply.github.com> Date: Mon, 2 Feb 2026 18:38:29 +0100 Subject: [PATCH 16/20] Update Spanish (Spain) translation --- src/SMAPI/i18n/es.json | 55 +++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/SMAPI/i18n/es.json b/src/SMAPI/i18n/es.json index 0aa48179..6ebe77b5 100644 --- a/src/SMAPI/i18n/es.json +++ b/src/SMAPI/i18n/es.json @@ -4,52 +4,51 @@ *********/ // short date format for SDate // tokens: {{day}} (like 15), {{season}} (like Spring), {{seasonLowercase}} (like spring), {{year}} (like 2) - "generic.date": "{{seasonLowercase}} {{day}}", - "generic.date-with-year": "{{seasonLowercase}} {{day}} del año {{year}}", + "generic.date": "{{day}} de {{season}}", + "generic.date-with-year": "{{day}} de {{season}} del año {{year}}", /********* ** Generic Mod Config Menu UI *********/ - // TODO // 'SMAPI features' section - "config.section.features": "SMAPI features", + "config.section.features": "Características de SMAPI", - "config.check-for-updates.name": "Check for updates", - "config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.", + "config.check-for-updates.name": "Comprobar actualizaciones", + "config.check-for-updates.desc": "Si se debería comprobar automáticamente si hay nuevas versiones de SMAPI y de mods al cargar el juego. Si existen versiones nuevas, aparecerá un aviso en la consola. Esto no afecta el tiempo de carga si tu conexión a Internet es lenta o inexistente, ya que la comprobación se realiza en el fondo.", - "config.check-content-integrity.name": "Check content integrity", - "config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.", + "config.check-content-integrity.name": "Comprobar integridad del contenido", + "config.check-content-integrity.desc": "Si SMAPI debería comprobar si los archivos de contenido del juego están presentes y sin modificar. Esto debería estar activado casi siempte. Si se desactiva, SMAPI guardará en el log un aviso para que, si alguien te ayuda a arreglar algún problema con el juego, lo sepa.", - "config.read-console-input.name": "Read console input", - "config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.", + "config.read-console-input.name": "Leer entrada de consola", + "config.read-console-input.desc": "Si SMAPI debería ver qué se introduce por consola. Si se desactiva, no podrás usar comandos de consola. En ciertos sistemas Linux, desactivando esta opción reducirá el uso de la CPU.", // 'Console window' section - "config.section.console-window": "Console window", + "config.section.console-window": "Ventana de consola", - "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.name": "Modo desarrollador", + "config.developer-mode.desc": "Si se debería mostrar mucha más información en la consola de SMAPI, para desarrolladores de mods. No recomendado para la mayoría de jugadores.", - "config.color-scheme.name": "Color scheme", - "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", - "config.color-scheme.options.AutoDetect": "Auto-detect", - "config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)", - "config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)", - "config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)", - "config.color-scheme.options.None": "No colors", + "config.color-scheme.name": "Esquema de color", + "config.color-scheme.desc": "Qué paleta de colores aplicar al texto en la consola de SMAPI. Esto no tiene ningún efecto sobre el juego, los mods, o el archivo con logs de SMAPI.", + "config.color-scheme.options.AutoDetect": "Detectar auto.", + "config.color-scheme.options.AutoDetect.on-windows": "Detectar auto. (recomendado)", + "config.color-scheme.options.DarkBackground": "Texto más claro (para fondos oscuros)", + "config.color-scheme.options.LightBackground": "Texto más oscuro (para fondos claros)", + "config.color-scheme.options.None": "Sin colores", // 'Verbose logging' section - "config.section.verbose-logs": "Verbose logs", - "config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.", + "config.section.verbose-logs": "Logs completos", + "config.section.verbose-logs.explanation": "Para ayudar con la resolución de problemas, SMAPI y muchos mods pueden mostrar información adicional al log de SMAPI (llamados 'verbose logging'). Esto podría causar problemas de rendimiento, y normalmente debería estar desactivado.", - "config.enable-for.name": "Enable for", - "config.enable-for.desc": "Choose which mods have verbose logging enabled.", - "config.enable-for.options.all": "All (not recommended)", - "config.enable-for.options.selected": "Mods selected below", + "config.enable-for.name": "Activar para", + "config.enable-for.desc": "Elige qué mods tienen activados los logs completos.", + "config.enable-for.options.all": "Todos (no recomendado)", + "config.enable-for.options.selected": "Mods seleccionados", "config.enable-for-smapi.name": "SMAPI", - "config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.", + "config.enable-for-smapi.desc": "Si SMAPI debería tener los logs completos activados.", "config.enable-for-mod.name": "{{modName}}", - "config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod." + "config.enable-for-mod.desc": "Si el mod '{{modName}}' debería tener los logs completos activados." } From 2430b66518a261b38a339fb521c4c22dc7523110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9C=A8=E4=B8=AD=E5=9B=BD=E7=9A=84=E6=B3=B0=E5=9B=BD?= =?UTF-8?q?=E9=9D=92=E5=B9=B4=5F?= Date: Sat, 21 Feb 2026 11:52:02 +0700 Subject: [PATCH 17/20] Translate SMAPI config options to Thai --- src/SMAPI/i18n/th.json | 50 +++++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/SMAPI/i18n/th.json b/src/SMAPI/i18n/th.json index 0c87c6cd..b9d2c54d 100644 --- a/src/SMAPI/i18n/th.json +++ b/src/SMAPI/i18n/th.json @@ -13,43 +13,43 @@ *********/ // TODO // 'SMAPI features' section - "config.section.features": "SMAPI features", + "config.section.features": "ฟีเจอร์ของ SMAPI", - "config.check-for-updates.name": "Check for updates", - "config.check-for-updates.desc": "Whether to automatically check for newer versions of SMAPI and mods when you load the game. If new versions are available, an alert will be shown in the console. This doesn't affect the load time even if your connection is offline or slow, because it happens in the background.", + "config.check-for-updates.name": "ตรวจสอบการอัปเดต", + "config.check-for-updates.desc": "กำหนดว่าจะให้ตรวจสอบเวอร์ชันใหม่ของ SMAPI และม็อดโดยอัตโนมัติเมื่อคุณโหลดเกมหรือไม่ หากมีเวอร์ชันใหม่ ระบบจะแสดงการแจ้งเตือนในคอนโซล การตั้งค่านี้จะไม่ส่งผลต่อเวลาในการโหลดเกม แม้ว่าการเชื่อมต่ออินเทอร์เน็ตของคุณจะออฟไลน์หรือช้าก็ตาม เนื่องจากการตรวจสอบจะทำงานอยู่เบื้องหลัง", - "config.check-content-integrity.name": "Check content integrity", - "config.check-content-integrity.desc": "Whether SMAPI should check whether the game's content files are present and unmodified. This should nearly always be enabled. If disabled, SMAPI will log a warning for visibility when someone helps you troubleshoot game issues.", + "config.check-content-integrity.name": "ตรวจสอบความสมบูรณ์ของไฟล์เนื้อหา", + "config.check-content-integrity.desc": "กำหนดว่า SMAPI ควรตรวจสอบว่าไฟล์เนื้อหาของเกมมีอยู่ครบและไม่ได้ถูกแก้ไขหรือไม่ โดยทั่วไปควรเปิดใช้งานตัวเลือกนี้เกือบตลอดเวลา หากปิดใช้งาน SMAPI จะบันทึกคำเตือนไว้ในบันทึก (log) เพื่อให้มองเห็นได้ชัดเจนเมื่อมีผู้ช่วยคุณแก้ไขปัญหาเกี่ยวกับเกม", - "config.read-console-input.name": "Read console input", - "config.read-console-input.desc": "Whether SMAPI should listen for console input. Disabling this will prevent you from using console commands. On some specific Linux systems, disabling this may reduce CPU usage.", + "config.read-console-input.name": "รับคำสั่งจากคอนโซล", + "config.read-console-input.desc": "กำหนดว่า SMAPI ควรรับคำสั่งจากคอนโซลหรือไม่ หากปิดใช้งาน คุณจะไม่สามารถใช้คำสั่งในคอนโซลได้ บนระบบ Linux บางประเภท การปิดใช้งานตัวเลือกนี้อาจช่วยลดการใช้ CPU ได้", // 'Console window' section - "config.section.console-window": "Console window", + "config.section.console-window": "หน้าต่างคอนโซล", - "config.developer-mode.name": "Developer mode", - "config.developer-mode.desc": "Whether to show much more info in the SMAPI consoler window, intended for mod developers. Not recommended for most players.", + "config.developer-mode.name": "โหมดนักพัฒนา", + "config.developer-mode.desc": "กำหนดว่าจะแสดงข้อมูลเพิ่มเติมจำนวนมากในหน้าต่างคอนโซลของ SMAPI หรือไม่ ซึ่งมีไว้สำหรับนักพัฒนาม็อด ไม่แนะนำสำหรับผู้เล่นส่วนใหญ่", - "config.color-scheme.name": "Color scheme", - "config.color-scheme.desc": "The color scheme to apply to text in the SMAPI console window. This has no effect on the game, mods, or SMAPI log file.", - "config.color-scheme.options.AutoDetect": "Auto-detect", - "config.color-scheme.options.AutoDetect.on-windows": "Auto-detect (recommended)", - "config.color-scheme.options.DarkBackground": "Lighter text (for dark backgrounds)", - "config.color-scheme.options.LightBackground": "Darker text (for light backgrounds)", - "config.color-scheme.options.None": "No colors", + "config.color-scheme.name": "ชุดรูปแบบสี", + "config.color-scheme.desc": "ชุดรูปแบบสีที่จะใช้กับข้อความในหน้าต่างคอนโซลของ SMAPI การตั้งค่านี้จะไม่มีผลต่อเกม ม็อด หรือไฟล์บันทึก (log) ของ SMAPI", + "config.color-scheme.options.AutoDetect": "ตรวจจับอัตโนมัติ", + "config.color-scheme.options.AutoDetect.on-windows": "ตรวจจับอัตโนมัติ (แนะนำ)", + "config.color-scheme.options.DarkBackground": "ข้อความสีอ่อน (สำหรับพื้นหลังสีเข้ม)", + "config.color-scheme.options.LightBackground": "ข้อความสีเข้ม (สำหรับพื้นหลังสีอ่อน)", + "config.color-scheme.options.None": "ไม่ใช้สี", // 'Verbose logging' section - "config.section.verbose-logs": "Verbose logs", - "config.section.verbose-logs.explanation": "To help troubleshoot, SMAPI and many mods can send extra info to the SMAPI log (called 'verbose logging'). This may cause performance issues, and should usually be disabled.", + "config.section.verbose-logs": "บันทึกข้อมูลแบบละเอียด", + "config.section.verbose-logs.explanation": "เพื่อช่วยในการแก้ไขปัญหา SMAPI และม็อดหลายตัวสามารถส่งข้อมูลเพิ่มเติมไปยังบันทึก (log) ของ SMAPI (เรียกว่า “การบันทึกแบบละเอียด” หรือ verbose logging) ได้ การเปิดใช้งานอาจส่งผลต่อประสิทธิภาพการทำงาน และโดยทั่วไปควรปิดไว้", - "config.enable-for.name": "Enable for", - "config.enable-for.desc": "Choose which mods have verbose logging enabled.", - "config.enable-for.options.all": "All (not recommended)", - "config.enable-for.options.selected": "Mods selected below", + "config.enable-for.name": "เปิดใช้งานสำหรับ", + "config.enable-for.desc": "เลือกม็อดที่ต้องการเปิดใช้งานการบันทึกแบบละเอียด (verbose logging)", + "config.enable-for.options.all": "ทั้งหมด (ไม่แนะนำ)", + "config.enable-for.options.selected": "ม็อดที่เลือกด้านล่าง", "config.enable-for-smapi.name": "SMAPI", - "config.enable-for-smapi.desc": "Whether to enable verbose logs for SMAPI itself.", + "config.enable-for-smapi.desc": "กำหนดว่าจะเปิดใช้งานการบันทึกแบบละเอียด (verbose logging) สำหรับตัว SMAPI เองหรือไม่", "config.enable-for-mod.name": "{{modName}}", - "config.enable-for-mod.desc": "Whether to enable verbose logs for the '{{modName}}' mod." + "config.enable-for-mod.desc": "กำหนดว่าจะเปิดใช้งานการบันทึกแบบละเอียด (verbose logging) สำหรับม็อด '{{modName}}' หรือไม่" } From 2c62785f4ead2e3d9254636f12706b83b7708330 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Thu, 5 Mar 2026 19:07:06 -0500 Subject: [PATCH 18/20] update translation docs --- docs/README.md | 11 +++++------ docs/release-notes.md | 4 ++-- src/SMAPI/i18n/th.json | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/docs/README.md b/docs/README.md index c60970f3..9971c9d7 100644 --- a/docs/README.md +++ b/docs/README.md @@ -52,13 +52,12 @@ developers and other modders! * [Technical docs](technical/smapi.md) ## Translating SMAPI -SMAPI rarely shows text in-game, so it only has a few translations. Contributions are welcome! See -[Modding:Translations](https://stardewvalleywiki.com/Modding:Translations) on the wiki for help -contributing translations. +Contributions are welcome! See [Modding:Translations](https://stardewvalleywiki.com/Modding:Translations) +on the wiki for help contributing translations. locale | status ----------- | :---------------- -default | ↻ [partly translated](../src/SMAPI/i18n/default.json) +default | ✓ [original text](../src/SMAPI/i18n/default.json) Chinese | ↻ [partly translated](../src/SMAPI/i18n/zh.json) French | ✓ [fully translated](../src/SMAPI/i18n/fr.json) German | ↻ [partly translated](../src/SMAPI/i18n/de.json) @@ -70,8 +69,8 @@ Korean | ↻ [partly translated](../src/SMAPI/i18n/ko.json) [Polish] | ↻ [partly translated](../src/SMAPI/i18n/pl.json) Portuguese | ✓ [fully translated](../src/SMAPI/i18n/pt.json) Russian | ✓ [fully translated](../src/SMAPI/i18n/ru.json) -Spanish | ↻ [partly translated](../src/SMAPI/i18n/es.json) -[Thai] | ↻ [partly translated](../src/SMAPI/i18n/th.json) +Spanish | ✓ [partly translated](../src/SMAPI/i18n/es.json) +[Thai] | ✓ [partly translated](../src/SMAPI/i18n/th.json) Turkish | ↻ [partly translated](../src/SMAPI/i18n/tr.json) [Ukrainian] | ↻ [partly translated](../src/SMAPI/i18n/uk.json) diff --git a/docs/release-notes.md b/docs/release-notes.md index 6efa5650..31ab71cd 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -6,8 +6,8 @@ * Minor performance optimizations. * Fixed the Linux/macOS installer not saving the color scheme correctly in 4.5.0+. * Fixed typo in config UI text (thanks to QuentiumYT!). - * Improved translations. Thanks to dewanggatrustha (updated Indonesian), QuentiumYT (updated French), and Timur13240 - (updated Russian)! + * Improved translations. Thanks to dekthaiinchina (updated Thai), dewanggatrustha (updated Indonesian), QuentiumYT (updated French), Timur13240 + (updated Russian), and vlcoo (updated Spanish)! * For mod authors: * Fixed input API ignoring controller overrides when there's no controller plugged in (thanks to spacechase0!). diff --git a/src/SMAPI/i18n/th.json b/src/SMAPI/i18n/th.json index b9d2c54d..3c321a0b 100644 --- a/src/SMAPI/i18n/th.json +++ b/src/SMAPI/i18n/th.json @@ -11,7 +11,6 @@ /********* ** Generic Mod Config Menu UI *********/ - // TODO // 'SMAPI features' section "config.section.features": "ฟีเจอร์ของ SMAPI", From 9746b01129c707c28618b771d55553a02d59571f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sun, 8 Mar 2026 21:05:50 -0400 Subject: [PATCH 19/20] update fridge position after patching a farmhouse map --- docs/release-notes.md | 1 + src/SMAPI/Metadata/CoreAssetPropagator.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/docs/release-notes.md b/docs/release-notes.md index 31ab71cd..73192317 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -5,6 +5,7 @@ * For players: * Minor performance optimizations. * Fixed the Linux/macOS installer not saving the color scheme correctly in 4.5.0+. + * Fixed farmhouse fridge when a mod dynamically adds it in later. * Fixed typo in config UI text (thanks to QuentiumYT!). * Improved translations. Thanks to dekthaiinchina (updated Thai), dewanggatrustha (updated Indonesian), QuentiumYT (updated French), Timur13240 (updated Russian), and vlcoo (updated Spanish)! diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs index ef8abc73..d810a955 100644 --- a/src/SMAPI/Metadata/CoreAssetPropagator.cs +++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs @@ -705,6 +705,18 @@ internal class CoreAssetPropagator this.Reflection.GetField(location, "displayingSpouseRoom").SetValue(false); location.MakeMapModifications(force: true); + // update fridge position + switch (location) + { + case FarmHouse farmhouse: + farmhouse.fridgePosition = farmhouse.GetFridgePositionFromMap() ?? Point.Zero; + break; + + case IslandFarmHouse farmhouse: + farmhouse.fridgePosition = farmhouse.GetFridgePositionFromMap() ?? Point.Zero; + break; + } + // reset player position // The game may move the player as part of the map changes, even if they're not in that // location. That's not needed in this case, and it can have weird effects like players From 13c4c1c44fe7c1456dd3c2a961384cefe0706f0a Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 14 Mar 2026 14:49:17 -0400 Subject: [PATCH 20/20] prepare for release --- build/common.targets | 2 +- docs/release-notes.md | 8 +++++--- src/SMAPI.Mods.ConsoleCommands/manifest.json | 4 ++-- src/SMAPI.Mods.SaveBackup/manifest.json | 4 ++-- src/SMAPI/Constants.cs | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/build/common.targets b/build/common.targets index 8f21cd76..779007b4 100644 --- a/build/common.targets +++ b/build/common.targets @@ -7,7 +7,7 @@ repo. It imports the other MSBuild files as needed. - 4.5.1 + 4.5.2 SMAPI latest $(AssemblySearchPaths);{GAC} diff --git a/docs/release-notes.md b/docs/release-notes.md index 73192317..2558c882 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,17 +1,19 @@ ← [README](README.md) # Release notes -## Upcoming release +## 4.5.2 +Released 14 March 2026 for Stardew Valley 1.6.14 or later. + * For players: - * Minor performance optimizations. + * Improved performance a bit. * Fixed the Linux/macOS installer not saving the color scheme correctly in 4.5.0+. - * Fixed farmhouse fridge when a mod dynamically adds it in later. * Fixed typo in config UI text (thanks to QuentiumYT!). * Improved translations. Thanks to dekthaiinchina (updated Thai), dewanggatrustha (updated Indonesian), QuentiumYT (updated French), Timur13240 (updated Russian), and vlcoo (updated Spanish)! * For mod authors: * Fixed input API ignoring controller overrides when there's no controller plugged in (thanks to spacechase0!). + * Fixed asset propagation for the farmhouse map not updating the farmhouse fridge position. ## 4.5.1 Released 25 January 2026 for Stardew Valley 1.6.14 or later. See [build attestation](https://github.com/Pathoschild/SMAPI/attestations/17385144). diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index e66e2f11..de884e6c 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,9 +1,9 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "4.5.1", + "Version": "4.5.2", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueId": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "4.5.1" + "MinimumApiVersion": "4.5.2" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 40436da4..40035e52 100644 --- a/src/SMAPI.Mods.SaveBackup/manifest.json +++ b/src/SMAPI.Mods.SaveBackup/manifest.json @@ -1,9 +1,9 @@ { "Name": "Save Backup", "Author": "SMAPI", - "Version": "4.5.1", + "Version": "4.5.2", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueId": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "4.5.1" + "MinimumApiVersion": "4.5.2" } diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index eeb22a88..89012a19 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -49,7 +49,7 @@ internal static class EarlyConstants internal static int? LogScreenId { get; set; } /// SMAPI's current raw semantic version. - internal static string RawApiVersion = "4.5.1"; + internal static string RawApiVersion = "4.5.2"; } /// Contains SMAPI's constants and assumptions.