From 5386c7ac8af2a2c24ea239a3f8ee2b128729e727 Mon Sep 17 00:00:00 2001 From: koka Date: Sun, 30 Aug 2026 15:09:01 +0200 Subject: [PATCH] fix(sanctuary): simplifier le suivi de quetes --- CHANGELOG.md | 3 +- build.gradle | 26 +++++------ gradle.properties | 2 +- sanctuary/build.gradle | 22 ++++----- .../sanctuary/client/QuestTrackerHud.java | 46 +++++-------------- .../assets/sanctuary/lang/en_us.json | 2 - .../assets/sanctuary/lang/fr_fr.json | 2 - .../assets/sanctuary/lang/ru_ru.json | 2 - 8 files changed, 38 insertions(+), 67 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04e373a..1500ed4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ Ce journal suit les **versions du modpack**. Lorsqu'un seul module change, sa ve ## Non distribué -Module modifié : **Sanctuary `0.0.0-alpha.123`**. Le pack public reste temporairement en `26.2.0-alpha.221` jusqu'à la publication. +Module modifié : **Sanctuary `0.0.0-alpha.124`**. Le pack public reste temporairement en `26.2.0-alpha.221` jusqu'à la publication. - ajoute un suivi d'avancement des quêtes, affichable ou masquable par une touche configurable (`J` par défaut) ; +- affiche chaque quête active comme un simple texte ombré en haut à gauche, sans panneau, bordure, titre, message vide ni barre de progression ; - synchronise un snapshot borné des quêtes acceptées et des contrats réservés, sans les demandes que le joueur a lui-même créées, ni changer les données Sanctuary v11 ni le protocole réseau 22 ; - propose une saisie assistée des IDs d'item et de mob dans l'éditeur de demande, avec icône et noms proches. diff --git a/build.gradle b/build.gradle index 2301090..1bf40ca 100644 --- a/build.gradle +++ b/build.gradle @@ -3438,7 +3438,7 @@ tasks.register("verifyProgressivePauseMenuRelease") { "sanctuary/src/main/resources/assets/sanctuary/lang/${locale}.json"))] } if (rootProject.pack_version != "26.2.0-alpha.221" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || rootProject.onlyfun_version != "0.0.0-alpha.25" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.modules != [sanctuary: "0.0.0-alpha.108", onlyfun: "0.0.0-alpha.17"] @@ -4279,7 +4279,7 @@ tasks.register("verifyShopPricingLayoutRelease") { def index = new JsonSlurper().parse(file("pack/prism/modrinth.index.json")) if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.onlyfun_version != "0.0.0-alpha.25" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.192" || migration.target?.pack_version != "26.2.0-alpha.193" @@ -4373,7 +4373,7 @@ tasks.register("verifyShopCsvBossGatesRelease") { def offerCatalog = file("sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.onlyfun_version != "0.0.0-alpha.25" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || release.pack_version != rootProject.pack_version || index.versionId != rootProject.pack_version || migration.source?.pack_version != "26.2.0-alpha.194" || migration.source?.modules != [onlyfun: "0.0.0-alpha.18", sanctuary: "0.0.0-alpha.110"] @@ -4465,7 +4465,7 @@ tasks.register("verifyQuestRequestsCauldronBatchesRelease") { def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.itsalive_version != "0.0.0-alpha.36" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.196" || migration.target?.pack_version != "26.2.0-alpha.197" || migration.target?.modules != [itsalive: "0.0.0-alpha.29", sanctuary: "0.0.0-alpha.113"] @@ -4565,7 +4565,7 @@ tasks.register("verifyQuestRequestContractsRelease") { def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.itsalive_version != "0.0.0-alpha.36" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.198" || migration.source?.modules?.sanctuary != "0.0.0-alpha.114" || migration.target?.pack_version != "26.2.0-alpha.199" @@ -4685,7 +4685,7 @@ tasks.register("verifyQuestRequestEscrowRelease") { def packwizIndex = file("pack/packwiz/index.toml").text def sanctuaryManifest = new JsonSlurper().parse(file("sanctuary/src/main/resources/fabric.mod.json")) if (rootProject.pack_version != "26.2.0-alpha.221" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.200" || migration.source?.modules?.sanctuary != "0.0.0-alpha.115" || migration.target?.pack_version != "26.2.0-alpha.201" @@ -4742,7 +4742,7 @@ tasks.register("verifyWaystoneShopCulinaryAlpha202Release") { || rootProject.anotherworld_version != "0.0.0-alpha.55" || rootProject.itsalive_version != "0.0.0-alpha.36" || rootProject.iliketomoveit_version != "0.0.0-alpha.16" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.201" || migration.source?.modules != [ itsalive: "0.0.0-alpha.30", @@ -4900,7 +4900,7 @@ tasks.register("verifySafeVaultFeature") { }.keySet() if (rootProject.pack_version != "26.2.0-alpha.221" || rootProject.anotherworld_version != "0.0.0-alpha.55" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.schema_version != 1 || migration.source?.pack_version != "26.2.0-alpha.201" || migration.target?.pack_version != "26.2.0-alpha.202" @@ -5759,7 +5759,7 @@ tasks.register("verifyAlpha210Release") { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" } if (rootProject.pack_version != "26.2.0-alpha.221" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || rootProject.onlyfun_version != "0.0.0-alpha.25" || rootProject.iliketomoveit_version != currentModules.iliketomoveit || rootProject.itsalive_version != "0.0.0-alpha.36" @@ -5858,7 +5858,7 @@ tasks.register("verifyAlpha211Release") { onlyfun: "0.0.0-alpha.25", ambiance: "0.0.0-alpha.22", iliketomoveit: "0.0.0-alpha.16"] - def workspaceModules = currentModules + [sanctuary: "0.0.0-alpha.123"] + def workspaceModules = currentModules + [sanctuary: "0.0.0-alpha.124"] def expectedDataVersions = [ambiance: 2, itsalive: 3, onlyfun: 2, ouch: 1, sanctuary: 11] def expectedProtocols = [ambiance: 6, itsalive: 4, onlyfun: 3, ouch: 1, sanctuary: 22] def manifests = expectedTarget.collectEntries { id, version -> @@ -5956,7 +5956,7 @@ tasks.register("verifyAlpha212Release") { it.path == "mods/jei-26.2-fabric-30.28.0.193.jar" } if (rootProject.pack_version != "26.2.0-alpha.221" - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.211" || migration.source?.modules != [sanctuary: "0.0.0-alpha.119"] || migration.target?.pack_version != "26.2.0-alpha.212" @@ -6449,7 +6449,7 @@ tasks.register("verifyAlpha218Release") { || currentModules.findAll { id, version -> id != "redstoner" && id != "sanctuary" }.any { id, version -> rootProject.property("${id}_version") != version } - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.217" || migration.source?.modules != sourceModules || migration.target?.pack_version != "26.2.0-alpha.218" @@ -6550,7 +6550,7 @@ tasks.register("verifyAlpha219Release") { || currentModules.findAll { id, version -> id != "sanctuary" }.any { id, version -> rootProject.property("${id}_version") != version } - || rootProject.sanctuary_version != "0.0.0-alpha.123" + || rootProject.sanctuary_version != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.218" || migration.source?.modules != sourceModules || migration.target?.pack_version != "26.2.0-alpha.219" diff --git a/gradle.properties b/gradle.properties index 361eb69..ba8df42 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,7 +28,7 @@ iliketomoveit_version=0.0.0-alpha.16 iliketomoveit_lifecycle=active onlyfun_version=0.0.0-alpha.25 onlyfun_lifecycle=active -sanctuary_version=0.0.0-alpha.123 +sanctuary_version=0.0.0-alpha.124 sanctuary_lifecycle=active pack_version=26.2.0-alpha.221 maven_group=fr.koka99cab.sanctuary26 diff --git a/sanctuary/build.gradle b/sanctuary/build.gradle index 9747572..6d82037 100644 --- a/sanctuary/build.gradle +++ b/sanctuary/build.gradle @@ -151,7 +151,7 @@ tasks.register("verifyBlackMarket") { def questData = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardData.java").text def quests = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/QuestBoardService.java").text def inventoryView = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/api/inventory/SanctuaryPlayerInventoryView.java").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || !data.contains('SAVE_KEY = "black_market"') || !data.contains("DATA_VERSION = 2") || !data.contains("ItemStack.CODEC.fieldOf(\"item\")") || !data.contains("replaceListing") || !service.contains("LISTING_FEE_RUBIES = 1") || !service.contains("COMMISSION_PERCENT = 5") @@ -2850,7 +2850,7 @@ tasks.register("verifyShopCurrencyRowsRelease") { "src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/BlackMarketService.java").text def shop = file( "src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopService.java").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.modules?.sanctuary != "0.0.0-alpha.117" || migration.shop_currency_inventory?.all_unlocked_rows_counted != true || migration.shop_currency_inventory?.overflow_rows_counted != true @@ -3016,7 +3016,7 @@ tasks.register("verifyProgressivePauseMenu") { "pack/migrations/26.2.0-alpha.190-progressive-pause-menu-to-alpha.191.json")) def pauseMenu = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/PauseScreenMixin.java").text def costs = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/progression/SanctuaryProgressionCosts.java").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.pack_version != "26.2.0-alpha.191" || migration.target?.modules?.sanctuary != "0.0.0-alpha.109" || migration.pause_menu?.progression_full_width != true @@ -3054,7 +3054,7 @@ tasks.register("verifyShopPricingLayout") { "pack/migrations/26.2.0-alpha.192-shop-pricing-layout-to-alpha.193.json")) def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/SanctuaryShopScreen.java").text def progression = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopProgression.java").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.modules?.sanctuary != "0.0.0-alpha.110" || migration.shop_layout?.locked_offer_buttons != 6 || migration.shop_layout?.button_slots != [4, 5, 6, 7, 8, 9] @@ -3085,7 +3085,7 @@ tasks.register("verifyShopCsvBossGates") { "pack/migrations/26.2.0-alpha.194-shop-csv-boss-gates-to-alpha.195.json")) def provider = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopCatalogProvider.java").text def catalog = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/shop/ShopOfferCatalog.java").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.pack_version != "26.2.0-alpha.195" || migration.target?.modules?.sanctuary != "0.0.0-alpha.111" || migration.compatibility?.sanctuary_data_version != 11 @@ -3116,7 +3116,7 @@ tasks.register("verifyDeliveryBoxOrientation") { def blockstate = new JsonSlurper().parse( file("src/main/resources/assets/sanctuary/blockstates/delivery_box.json")) def expectedVariants = ["facing=north", "facing=east", "facing=south", "facing=west"].toSet() - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.modules?.sanctuary != "0.0.0-alpha.112" || migration.mailbox?.id != "sanctuary:delivery_box" || migration.mailbox?.horizontal_facing != true @@ -3144,7 +3144,7 @@ tasks.register("verifyInventoryShiftClick") { def mixin = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/AbstractContainerMenuMixin.java").text def screen = file("src/main/java/fr/koka99cab/sanctuary26/sanctuary/mixin/client/AbstractContainerScreenMixin.java").text def gui = file("INVENTORY_GUI.md").text - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || !transfer.contains("shouldAppendOverflow") || !transfer.contains("isVanillaStorageRange") || !transfer.contains("hotbarStart") @@ -3190,7 +3190,7 @@ tasks.register("verifyQuestRequests") { new JsonSlurper().parse(file("src/main/resources/data/sanctuary/loot_table/blocks/${path}.json")) .pools[0].entries[0].name } - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.modules?.sanctuary != "0.0.0-alpha.113" || migration.quest_requests?.save_key != "quest_requests" || migration.quest_requests?.data_version != 1 @@ -3248,7 +3248,7 @@ tasks.register("verifyQuestRequestContracts") { def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale -> [(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))] } - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.198" || migration.source?.modules?.sanctuary != "0.0.0-alpha.114" || migration.target?.pack_version != "26.2.0-alpha.199" @@ -3317,7 +3317,7 @@ tasks.register("verifyQuestRequestEscrow") { def locales = ["fr_fr", "en_us", "ru_ru"].collectEntries { locale -> [(locale): new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${locale}.json"))] } - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.source?.pack_version != "26.2.0-alpha.200" || migration.source?.modules?.sanctuary != "0.0.0-alpha.115" || migration.target?.pack_version != "26.2.0-alpha.201" @@ -3389,7 +3389,7 @@ tasks.register("verifyAlphaIndev") { def locales = ["fr_fr", "en_us", "ru_ru"].collect { new JsonSlurper().parse(file("src/main/resources/assets/sanctuary/lang/${it}.json")) } - if (project.version.toString() != "0.0.0-alpha.123" + if (project.version.toString() != "0.0.0-alpha.124" || migration.target?.modules?.sanctuary != "0.0.0-alpha.122" || migration.alpha_world?.dimension != "sanctuary:alpha" || migration.alpha_world?.legacy_dimension != "portals:alpha" diff --git a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/QuestTrackerHud.java b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/QuestTrackerHud.java index 80d42c5..7934e29 100644 --- a/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/QuestTrackerHud.java +++ b/sanctuary/src/main/java/fr/koka99cab/sanctuary26/sanctuary/client/QuestTrackerHud.java @@ -14,19 +14,12 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.Identifier; import net.minecraft.world.item.ItemStack; -/** Compact toggleable overlay for accepted quests. */ +/** Transparent, toggleable text overlay for accepted quests. */ final class QuestTrackerHud { - private static final int PANEL_WIDTH = 168; - private static final int MARGIN = 6; - private static final int HEADER_HEIGHT = 14; - private static final int ENTRY_HEIGHT = 22; - private static final int EMPTY_HEIGHT = 22; - private static final int BACKGROUND = 0xD0181417; - private static final int OUTLINE = 0xFFE8A8C3; - private static final int TITLE = 0xFFF2C4D7; + private static final int MAX_WIDTH = 240; + private static final int MARGIN = 2; + private static final int ENTRY_SPACING = 2; private static final int BODY = 0xFFE9DDE2; - private static final int MUTED = 0xFF9F8B95; - private static final int BAR_BACK = 0xFF3A2A30; private QuestTrackerHud() {} @@ -39,39 +32,22 @@ final class QuestTrackerHud { if (client.player == null || client.level == null || client.gui.screen() != null) return; if (!SanctuaryClientQuests.visible()) return; List entries = SanctuaryClientQuests.entries(); - int height = HEADER_HEIGHT + 6 + (entries.isEmpty() ? EMPTY_HEIGHT : entries.size() * ENTRY_HEIGHT); - int left = MARGIN; - int top = MARGIN; - int right = left + PANEL_WIDTH; - int bottom = top + height; - graphics.fill(left, top, right, bottom, BACKGROUND); - graphics.outline(left, top, PANEL_WIDTH, height, OUTLINE); - graphics.text(client.font, Component.translatable("hud.sanctuary.quest_tracker.title"), - left + 6, top + 4, TITLE); - if (entries.isEmpty()) { - graphics.text(client.font, Component.translatable("hud.sanctuary.quest_tracker.empty"), - left + 6, top + HEADER_HEIGHT + 4, MUTED); - return; - } - int y = top + HEADER_HEIGHT + 2; + if (entries.isEmpty()) return; + int width = Math.max(1, Math.min(MAX_WIDTH, graphics.guiWidth() - MARGIN * 2)); + int y = MARGIN; for (QuestTrackerSnapshotPayload.Entry entry : entries) { - drawEntry(graphics, client.font, entry, left + 6, y, PANEL_WIDTH - 12); - y += ENTRY_HEIGHT; + drawEntry(graphics, client.font, entry, MARGIN, y, width); + y += client.font.lineHeight * 2 + ENTRY_SPACING; } } private static void drawEntry(GuiGraphicsExtractor graphics, Font font, QuestTrackerSnapshotPayload.Entry entry, int x, int y, int width) { int accent = 0xFF000000 | (entry.accent() & 0xFFFFFF); - graphics.text(font, ellipsize(font, title(entry), width), x, y, accent); + graphics.text(font, ellipsize(font, title(entry), width), x, y, accent, true); Component progress = Component.translatable("hud.sanctuary.quest_tracker.progress", action(entry), describeTarget(entry), entry.progress(), entry.required()); - graphics.text(font, ellipsize(font, progress, width), x, y + 9, BODY); - int barTop = y + 18; - int barRight = x + width; - graphics.fill(x, barTop, barRight, barTop + 2, BAR_BACK); - int filled = Math.round(width * Math.min(1.0F, entry.progress() / (float) entry.required())); - if (filled > 0) graphics.fill(x, barTop, x + filled, barTop + 2, accent); + graphics.text(font, ellipsize(font, progress, width), x, y + font.lineHeight, BODY, true); } private static Component title(QuestTrackerSnapshotPayload.Entry entry) { diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json b/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json index c745088..341de47 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/en_us.json @@ -244,8 +244,6 @@ "key.sanctuary.zoom": "Telephoto zoom", "key.sanctuary.switch_hotbar_row": "Cycle hotbar row", "key.sanctuary.quest_tracker": "Quest tracker", - "hud.sanctuary.quest_tracker.title": "Quests", - "hud.sanctuary.quest_tracker.empty": "No quest in progress", "hud.sanctuary.quest_tracker.toggle_on": "Quest tracker shown", "hud.sanctuary.quest_tracker.toggle_off": "Quest tracker hidden", "hud.sanctuary.quest_tracker.source.request": "Accepted request", diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json b/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json index 85ad3f6..ae46910 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/fr_fr.json @@ -244,8 +244,6 @@ "key.sanctuary.zoom": "Zoom téléobjectif", "key.sanctuary.switch_hotbar_row": "Changer de rangée de hotbar", "key.sanctuary.quest_tracker": "Suivi des quêtes", - "hud.sanctuary.quest_tracker.title": "Quêtes", - "hud.sanctuary.quest_tracker.empty": "Aucune quête en cours", "hud.sanctuary.quest_tracker.toggle_on": "Suivi des quêtes affiché", "hud.sanctuary.quest_tracker.toggle_off": "Suivi des quêtes masqué", "hud.sanctuary.quest_tracker.source.request": "Demande acceptée", diff --git a/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json b/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json index 0cb770b..0e47ea1 100644 --- a/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json +++ b/sanctuary/src/main/resources/assets/sanctuary/lang/ru_ru.json @@ -156,8 +156,6 @@ "key.sanctuary.zoom": "Телефото-зум", "key.sanctuary.switch_hotbar_row": "Сменить ряд панели быстрого доступа", "key.sanctuary.quest_tracker": "Трекер заданий", - "hud.sanctuary.quest_tracker.title": "Задания", - "hud.sanctuary.quest_tracker.empty": "Нет активного задания", "hud.sanctuary.quest_tracker.toggle_on": "Трекер заданий показан", "hud.sanctuary.quest_tracker.toggle_off": "Трекер заданий скрыт", "hud.sanctuary.quest_tracker.source.request": "Принятый запрос", -- 2.54.0