From 3a712cdfe0088400e9d48d69639adc2c4039a8e3 Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Mon, 7 Sep 2026 22:40:38 +0100 Subject: [PATCH 1/8] fix: Syncing resource packs doesn't work Fixes #7441 --- .../instances/instances-synced-settings/index.vue | 8 ++++---- .../src/api/instance/synced_packs/operations.rs | 12 +++++++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/app-frontend/src/components/ui/settings/instances/instances-synced-settings/index.vue b/apps/app-frontend/src/components/ui/settings/instances/instances-synced-settings/index.vue index 5482bbf067..b169a6611d 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/instances-synced-settings/index.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/instances-synced-settings/index.vue @@ -272,13 +272,13 @@ const baseSourcesLoading = computed(() => baseOption.value === null ? false : baseOption.value === 'game_options' - ? gameOptionSourcesQuery.isFetching.value - : instancesQuery.isFetching.value, + ? gameOptionSourcesQuery.isPending.value + : instancesQuery.isPending.value, ) const baseSourcesError = computed(() => baseOption.value === 'game_options' - ? gameOptionSourcesQuery.isError.value - : instancesQuery.isError.value, + ? gameOptionSourcesQuery.isError.value && !gameOptionSourcesQuery.data.value + : instancesQuery.isError.value && !instancesQuery.data.value, ) let baseSourceGeneration = 0 diff --git a/packages/app-lib/src/api/instance/synced_packs/operations.rs b/packages/app-lib/src/api/instance/synced_packs/operations.rs index 51d1bac671..500ce8f9d2 100644 --- a/packages/app-lib/src/api/instance/synced_packs/operations.rs +++ b/packages/app-lib/src/api/instance/synced_packs/operations.rs @@ -293,7 +293,17 @@ pub(in crate::api::instance) async fn seed_from_instance( { continue; } - let candidate = pack_from_item(item.clone(), metadata, state).await?; + let candidate = match pack_from_item(item.clone(), metadata, state).await { + Ok(candidate) => candidate, + Err(error) if matches!(error.raw.as_ref(), crate::ErrorKind::JSONError(_)) => { + tracing::warn!( + "Skipping pack {} from instance {instance_id} while initializing pack sync because its JSON metadata could not be parsed: {error}", + item.file_path + ); + continue; + } + Err(error) => return Err(error), + }; candidates.push((item, candidate)); } From 00c9237fee96f77e15be064aa7a76a355a1acc0c Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Mon, 7 Sep 2026 22:41:00 +0100 Subject: [PATCH 2/8] fix: clamp --- packages/ui/src/components/base/Slider.vue | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/components/base/Slider.vue b/packages/ui/src/components/base/Slider.vue index 6cefe674fc..da817afad6 100644 --- a/packages/ui/src/components/base/Slider.vue +++ b/packages/ui/src/components/base/Slider.vue @@ -66,7 +66,7 @@ :min="min" :max="max" :step="step" - @change="onInput(($event.target as HTMLInputElement).value)" + @change="onInput" /> @@ -169,8 +169,10 @@ function onInputWithSnap(value: string) { inputValueValid(parsedValue) } -function onInput(value: string) { - inputValueValid(Number.parseFloat(value)) +function onInput(event: Event) { + const target = event.target as HTMLInputElement + inputValueValid(target.valueAsNumber) + target.value = currentValue.value === null ? '' : String(currentValue.value) } From 020f566cf3224dee3e80f4a22d6f262a59e63ffd Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Tue, 8 Sep 2026 09:02:10 +0100 Subject: [PATCH 3/8] fix: various issues --- apps/app-frontend/src/App.vue | 8 +- .../components/ui/QuickInstanceSwitcher.vue | 110 +++++++------ .../ui/library/instance-group/index.vue | 2 +- .../instances/game-settings-modal/editors.ts | 9 +- .../game-settings-modal/languages.ts | 152 ++++++++++++++++++ .../instances/game-settings-modal/row.vue | 25 ++- .../instances-synced-settings/index.vue | 2 +- .../launch-options.vue | 2 + apps/app-frontend/src/pages/Screenshots.vue | 4 +- .../settings-modal/java-settings.vue | 2 + .../game_options/catalog/version_changes.rs | 41 ++--- packages/ui/src/components/base/Slider.vue | 17 +- 12 files changed, 279 insertions(+), 95 deletions(-) create mode 100644 apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index 52f7a10e15..985e7e2e5a 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -2216,7 +2216,6 @@ provideAppUpdateDownloadProgress(appUpdateDownload) > -
:deep(*) { + flex-shrink: 0; + } } .app-grid-statusbar { diff --git a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue index 7387eaca6a..00a6df686b 100644 --- a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue +++ b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue @@ -27,7 +27,6 @@ import { showInstanceInFolder } from '@/helpers/utils' import { instanceListQueryOptions } from '@/pages/instance/query-options' const ITEM_SIZE = 52 -const APPROX_USED_VERTICAL_SPACE = 475 // doesn't need to be exact lol just close enough so there's a little gap and no overflow const { handleError } = injectNotificationManager() const instancesQuery = useQuery(instanceListQueryOptions()) const router = useRouter() @@ -36,6 +35,8 @@ const runningInstances = ref([]) const { formatMessage } = useVIntl() +const container = ref() +let resizeObserver const maxAuto = ref(0) const allInstances = computed(() => (instancesQuery.data.value ?? []).slice().sort((a, b) => { @@ -69,9 +70,13 @@ const canDrag = computed(() => maxVisible.value > 0) const showOverdrag = ref(false) const updateMaxAuto = () => { + if (!container.value) return + const rem = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) + const dividerHeight = rem + 1 + const gap = rem / 4 maxAuto.value = Math.max( 0, - Math.floor((window.innerHeight - APPROX_USED_VERTICAL_SPACE) / ITEM_SIZE), + Math.floor((container.value.clientHeight - 2 * dividerHeight - gap) / (3 * rem + gap)), ) } @@ -154,17 +159,18 @@ const onDividerPointerUp = (event) => { } await instancesQuery.suspense().catch(handleError) -updateMaxAuto() useAppEvent('process', checkProcesses) onMounted(() => { - window.addEventListener('resize', updateMaxAuto) + resizeObserver = new ResizeObserver(updateMaxAuto) + resizeObserver.observe(container.value) + updateMaxAuto() checkProcesses() }) onUnmounted(() => { - window.removeEventListener('resize', updateMaxAuto) + resizeObserver?.disconnect() document.body.classList.remove('quick-instance-dragging') clearOverdragFlash() }) @@ -264,55 +270,57 @@ function openContextMenu(event, instance) { diff --git a/apps/app-frontend/src/components/ui/library/instance-group/index.vue b/apps/app-frontend/src/components/ui/library/instance-group/index.vue index 8662927fd1..5c3b681f20 100644 --- a/apps/app-frontend/src/components/ui/library/instance-group/index.vue +++ b/apps/app-frontend/src/components/ui/library/instance-group/index.vue @@ -128,7 +128,7 @@ const cardWidth = computed( () => (gridWidth.value - gap.value * (columnCount.value - 1)) / columnCount.value, ) const cardHeight = computed(() => - compactMode.value ? remSize.value * 3.875 : Math.max(0, cardWidth.value) + remSize.value * 3.375, + compactMode.value ? remSize.value * 3.875 + 2 : Math.max(0, cardWidth.value) + remSize.value * 3.375, ) const gridHeight = computed(() => Math.max( diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts index 0ccd80d64d..abb206dd2c 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts @@ -64,6 +64,11 @@ export function gameSettingChanges( }) } +export function gameSettingNumberScale(setting: EditableGameSetting): number { + if (setting.editor.unit !== 'percent') return 1 + return setting.option_id === 'sensitivity' ? 200 : 100 +} + export function canonicalValueText(setting: EditableGameSetting): string { const value = setting.canonical_value if (!value) return '' @@ -74,7 +79,7 @@ export function canonicalValueText(setting: EditableGameSetting): string { case 'integer': case 'decimal': return setting.editor.unit === 'percent' - ? String(Number((Number(value.value) * 100).toFixed(8))) + ? String(Number((Number(value.value) * gameSettingNumberScale(setting)).toFixed(8))) : String(value.value) case 'string_list': return value.value.join(', ') @@ -114,7 +119,7 @@ export function canonicalValueFromInput( type: 'decimal', value: setting.editor.unit === 'percent' - ? String(Number((parsed / 100).toFixed(8))) + ? String(Number((parsed / gameSettingNumberScale(setting)).toFixed(8))) : String(value), } } diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts new file mode 100644 index 0000000000..34fd106378 --- /dev/null +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts @@ -0,0 +1,152 @@ +import type { ComboboxOption } from '@modrinth/ui' + +/** Java Edition language names and regions from https://github.com/misode/mcmeta/blob/assets/pack.mcmeta. */ +const languageNames: Record = { + en_us: 'English (US)', + af_za: 'Afrikaans (Suid-Afrika)', + esan: 'Andalûh (Andaluçía)', + enp: 'Anglish (Oned Riches)', + ast_es: 'Asturianu (Asturies)', + az_az: 'Azərbaycanca (Azərbaycan)', + id_id: 'Bahasa Indonesia (Indonesia)', + ms_my: 'Bahasa Melayu (Malaysia)', + tzo_mx: 'Bats\'i k\'op (Jobel)', + qid: 'Bhs. Indonesia edjaän lama (Indonesia tempo doeloe)', + be_latn: 'Biełaruskaja (Biełaruś)', + bar: 'Boarisch (Bayern)', + bs_ba: 'Bosanski (Bosna i Hercegovina)', + brb: 'Braobans (Braobant)', + br_fr: 'Brezhoneg (Breizh)', + ca_es: 'Català (Catalunya)', + val_es: 'Català (Valencià) (País Valencià)', + cy_gb: 'Cymraeg (Cymru)', + qcb_es: 'Cántabru/Montañés (Cantabria)', + da_dk: 'Dansk (Danmark)', + se_no: 'Davvisámegiella (Sápmi)', + de_at: 'Deitsch (Österreich)', + de_de: 'Deutsch (Deutschland)', + et_ee: 'Eesti keel (Eesti)', + en_au: 'English (Australia)', + en_ca: 'English (Canada)', + en_nz: 'English (New Zealand)', + en_gb: 'English (United Kingdom)', + es_ar: 'Español (Argentina)', + es_cl: 'Español (Chile)', + es_ec: 'Español (Ecuador)', + es_es: 'Español (España)', + es_mx: 'Español (México)', + es_uy: 'Español (Uruguay)', + es_ve: 'Español (Venezuela)', + eo_uy: 'Esperanto (Esperantujo)', + eu_es: 'Euskara (Euskal Herria)', + fil_ph: 'Filipino (Pilipinas)', + fr_ca: 'Français (Canada)', + fr_fr: 'Français (France)', + fr_ch: 'Français (Suisse)', + fy_nl: 'Frysk (Fryslân)', + fra_de: 'Fränggisch (Franggn)', + fur_it: 'Furlan (Friûl)', + fo_fo: 'Føroyskt (Føroyar)', + ga_ie: 'Gaeilge (Éire)', + gl_es: 'Galego (Galicia / Galiza)', + go_fr: 'Galo (Bertègn)', + gd_gb: 'Gàidhlig (Alba)', + hr_hr: 'Hrvatski (Hrvatska)', + hn_no: 'Høgnorsk (Norig)', + io_en: 'Ido (Idia)', + ig_ng: 'Igbo (Naigeria)', + it_it: 'Italiano (Italia)', + kw_gb: 'Kernewek (Kernow)', + ksh: 'Kölsch/Ripoarisch (Rhingland)', + lol_us: 'LOLCAT (Kingdom of Cats)', + la_la: 'Latina (Latium)', + lv_lv: 'Latviešu (Latvija)', + lt_lt: 'Lietuvių (Lietuva)', + li_li: 'Limburgs (Limburg)', + lmo: 'Lombard (Lombardia)', + lb_lu: 'Lëtzebuergesch (Lëtzebuerg)', + hu_hu: 'Magyar (Magyarország)', + mt_mt: 'Malti (Malta)', + isv: 'Medžuslovjansky (Slovjanščina)', + nah: 'Mēxikatlahtōlli (Mēxiko)', + nl_nl: 'Nederlands (Nederland)', + pls: 'Ngiiwà (Ndanìꞌngà)', + no_no: 'Norsk bokmål (Norge)', + nn_no: 'Norsk nynorsk (Noreg)', + uz_uz: 'O\'zbekcha (O\'zbekiston)', + oc_fr: 'Occitan (Occitània)', + en_pt: 'Pirate Speak (The Seven Seas)', + nds_de: 'Plattdüütsch (Düütschland)', + pl_pl: 'Polski (Polska)', + pt_br: 'Português (Brasil)', + pt_pt: 'Português (Portugal)', + qya_aa: 'Quenya (Arda)', + ro_ro: 'Română (România)', + de_ch: 'Schwiizerdütsch (Schwiiz)', + enws: 'Shakespearean English (Kingdom of England)', + sq_al: 'Shqip (Shqipëri)', + sk_sk: 'Slovenčina (Slovensko)', + sl_si: 'Slovenščina (Slovenija)', + so_so: 'Soomaali (Soomaaliya)', + sr_cs: 'Srpski (Srbija)', + fi_fi: 'Suomi (Suomi)', + sv_se: 'Svenska (Sverige)', + sxu: 'Säggs’sch (Saggsn)', + tl_ph: 'Tagalog (Pilipinas)', + vi_vn: 'Tiếng Việt (Việt Nam)', + tr_tr: 'Türkçe (Türkiye)', + vp_vl: 'Viossa (Vilant)', + nl_be: 'Vlaams (België)', + vec_it: 'Vèneto (Veneto)', + vro: 'Võro (Eesti)', + yo_ng: 'Yorùbá (Nàìjíríà)', + jbo_en: 'la .lojban. (la jbogu\'e)', + tlh_aa: 'tlhIngan Hol (tlhIngan wo\')', + tok: 'toki pona (kulupu pona)', + is_is: 'Íslenska (Ísland)', + ovd: 'Övdalska (Swerre)', + cs_cz: 'Čeština (Česko)', + szl: 'Ślōnski (Gōrny Ślōnsk)', + en_ud: 'ɥsᴉꞁᵷuƎ (uʍoᗡ ǝpᴉsd∩)', + haw_us: 'ʻŌlelo Hawaiʻi (Hawaiʻi)', + el_gr: 'Ελληνικά (Ελλάδα)', + ba_ru: 'Башҡортса (Башҡортостан, Рәсәй)', + be_by: 'Беларуская (Беларусь)', + bg_bg: 'Български (България)', + hal_ua: 'Галицка (Галичина, Вкраїна)', + ky_kg: 'Кыргызча (Кыргызстан)', + mk_mk: 'Македонски (Северна Македонија)', + mn_mn: 'Монгол (Монгол Улс)', + ry_ua: 'Руснацькый (Пудкарпатя, Украина)', + ru_ru: 'Русский (Россия)', + rpr: 'Русскій дореформенный (Россійская имперія)', + sah_sah: 'Сахалыы (Cаха Сирэ)', + sr_sp: 'Српски (Србија)', + tt_ru: 'Татарча (Татарстан, Рәсәй)', + uk_ua: 'Українська (Україна)', + cv_cu: 'Чӑвашла (Чӑваш Ен, Раҫҫей)', + kk_kz: 'Қазақша (Қазақстан)', + hy_am: 'Հայերեն (Հայաստան)', + yi_de: 'ייִדיש (אשכנזיש יידן)', + he_il: 'עברית (ישראל)', + ar_sa: 'العربية (العالم العربي)', + zlm_arab: 'بهاس ملايو (مليسيا)', + fa_ir: 'فارسی (ايران)', + hi_in: 'हिंदी (भारत)', + ta_in: 'தமிழ் (இந்தியா)', + kn_in: 'ಕನ್ನಡ (ಭಾರತ)', + th_th: 'ไทย (ประเทศไทย)', + lo_la: 'ລາວ (ປະເທດລາວ)', + ka_ge: 'ქართული (საქართველო)', + lzh: '文言 (華夏)', + ja_jp: '日本語 (日本)', + zh_cn: '简体中文 (中国大陆)', + zh_tw: '繁體中文 (台灣)', + zh_hk: '繁體中文 (香港特別行政區)', + ko_kr: '한국어 (대한민국)', + got_de: '𐌲𐌿𐍄𐍂𐌰𐌶𐌳𐌰 (𐌲𐌿𐍄𐌸𐌹𐌿𐌳𐌰)', +} + +export const minecraftLanguageOptions: ComboboxOption[] = Object.entries(languageNames) + .map(([value, label]) => ({ value, label, searchTerms: [value] })) + .sort((a, b) => a.label.localeCompare(b.label)) diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue index 049afab5c1..cfea5f58ff 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue @@ -19,10 +19,12 @@ import { canonicalBooleanValue, canonicalValueFromInput, canonicalValueText, + gameSettingNumberScale, isKeybindSetting, settingCanBeEnabled, } from './editors' import GameKeybindInput from './keybind-input.vue' +import { minecraftLanguageOptions } from './languages' import { formatGameSettingChoice, formatGameSettingDescription, @@ -93,6 +95,13 @@ const settingDescription = computed(() => formatGameSettingDescription(formatMessage, props.setting), ) const valueText = computed(() => canonicalValueText(props.setting)) +const languageOptions = computed[]>(() => { + const value = valueText.value + if (value && !minecraftLanguageOptions.some((option) => option.value === value)) { + return [{ value, label: value }, ...minecraftLanguageOptions] + } + return minecraftLanguageOptions +}) const enumOptions = computed[]>(() => (props.setting.editor.choices ?? []).map((choice) => ({ value: choice.value, @@ -106,7 +115,7 @@ const isSlider = computed( () => isNumber.value && props.setting.editor.min != null && props.setting.editor.max != null, ) const booleanValue = computed(() => canonicalBooleanValue(props.setting)) -const numberScale = computed(() => (props.setting.editor.unit === 'percent' ? 100 : 1)) +const numberScale = computed(() => gameSettingNumberScale(props.setting)) const inputMin = computed(() => props.setting.editor.min === null || props.setting.editor.min === undefined ? undefined @@ -254,6 +263,20 @@ function updateValue(value: string | number | boolean | undefined) { @update:model-value="updateValue" /> + +

diff --git a/apps/app-frontend/src/pages/Screenshots.vue b/apps/app-frontend/src/pages/Screenshots.vue index 650acb3faa..00835b8f65 100644 --- a/apps/app-frontend/src/pages/Screenshots.vue +++ b/apps/app-frontend/src/pages/Screenshots.vue @@ -1,5 +1,5 @@ diff --git a/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue index a660b09eaf..c94f3b01a3 100644 --- a/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue +++ b/apps/app-frontend/src/pages/instance/components/settings-modal/java-settings.vue @@ -228,6 +228,8 @@ const messages = defineMessages({ :step="64" :snap-points="snapPoints" :snap-range="512" + min-label="512 MB" + :max-label="`${Number((maxMemory / 1024).toFixed(1))} GB`" unit="MB" /> diff --git a/packages/app-lib/src/api/instance/synced_options/game_options/catalog/version_changes.rs b/packages/app-lib/src/api/instance/synced_options/game_options/catalog/version_changes.rs index 0bbedd5464..e73415be40 100644 --- a/packages/app-lib/src/api/instance/synced_options/game_options/catalog/version_changes.rs +++ b/packages/app-lib/src/api/instance/synced_options/game_options/catalog/version_changes.rs @@ -69,20 +69,12 @@ pub(in crate::api::instance) const AMBIENT_OCCLUSION_KEYS: &[VersionedKey] = &[ }, ]; -pub(in crate::api::instance) const FOV_KEYS: &[VersionedKey] = &[ - VersionedKey { - key: "fov", - since: "1.0", - until: "1.18.2", - mapping: GameOptionMappingKind::Legacy, - }, - VersionedKey { - key: "fov", - since: "1.19", - until: "26.3", - mapping: GameOptionMappingKind::Direct, - }, -]; +pub(in crate::api::instance) const FOV_KEYS: &[VersionedKey] = &[VersionedKey { + key: "fov", + since: "1.0", + until: "26.3", + mapping: GameOptionMappingKind::Direct, +}]; pub(in crate::api::instance) const CLOUD_KEYS: &[VersionedKey] = &[ VersionedKey { @@ -551,14 +543,8 @@ pub(in crate::api::instance) fn encode_value( (ValueEncoding::Fov, CanonicalValue::Integer(value)) if (30..=110).contains(value) => { - if release_version(game_version) - .is_some_and(|version| version >= (1, 19, 0)) - { - Some(value.to_string()) - } else { - let normalized = (*value as f64 - 70.0) / 40.0; - Some(format_decimal(normalized)) - } + let normalized = (*value as f64 - 70.0) / 40.0; + Some(format_decimal(normalized)) } (ValueEncoding::GuiScale, CanonicalValue::Integer(value)) if (0..=8).contains(value) @@ -914,14 +900,9 @@ pub(in crate::api::instance) fn physical_representation_supported_for_target( }; } if matches!(definition.encoding, ValueEncoding::Fov) { - return if target_version >= (1, 19, 0) { - raw.parse::() - .is_ok_and(|value| (30..=110).contains(&value)) - } else { - raw.parse::().is_ok_and(|value| { - value.is_finite() && (-1.0..=1.0).contains(&value) - }) - }; + return raw.parse::().is_ok_and(|value| { + value.is_finite() && (-1.0..=1.0).contains(&value) + }); } if matches!(definition.encoding, ValueEncoding::ChatPreview) { return if target_version == (1, 19, 0) { diff --git a/packages/ui/src/components/base/Slider.vue b/packages/ui/src/components/base/Slider.vue index da817afad6..650a1a4e19 100644 --- a/packages/ui/src/components/base/Slider.vue +++ b/packages/ui/src/components/base/Slider.vue @@ -2,9 +2,9 @@

- {{ min }} + {{ minLabel ?? min }}
- {{ formatValue(max) }} + {{ maxLabel ?? formatValue(max) }} { + const digits = Math.max(String(props.min).length, String(props.max).length) + const padding = props.size === 'small' || props.size === 'standard' ? 1.5 : 2 + return `max(65px, calc(${digits}ch + ${padding}rem + 2px))` +}) const currentPercentage = computed(() => getPercentage(currentValue.value ?? props.min)) const visibleSnapPoints = computed(() => props.snapPoints.filter((snapPoint) => snapPoint >= props.min && snapPoint <= props.max), From ff92874d8f724d2887b12215cae190e608720b6b Mon Sep 17 00:00:00 2001 From: "Calum H. (IMB11)" Date: Tue, 8 Sep 2026 09:40:27 +0100 Subject: [PATCH 4/8] feat: extract locales from mods + game jars --- .../components/ui/QuickInstanceSwitcher.vue | 6 +- .../ui/library/instance-group/index.vue | 4 +- .../instances/game-settings-modal/editors.ts | 2 +- .../instances/game-settings-modal/index.vue | 25 +- .../game-settings-modal/languages.ts | 8 +- .../instances/game-settings-modal/messages.ts | 1175 +---------------- .../instances/game-settings-modal/row.vue | 15 +- .../game-settings-modal/use-labels.ts | 87 ++ .../src/components/ui/world/WorldItem.vue | 15 + apps/app-frontend/src/helpers/game-options.ts | 19 + .../app-frontend/src/locales/en-US/index.json | 698 +--------- apps/app/src/api/instance.rs | 8 + ...d5c5b3ed5c0d5e515a956e1ed4a722408748b.json | 12 + ...19b83e3a6663fbd52b0198a0f2a5cd97c3961.json | 56 + ...5edb59da2487c0cc099bd965e16424f47d827.json | 12 + .../20260908120000_game-option-locales.sql | 24 + packages/app-lib/src/api/instance.rs | 2 + .../game_options/locales/archive.rs | 187 +++ .../game_options/locales/catalog.rs | 138 ++ .../game_options/locales/mod.rs | 301 +++++ .../game_options/locales/sources.rs | 196 +++ .../game_options/locales/storage.rs | 63 + .../synced_options/game_options/mod.rs | 3 + .../game_options/read_instance_changes.rs | 8 + .../game_options/source_selection.rs | 3 + packages/app-lib/src/install/store.rs | 1 + .../instances/commands/sync_content_files.rs | 1 + .../app-lib/src/state/instances/watcher.rs | 3 + packages/app-lib/src/state/mod.rs | 3 + packages/assets/generated-icons.ts | 2 + packages/assets/icons/link-2.svg | 17 + .../components/ContentCardItem.vue | 10 +- 32 files changed, 1241 insertions(+), 1863 deletions(-) create mode 100644 apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/use-labels.ts create mode 100644 packages/app-lib/.sqlx/query-5026df81edab9891eb69be610f2d5c5b3ed5c0d5e515a956e1ed4a722408748b.json create mode 100644 packages/app-lib/.sqlx/query-c4a7ef44cae3241d2afb444ea7819b83e3a6663fbd52b0198a0f2a5cd97c3961.json create mode 100644 packages/app-lib/.sqlx/query-d2c0630471ca3ecabcd9482cec25edb59da2487c0cc099bd965e16424f47d827.json create mode 100644 packages/app-lib/migrations/20260908120000_game-option-locales.sql create mode 100644 packages/app-lib/src/api/instance/synced_options/game_options/locales/archive.rs create mode 100644 packages/app-lib/src/api/instance/synced_options/game_options/locales/catalog.rs create mode 100644 packages/app-lib/src/api/instance/synced_options/game_options/locales/mod.rs create mode 100644 packages/app-lib/src/api/instance/synced_options/game_options/locales/sources.rs create mode 100644 packages/app-lib/src/api/instance/synced_options/game_options/locales/storage.rs create mode 100644 packages/assets/icons/link-2.svg diff --git a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue index 00a6df686b..b0cdbe9b72 100644 --- a/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue +++ b/apps/app-frontend/src/components/ui/QuickInstanceSwitcher.vue @@ -317,7 +317,11 @@ function openContextMenu(event, instance) {
diff --git a/apps/app-frontend/src/components/ui/library/instance-group/index.vue b/apps/app-frontend/src/components/ui/library/instance-group/index.vue index 5c3b681f20..644246aee4 100644 --- a/apps/app-frontend/src/components/ui/library/instance-group/index.vue +++ b/apps/app-frontend/src/components/ui/library/instance-group/index.vue @@ -128,7 +128,9 @@ const cardWidth = computed( () => (gridWidth.value - gap.value * (columnCount.value - 1)) / columnCount.value, ) const cardHeight = computed(() => - compactMode.value ? remSize.value * 3.875 + 2 : Math.max(0, cardWidth.value) + remSize.value * 3.375, + compactMode.value + ? remSize.value * 3.875 + 2 + : Math.max(0, cardWidth.value) + remSize.value * 3.375, ) const gridHeight = computed(() => Math.max( diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts index abb206dd2c..16908ab858 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/editors.ts @@ -95,7 +95,7 @@ export function canonicalBooleanValue(setting: EditableGameSetting): boolean | u export function isKeybindSetting(setting: EditableGameSetting): boolean { return ( setting.editor.type === 'key_binding' || - (setting.editor.type === 'external_raw' && !!setting.raw_key?.startsWith('key_key')) + (setting.editor.type === 'external_raw' && !!setting.raw_key?.startsWith('key_')) ) } diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue index f1a826bb1d..6550842a1a 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/index.vue @@ -40,13 +40,10 @@ import { settingSearchText, } from './editors' import { minecraftKeybindConflictKey } from './keybinds' -import { - formatGameSettingDescription, - formatGameSettingLabel, - gameSettingCategoryMessage, -} from './messages' +import { formatGameSettingDescription, gameSettingCategoryMessage } from './messages' import GameSettingRow from './row.vue' import { useGameSettingsEditor } from './use-editor' +import { useGameSettingLabels } from './use-labels' const props = defineProps<{ instanceId?: string @@ -119,6 +116,7 @@ const modal = ref | null>(null) const confirmLeaveModal = ref | null>(null) const activeCategoryId = ref('') const search = ref('') +const opened = ref(false) let allowClose = false const { @@ -154,6 +152,16 @@ const categoryIcons: Record = { custom_settings: WrenchIcon, } +const localeLabels = useGameSettingLabels( + opened, + () => props.instanceId, + () => draftState.value?.settings ?? [], +) + +function settingLabel(setting: EditableGameSetting) { + return localeLabels.value[setting.option_id]?.label ?? setting.raw_key ?? setting.option_id +} + const categories = computed(() => { if (!draftState.value) return [] @@ -192,7 +200,7 @@ const categorySettings = computed(() => { query && !settingSearchText( setting, - formatGameSettingLabel(formatMessage, setting), + settingLabel(setting), formatGameSettingDescription(formatMessage, setting), ).includes(query) ) @@ -220,7 +228,7 @@ const keybindConflicts = computed(() => { setting.option_id, settings .filter((candidate) => candidate.option_id !== setting.option_id) - .map((candidate) => formatGameSettingLabel(formatMessage, candidate)), + .map((candidate) => settingLabel(candidate)), ) } } @@ -267,6 +275,7 @@ async function load() { } function show() { + opened.value = true allowClose = false search.value = '' modal.value?.show() @@ -278,6 +287,7 @@ function hide() { } function reset() { + opened.value = false resetEditor() allowClose = false } @@ -394,6 +404,7 @@ defineExpose({ show, hide }) v-for="setting in categorySettings" :key="setting.option_id" :setting="setting" + :locale-label="localeLabels[setting.option_id]" :keybind-conflicts="keybindConflicts.get(setting.option_id)" :show-sync-toggle="!isLocalEditor" @update:sync-enabled="setSyncEnabled([setting.option_id], $event)" diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts index 34fd106378..752e3aa928 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/languages.ts @@ -10,7 +10,7 @@ const languageNames: Record = { az_az: 'Azərbaycanca (Azərbaycan)', id_id: 'Bahasa Indonesia (Indonesia)', ms_my: 'Bahasa Melayu (Malaysia)', - tzo_mx: 'Bats\'i k\'op (Jobel)', + tzo_mx: "Bats'i k'op (Jobel)", qid: 'Bhs. Indonesia edjaän lama (Indonesia tempo doeloe)', be_latn: 'Biełaruskaja (Biełaruś)', bar: 'Boarisch (Bayern)', @@ -73,7 +73,7 @@ const languageNames: Record = { pls: 'Ngiiwà (Ndanìꞌngà)', no_no: 'Norsk bokmål (Norge)', nn_no: 'Norsk nynorsk (Noreg)', - uz_uz: 'O\'zbekcha (O\'zbekiston)', + uz_uz: "O'zbekcha (O'zbekiston)", oc_fr: 'Occitan (Occitània)', en_pt: 'Pirate Speak (The Seven Seas)', nds_de: 'Plattdüütsch (Düütschland)', @@ -100,8 +100,8 @@ const languageNames: Record = { vec_it: 'Vèneto (Veneto)', vro: 'Võro (Eesti)', yo_ng: 'Yorùbá (Nàìjíríà)', - jbo_en: 'la .lojban. (la jbogu\'e)', - tlh_aa: 'tlhIngan Hol (tlhIngan wo\')', + jbo_en: "la .lojban. (la jbogu'e)", + tlh_aa: "tlhIngan Hol (tlhIngan wo')", tok: 'toki pona (kulupu pona)', is_is: 'Íslenska (Ísland)', ovd: 'Övdalska (Swerre)', diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/messages.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/messages.ts index a5e741b63a..0cd17a2663 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/messages.ts +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/messages.ts @@ -9,855 +9,110 @@ import type { type FormatMessage = VIntlFormatters['formatMessage'] const settingMessages = defineMessages({ - fovLabel: { id: 'app.settings.game-options.setting.fov.label', defaultMessage: 'Field of view' }, - graphicsLabel: { - id: 'app.settings.game-options.setting.graphics.label', - defaultMessage: 'Graphics', - }, graphicsDescription: { id: 'app.settings.game-options.setting.graphics.description', defaultMessage: 'Controls visual quality and performance.', }, - ambientOcclusionLabel: { - id: 'app.settings.game-options.setting.ambient-occlusion.label', - defaultMessage: 'Smooth lighting', - }, - renderDistanceLabel: { - id: 'app.settings.game-options.setting.render-distance.label', - defaultMessage: 'Render distance', - }, - simulationDistanceLabel: { - id: 'app.settings.game-options.setting.simulation-distance.label', - defaultMessage: 'Simulation distance', - }, simulationDistanceDescription: { id: 'app.settings.game-options.setting.simulation-distance.description', defaultMessage: 'How far away entities update and blocks and fluids tick.', }, - guiScaleLabel: { - id: 'app.settings.game-options.setting.gui-scale.label', - defaultMessage: 'GUI scale', - }, guiScaleDescription: { id: 'app.settings.game-options.setting.gui-scale.description', defaultMessage: 'The size of the game interface and HUD.', }, - particlesLabel: { - id: 'app.settings.game-options.setting.particles.label', - defaultMessage: 'Particles', - }, - cloudsLabel: { id: 'app.settings.game-options.setting.clouds.label', defaultMessage: 'Clouds' }, - entityShadowsLabel: { - id: 'app.settings.game-options.setting.entity-shadows.label', - defaultMessage: 'Entity shadows', - }, - viewBobbingLabel: { - id: 'app.settings.game-options.setting.view-bobbing.label', - defaultMessage: 'View bobbing', - }, viewBobbingDescription: { id: 'app.settings.game-options.setting.view-bobbing.description', defaultMessage: 'Add a bobbing motion to the camera while walking.', }, - vsyncLabel: { id: 'app.settings.game-options.setting.vsync.label', defaultMessage: 'VSync' }, vsyncDescription: { id: 'app.settings.game-options.setting.vsync.description', defaultMessage: 'Limit the frame rate to the display refresh rate to prevent screen tearing.', }, - fullscreenLabel: { - id: 'app.settings.game-options.setting.fullscreen.label', - defaultMessage: 'Fullscreen', - }, - maxFramerateLabel: { - id: 'app.settings.game-options.setting.max-framerate.label', - defaultMessage: 'Maximum framerate', - }, - mipmapLevelsLabel: { - id: 'app.settings.game-options.setting.mipmap-levels.label', - defaultMessage: 'Mipmap levels', - }, mipmapLevelsDescription: { id: 'app.settings.game-options.setting.mipmap-levels.description', defaultMessage: 'Texture smoothing at a distance.', }, - biomeBlendRadiusLabel: { - id: 'app.settings.game-options.setting.biome-blend-radius.label', - defaultMessage: 'Biome blend', - }, biomeBlendRadiusDescription: { id: 'app.settings.game-options.setting.biome-blend-radius.description', defaultMessage: 'The distance over which biome colors transition.', }, - languageLabel: { - id: 'app.settings.game-options.setting.language.label', - defaultMessage: 'Language', - }, - masterVolumeLabel: { - id: 'app.settings.game-options.setting.master-volume.label', - defaultMessage: 'Master volume', - }, - musicVolumeLabel: { - id: 'app.settings.game-options.setting.music-volume.label', - defaultMessage: 'Music', - }, - musicToastLabel: { - id: 'app.settings.game-options.setting.music-toast.label', - defaultMessage: 'Music notification', - }, musicToastDescription: { id: 'app.settings.game-options.setting.music-toast.description', defaultMessage: 'Choose whether music titles appear in the pause menu and as toasts.', }, - recordVolumeLabel: { - id: 'app.settings.game-options.setting.record-volume.label', - defaultMessage: 'Jukebox/Note Blocks', - }, - weatherVolumeLabel: { - id: 'app.settings.game-options.setting.weather-volume.label', - defaultMessage: 'Weather', - }, - blocksVolumeLabel: { - id: 'app.settings.game-options.setting.blocks-volume.label', - defaultMessage: 'Blocks', - }, - hostileVolumeLabel: { - id: 'app.settings.game-options.setting.hostile-volume.label', - defaultMessage: 'Hostile creatures', - }, - neutralVolumeLabel: { - id: 'app.settings.game-options.setting.neutral-volume.label', - defaultMessage: 'Friendly creatures', - }, - playersVolumeLabel: { - id: 'app.settings.game-options.setting.players-volume.label', - defaultMessage: 'Players', - }, - ambientVolumeLabel: { - id: 'app.settings.game-options.setting.ambient-volume.label', - defaultMessage: 'Ambient/Environment', - }, - voiceVolumeLabel: { - id: 'app.settings.game-options.setting.voice-volume.label', - defaultMessage: 'Voice and speech', - }, - uiVolumeLabel: { - id: 'app.settings.game-options.setting.ui-volume.label', - defaultMessage: 'UI', - }, - sensitivityLabel: { - id: 'app.settings.game-options.setting.sensitivity.label', - defaultMessage: 'Mouse sensitivity', - }, - invertMouseLabel: { - id: 'app.settings.game-options.setting.invert-mouse.label', - defaultMessage: 'Invert mouse', - }, invertMouseDescription: { id: 'app.settings.game-options.setting.invert-mouse.description', defaultMessage: 'Invert vertical mouse movement.', }, - autoJumpLabel: { - id: 'app.settings.game-options.setting.auto-jump.label', - defaultMessage: 'Auto-jump', - }, autoJumpDescription: { id: 'app.settings.game-options.setting.auto-jump.description', defaultMessage: 'Automatically jump up one-block-high obstacles.', }, - toggleCrouchLabel: { - id: 'app.settings.game-options.setting.toggle-crouch.label', - defaultMessage: 'Toggle crouch', - }, toggleCrouchDescription: { id: 'app.settings.game-options.setting.toggle-crouch.description', defaultMessage: 'Press once to remain crouched.', }, - toggleSprintLabel: { - id: 'app.settings.game-options.setting.toggle-sprint.label', - defaultMessage: 'Toggle sprint', - }, toggleSprintDescription: { id: 'app.settings.game-options.setting.toggle-sprint.description', defaultMessage: 'Press once to remain sprinting.', }, - discreteMouseScrollLabel: { - id: 'app.settings.game-options.setting.discrete-mouse-scroll.label', - defaultMessage: 'Discrete scrolling', - }, discreteMouseScrollDescription: { id: 'app.settings.game-options.setting.discrete-mouse-scroll.description', defaultMessage: 'Treat each mouse-wheel input as a single scroll step.', }, - keyForwardLabel: { - id: 'app.settings.game-options.setting.key-forward.label', - defaultMessage: 'Move forward', - }, - keyLeftLabel: { - id: 'app.settings.game-options.setting.key-left.label', - defaultMessage: 'Strafe left', - }, - keyBackLabel: { - id: 'app.settings.game-options.setting.key-back.label', - defaultMessage: 'Move backward', - }, - keyRightLabel: { - id: 'app.settings.game-options.setting.key-right.label', - defaultMessage: 'Strafe right', - }, - keyJumpLabel: { id: 'app.settings.game-options.setting.key-jump.label', defaultMessage: 'Jump' }, - keySneakLabel: { - id: 'app.settings.game-options.setting.key-sneak.label', - defaultMessage: 'Sneak', - }, - keySprintLabel: { - id: 'app.settings.game-options.setting.key-sprint.label', - defaultMessage: 'Sprint', - }, - keyInventoryLabel: { - id: 'app.settings.game-options.setting.key-inventory.label', - defaultMessage: 'Inventory', - }, - keySwapOffhandLabel: { - id: 'app.settings.game-options.setting.key-swap-offhand.label', - defaultMessage: 'Swap offhand', - }, - keyDropLabel: { - id: 'app.settings.game-options.setting.key-drop.label', - defaultMessage: 'Drop item', - }, - keyUseLabel: { - id: 'app.settings.game-options.setting.key-use.label', - defaultMessage: 'Use item', - }, - keyAttackLabel: { - id: 'app.settings.game-options.setting.key-attack.label', - defaultMessage: 'Attack', - }, - keyPickItemLabel: { - id: 'app.settings.game-options.setting.key-pick-item.label', - defaultMessage: 'Pick block', - }, - keyChatLabel: { - id: 'app.settings.game-options.setting.key-chat.label', - defaultMessage: 'Open chat', - }, - keyPlayerListLabel: { - id: 'app.settings.game-options.setting.key-player-list.label', - defaultMessage: 'Player list', - }, - keyCommandLabel: { - id: 'app.settings.game-options.setting.key-command.label', - defaultMessage: 'Command', - }, - keyScreenshotLabel: { - id: 'app.settings.game-options.setting.key-screenshot.label', - defaultMessage: 'Screenshot', - }, - keyPerspectiveLabel: { - id: 'app.settings.game-options.setting.key-perspective.label', - defaultMessage: 'Change perspective', - }, - keyFullscreenLabel: { - id: 'app.settings.game-options.setting.key-fullscreen.label', - defaultMessage: 'Toggle fullscreen', - }, - keyAdvancementsLabel: { - id: 'app.settings.game-options.setting.key-advancements.label', - defaultMessage: 'Advancements', - }, - chatVisibilityLabel: { - id: 'app.settings.game-options.setting.chat-visibility.label', - defaultMessage: 'Chat visibility', - }, - chatColorsLabel: { - id: 'app.settings.game-options.setting.chat-colors.label', - defaultMessage: 'Chat colors', - }, - chatLinksLabel: { - id: 'app.settings.game-options.setting.chat-links.label', - defaultMessage: 'Web links', - }, chatLinksDescription: { id: 'app.settings.game-options.setting.chat-links.description', defaultMessage: 'Allow web links in chat to be opened.', }, - chatLinksPromptLabel: { - id: 'app.settings.game-options.setting.chat-links-prompt.label', - defaultMessage: 'Prompt on links', - }, chatLinksPromptDescription: { id: 'app.settings.game-options.setting.chat-links-prompt.description', defaultMessage: 'Ask before opening links from chat.', }, - chatOpacityLabel: { - id: 'app.settings.game-options.setting.chat-opacity.label', - defaultMessage: 'Chat opacity', - }, chatOpacityDescription: { id: 'app.settings.game-options.setting.chat-opacity.description', defaultMessage: 'The opacity of chat text.', }, - chatScaleLabel: { - id: 'app.settings.game-options.setting.chat-scale.label', - defaultMessage: 'Chat scale', - }, - narratorLabel: { - id: 'app.settings.game-options.setting.narrator.label', - defaultMessage: 'Narrator', - }, narratorDescription: { id: 'app.settings.game-options.setting.narrator.description', defaultMessage: 'Choose what the narrator reads.', }, - subtitlesLabel: { - id: 'app.settings.game-options.setting.subtitles.label', - defaultMessage: 'Subtitles', - }, subtitlesDescription: { id: 'app.settings.game-options.setting.subtitles.description', defaultMessage: 'Show captions for sounds played in the game.', }, - highContrastLabel: { - id: 'app.settings.game-options.setting.high-contrast.label', - defaultMessage: 'High contrast', - }, highContrastDescription: { id: 'app.settings.game-options.setting.high-contrast.description', defaultMessage: 'Enhance the contrast of interface elements.', }, - darkSplashLabel: { - id: 'app.settings.game-options.setting.dark-splash.label', - defaultMessage: 'Monochrome logo', - }, darkSplashDescription: { id: 'app.settings.game-options.setting.dark-splash.description', defaultMessage: 'Change the Mojang Studios loading screen from red to black.', }, - notificationTimeLabel: { - id: 'app.settings.game-options.setting.notification-time.label', - defaultMessage: 'Notification time', - }, notificationTimeDescription: { id: 'app.settings.game-options.setting.notification-time.description', defaultMessage: 'How long toast notifications remain visible.', }, - mainHandLabel: { - id: 'app.settings.game-options.setting.main-hand.label', - defaultMessage: 'Main hand', - }, mainHandDescription: { id: 'app.settings.game-options.setting.main-hand.description', defaultMessage: 'Choose whether the main hand is left or right.', }, - capeLabel: { id: 'app.settings.game-options.setting.cape.label', defaultMessage: 'Cape' }, capeDescription: { id: 'app.settings.game-options.setting.cape.description', defaultMessage: "Show the player's cape, including its elytra texture.", }, - hatLabel: { id: 'app.settings.game-options.setting.hat.label', defaultMessage: 'Hat' }, hatDescription: { id: 'app.settings.game-options.setting.hat.description', defaultMessage: 'Show the hat skin layer.', }, - jacketLabel: { id: 'app.settings.game-options.setting.jacket.label', defaultMessage: 'Jacket' }, jacketDescription: { id: 'app.settings.game-options.setting.jacket.description', defaultMessage: 'Show the jacket skin layer.', }, - allowServerListingLabel: { - id: 'app.settings.game-options.setting.allow-server-listing.label', - defaultMessage: 'Server listings', - }, allowServerListingDescription: { id: 'app.settings.game-options.setting.allow-server-listing.description', defaultMessage: "Allow the player's name to appear in server listings.", }, - realmsNotificationsLabel: { - id: 'app.settings.game-options.setting.realms-notifications.label', - defaultMessage: 'Realms notifications', - }, -}) - -const catalogSettingMessages = defineMessages({ - brightnessLabel: { - id: 'app.settings.game-options.setting.brightness.label', - defaultMessage: 'Brightness', - }, - legacyViewDistanceLabel: { - id: 'app.settings.game-options.setting.legacy-view-distance.label', - defaultMessage: 'View distance', - }, - entityDistanceLabel: { - id: 'app.settings.game-options.setting.entity-distance.label', - defaultMessage: 'Entity distance', - }, - debugGuiScaleLabel: { - id: 'app.settings.game-options.setting.debug-gui-scale.label', - defaultMessage: 'Debug GUI scale', - }, - graphicsBackendLabel: { - id: 'app.settings.game-options.setting.graphics-backend.label', - defaultMessage: 'Graphics backend', - }, - cloudRangeLabel: { - id: 'app.settings.game-options.setting.cloud-range.label', - defaultMessage: 'Cloud distance', - }, - exclusiveFullscreenLabel: { - id: 'app.settings.game-options.setting.exclusive-fullscreen.label', - defaultMessage: 'Exclusive fullscreen', - }, - macFullscreenMenuLabel: { - id: 'app.settings.game-options.setting.mac-fullscreen-menu.label', - defaultMessage: 'Show macOS menu in fullscreen', - }, - legacyFramerateLimitLabel: { - id: 'app.settings.game-options.setting.legacy-framerate-limit.label', - defaultMessage: 'Framerate limit', - }, - inactivityFramerateLimitLabel: { - id: 'app.settings.game-options.setting.inactivity-framerate-limit.label', - defaultMessage: 'Reduced framerate', - }, - prioritizeChunkUpdatesLabel: { - id: 'app.settings.game-options.setting.prioritize-chunk-updates.label', - defaultMessage: 'Prioritize chunk updates', - }, - attackIndicatorLabel: { - id: 'app.settings.game-options.setting.attack-indicator.label', - defaultMessage: 'Attack indicator', - }, - reducedDebugInfoLabel: { - id: 'app.settings.game-options.setting.reduced-debug-info.label', - defaultMessage: 'Reduced debug information', - }, - chunkFadeTimeLabel: { - id: 'app.settings.game-options.setting.chunk-fade-time.label', - defaultMessage: 'Chunk fade time', - }, - cutoutLeavesLabel: { - id: 'app.settings.game-options.setting.cutout-leaves.label', - defaultMessage: 'Cutout leaves', - }, - improvedTransparencyLabel: { - id: 'app.settings.game-options.setting.improved-transparency.label', - defaultMessage: 'Improved transparency', - }, - textureFilteringLabel: { - id: 'app.settings.game-options.setting.texture-filtering.label', - defaultMessage: 'Texture filtering', - }, - anisotropyLabel: { - id: 'app.settings.game-options.setting.anisotropy.label', - defaultMessage: 'Anisotropy', - }, - vignetteLabel: { - id: 'app.settings.game-options.setting.vignette.label', - defaultMessage: 'Vignette', - }, - weatherRadiusLabel: { - id: 'app.settings.game-options.setting.weather-radius.label', - defaultMessage: 'Weather radius', - }, - advancedOpenGlLabel: { - id: 'app.settings.game-options.setting.advanced-opengl.label', - defaultMessage: 'Advanced OpenGL', - }, - anaglyph3dLabel: { - id: 'app.settings.game-options.setting.anaglyph-3d.label', - defaultMessage: '3D anaglyph', - }, - anisotropicFilteringLabel: { - id: 'app.settings.game-options.setting.anisotropic-filtering.label', - defaultMessage: 'Anisotropic filtering', - }, - alternateBlocksLabel: { - id: 'app.settings.game-options.setting.alternate-blocks.label', - defaultMessage: 'Alternate blocks', - }, - heldItemTooltipsLabel: { - id: 'app.settings.game-options.setting.held-item-tooltips.label', - defaultMessage: 'Held item tooltips', - }, - useVboLabel: { - id: 'app.settings.game-options.setting.use-vbo.label', - defaultMessage: 'Use VBOs', - }, - forceUnicodeFontLabel: { - id: 'app.settings.game-options.setting.force-unicode-font.label', - defaultMessage: 'Force Unicode font', - }, - japaneseGlyphVariantsLabel: { - id: 'app.settings.game-options.setting.japanese-glyph-variants.label', - defaultMessage: 'Japanese glyph variants', - }, - musicFrequencyLabel: { - id: 'app.settings.game-options.setting.music-frequency.label', - defaultMessage: 'Music frequency', - }, - directionalAudioLabel: { - id: 'app.settings.game-options.setting.directional-audio.label', - defaultMessage: 'Directional audio', - }, - invertHorizontalMouseLabel: { - id: 'app.settings.game-options.setting.invert-horizontal-mouse.label', - defaultMessage: 'Invert horizontal mouse', - }, - toggleAttackLabel: { - id: 'app.settings.game-options.setting.toggle-attack.label', - defaultMessage: 'Toggle attack', - }, - toggleUseLabel: { - id: 'app.settings.game-options.setting.toggle-use.label', - defaultMessage: 'Toggle use', - }, - mouseWheelSensitivityLabel: { - id: 'app.settings.game-options.setting.mouse-wheel-sensitivity.label', - defaultMessage: 'Mouse wheel sensitivity', - }, - rawMouseInputLabel: { - id: 'app.settings.game-options.setting.raw-mouse-input.label', - defaultMessage: 'Raw mouse input', - }, - touchscreenLabel: { - id: 'app.settings.game-options.setting.touchscreen.label', - defaultMessage: 'Touchscreen mode', - }, - allowCursorChangesLabel: { - id: 'app.settings.game-options.setting.allow-cursor-changes.label', - defaultMessage: 'Allow cursor changes', - }, - sprintWindowLabel: { - id: 'app.settings.game-options.setting.sprint-window.label', - defaultMessage: 'Sprint window', - }, - operatorItemsTabLabel: { - id: 'app.settings.game-options.setting.operator-items-tab.label', - defaultMessage: 'Operator items tab', - }, - ctrlClickRightClickLabel: { - id: 'app.settings.game-options.setting.ctrl-click-right-click.label', - defaultMessage: 'Control-click as right-click', - }, - quitShortcutsLabel: { - id: 'app.settings.game-options.setting.quit-shortcuts.label', - defaultMessage: 'Quit shortcuts', - }, - chatWidthLabel: { - id: 'app.settings.game-options.setting.chat-width.label', - defaultMessage: 'Chat width', - }, - focusedChatHeightLabel: { - id: 'app.settings.game-options.setting.focused-chat-height.label', - defaultMessage: 'Focused chat height', - }, - unfocusedChatHeightLabel: { - id: 'app.settings.game-options.setting.unfocused-chat-height.label', - defaultMessage: 'Unfocused chat height', - }, - chatLineSpacingLabel: { - id: 'app.settings.game-options.setting.chat-line-spacing.label', - defaultMessage: 'Chat line spacing', - }, - chatDelayLabel: { - id: 'app.settings.game-options.setting.chat-delay.label', - defaultMessage: 'Chat delay', - }, - textBackgroundOpacityLabel: { - id: 'app.settings.game-options.setting.text-background-opacity.label', - defaultMessage: 'Text background opacity', - }, - chatBackgroundOnlyLabel: { - id: 'app.settings.game-options.setting.chat-background-only.label', - defaultMessage: 'Chat background only', - }, - autoSuggestionsLabel: { - id: 'app.settings.game-options.setting.auto-suggestions.label', - defaultMessage: 'Command suggestions', - }, - secureChatOnlyLabel: { - id: 'app.settings.game-options.setting.secure-chat-only.label', - defaultMessage: 'Only show secure chat', - }, - saveChatDraftsLabel: { - id: 'app.settings.game-options.setting.save-chat-drafts.label', - defaultMessage: 'Save chat drafts', - }, - hideMatchedNamesLabel: { - id: 'app.settings.game-options.setting.hide-matched-names.label', - defaultMessage: 'Hide matched names', - }, - chatPreviewLabel: { - id: 'app.settings.game-options.setting.chat-preview.label', - defaultMessage: 'Chat preview', - }, - fovEffectsLabel: { - id: 'app.settings.game-options.setting.fov-effects.label', - defaultMessage: 'FOV effects', - }, - screenEffectsLabel: { - id: 'app.settings.game-options.setting.screen-effects.label', - defaultMessage: 'Screen effects', - }, - darknessPulsingLabel: { - id: 'app.settings.game-options.setting.darkness-pulsing.label', - defaultMessage: 'Darkness pulsing', - }, - damageTiltLabel: { - id: 'app.settings.game-options.setting.damage-tilt.label', - defaultMessage: 'Damage tilt', - }, - glintSpeedLabel: { - id: 'app.settings.game-options.setting.glint-speed.label', - defaultMessage: 'Glint speed', - }, - glintStrengthLabel: { - id: 'app.settings.game-options.setting.glint-strength.label', - defaultMessage: 'Glint strength', - }, - hideLightningFlashesLabel: { - id: 'app.settings.game-options.setting.hide-lightning-flashes.label', - defaultMessage: 'Hide lightning flashes', - }, - hideSplashTextsLabel: { - id: 'app.settings.game-options.setting.hide-splash-texts.label', - defaultMessage: 'Hide splash texts', - }, - highContrastOutlineLabel: { - id: 'app.settings.game-options.setting.high-contrast-outline.label', - defaultMessage: 'High contrast block outline', - }, - narratorHotkeyLabel: { - id: 'app.settings.game-options.setting.narrator-hotkey.label', - defaultMessage: 'Narrator hotkey', - }, - autosaveIndicatorLabel: { - id: 'app.settings.game-options.setting.autosave-indicator.label', - defaultMessage: 'Autosave indicator', - }, - panoramaSpeedLabel: { - id: 'app.settings.game-options.setting.panorama-speed.label', - defaultMessage: 'Panorama speed', - }, - menuBackgroundBlurLabel: { - id: 'app.settings.game-options.setting.menu-background-blur.label', - defaultMessage: 'Menu background blur', - }, - rotateWithMinecartLabel: { - id: 'app.settings.game-options.setting.rotate-with-minecart.label', - defaultMessage: 'Rotate with minecart', - }, - leftSleeveLabel: { - id: 'app.settings.game-options.setting.left-sleeve.label', - defaultMessage: 'Left sleeve', - }, - rightSleeveLabel: { - id: 'app.settings.game-options.setting.right-sleeve.label', - defaultMessage: 'Right sleeve', - }, - leftPantsLegLabel: { - id: 'app.settings.game-options.setting.left-pants-leg.label', - defaultMessage: 'Left pants leg', - }, - rightPantsLegLabel: { - id: 'app.settings.game-options.setting.right-pants-leg.label', - defaultMessage: 'Right pants leg', - }, - hideServerAddressLabel: { - id: 'app.settings.game-options.setting.hide-server-address.label', - defaultMessage: 'Hide server address', - }, - serverTexturesLabel: { - id: 'app.settings.game-options.setting.server-textures.label', - defaultMessage: 'Server textures', - }, - snooperLabel: { - id: 'app.settings.game-options.setting.snooper.label', - defaultMessage: 'Snooper', - }, - extraTelemetryLabel: { - id: 'app.settings.game-options.setting.extra-telemetry.label', - defaultMessage: 'Optional telemetry', - }, - inGameNotificationsLabel: { - id: 'app.settings.game-options.setting.in-game-notifications.label', - defaultMessage: 'In-game notifications', - }, - sharePresenceLabel: { - id: 'app.settings.game-options.setting.share-presence.label', - defaultMessage: 'Share presence', - }, -}) - -const catalogKeyMessages = defineMessages({ - smoothCameraLabel: { - id: 'app.settings.game-options.setting.key-smooth-camera.label', - defaultMessage: 'Toggle cinematic camera', - }, - spectatorOutlinesLabel: { - id: 'app.settings.game-options.setting.key-spectator-outlines.label', - defaultMessage: 'Highlight spectators', - }, - saveToolbarLabel: { - id: 'app.settings.game-options.setting.key-save-toolbar.label', - defaultMessage: 'Save toolbar', - }, - loadToolbarLabel: { - id: 'app.settings.game-options.setting.key-load-toolbar.label', - defaultMessage: 'Load toolbar', - }, - socialInteractionsLabel: { - id: 'app.settings.game-options.setting.key-social-interactions.label', - defaultMessage: 'Social interactions', - }, - quickActionsLabel: { - id: 'app.settings.game-options.setting.key-quick-actions.label', - defaultMessage: 'Quick actions', - }, - spectatorHotbarLabel: { - id: 'app.settings.game-options.setting.key-spectator-hotbar.label', - defaultMessage: 'Spectator hotbar', - }, - friendsLabel: { - id: 'app.settings.game-options.setting.key-friends.label', - defaultMessage: 'Friends', - }, - toggleGuiLabel: { - id: 'app.settings.game-options.setting.key-toggle-gui.label', - defaultMessage: 'Toggle HUD', - }, - toggleSpectatorShaderLabel: { - id: 'app.settings.game-options.setting.key-toggle-spectator-shader.label', - defaultMessage: 'Toggle spectator shader', - }, - hotbar1Label: { - id: 'app.settings.game-options.setting.key-hotbar-1.label', - defaultMessage: 'Hotbar 1', - }, - hotbar2Label: { - id: 'app.settings.game-options.setting.key-hotbar-2.label', - defaultMessage: 'Hotbar 2', - }, - hotbar3Label: { - id: 'app.settings.game-options.setting.key-hotbar-3.label', - defaultMessage: 'Hotbar 3', - }, - hotbar4Label: { - id: 'app.settings.game-options.setting.key-hotbar-4.label', - defaultMessage: 'Hotbar 4', - }, - hotbar5Label: { - id: 'app.settings.game-options.setting.key-hotbar-5.label', - defaultMessage: 'Hotbar 5', - }, - hotbar6Label: { - id: 'app.settings.game-options.setting.key-hotbar-6.label', - defaultMessage: 'Hotbar 6', - }, - hotbar7Label: { - id: 'app.settings.game-options.setting.key-hotbar-7.label', - defaultMessage: 'Hotbar 7', - }, - hotbar8Label: { - id: 'app.settings.game-options.setting.key-hotbar-8.label', - defaultMessage: 'Hotbar 8', - }, - hotbar9Label: { - id: 'app.settings.game-options.setting.key-hotbar-9.label', - defaultMessage: 'Hotbar 9', - }, - debugOverlayLabel: { - id: 'app.settings.game-options.setting.key-debug-overlay.label', - defaultMessage: 'Debug overlay', - }, - debugModifierLabel: { - id: 'app.settings.game-options.setting.key-debug-modifier.label', - defaultMessage: 'Debug modifier', - }, - debugReloadChunksLabel: { - id: 'app.settings.game-options.setting.key-debug-reload-chunks.label', - defaultMessage: 'Reload chunks', - }, - debugHitboxesLabel: { - id: 'app.settings.game-options.setting.key-debug-hitboxes.label', - defaultMessage: 'Show hitboxes', - }, - debugClearChatLabel: { - id: 'app.settings.game-options.setting.key-debug-clear-chat.label', - defaultMessage: 'Clear chat', - }, - debugCrashLabel: { - id: 'app.settings.game-options.setting.key-debug-crash.label', - defaultMessage: 'Trigger debug crash', - }, - debugChunkBordersLabel: { - id: 'app.settings.game-options.setting.key-debug-chunk-borders.label', - defaultMessage: 'Show chunk borders', - }, - debugAdvancedTooltipsLabel: { - id: 'app.settings.game-options.setting.key-debug-advanced-tooltips.label', - defaultMessage: 'Show advanced tooltips', - }, - debugCopyRecreateCommandLabel: { - id: 'app.settings.game-options.setting.key-debug-copy-recreate-command.label', - defaultMessage: 'Copy recreate command', - }, - debugSpectateLabel: { - id: 'app.settings.game-options.setting.key-debug-spectate.label', - defaultMessage: 'Spectate entity', - }, - debugSwitchGameModeLabel: { - id: 'app.settings.game-options.setting.key-debug-switch-game-mode.label', - defaultMessage: 'Switch game mode', - }, - debugOptionsLabel: { - id: 'app.settings.game-options.setting.key-debug-options.label', - defaultMessage: 'Debug options', - }, - debugFocusPauseLabel: { - id: 'app.settings.game-options.setting.key-debug-focus-pause.label', - defaultMessage: 'Pause on lost focus', - }, - debugDumpDynamicTexturesLabel: { - id: 'app.settings.game-options.setting.key-debug-dump-dynamic-textures.label', - defaultMessage: 'Dump dynamic textures', - }, - debugReloadResourcePacksLabel: { - id: 'app.settings.game-options.setting.key-debug-reload-resource-packs.label', - defaultMessage: 'Reload resource packs', - }, - debugProfilingLabel: { - id: 'app.settings.game-options.setting.key-debug-profiling.label', - defaultMessage: 'Start profiling', - }, - debugCopyLocationLabel: { - id: 'app.settings.game-options.setting.key-debug-copy-location.label', - defaultMessage: 'Copy location', - }, - debugDumpVersionLabel: { - id: 'app.settings.game-options.setting.key-debug-dump-version.label', - defaultMessage: 'Dump version', - }, - debugProfilingChartLabel: { - id: 'app.settings.game-options.setting.key-debug-profiling-chart.label', - defaultMessage: 'Profiling chart', - }, - debugFpsChartsLabel: { - id: 'app.settings.game-options.setting.key-debug-fps-charts.label', - defaultMessage: 'FPS charts', - }, - debugNetworkChartsLabel: { - id: 'app.settings.game-options.setting.key-debug-network-charts.label', - defaultMessage: 'Network charts', - }, - debugLightmapTextureLabel: { - id: 'app.settings.game-options.setting.key-debug-lightmap-texture.label', - defaultMessage: 'Lightmap texture', - }, - debugImprovedTransparencyLabel: { - id: 'app.settings.game-options.setting.key-debug-improved-transparency.label', - defaultMessage: 'Improved transparency debug view', - }, }) const categoryMessages = defineMessages({ @@ -926,59 +181,6 @@ const categoryMessages = defineMessages({ }, }) -const choiceMessages = defineMessages({ - fast: { id: 'app.settings.game-options.choice.fast', defaultMessage: 'Fast' }, - fancy: { id: 'app.settings.game-options.choice.fancy', defaultMessage: 'Fancy' }, - fabulous: { id: 'app.settings.game-options.choice.fabulous', defaultMessage: 'Fabulous' }, - custom: { id: 'app.settings.game-options.choice.custom', defaultMessage: 'Custom' }, - left: { id: 'app.settings.game-options.choice.left', defaultMessage: 'Left' }, - right: { id: 'app.settings.game-options.choice.right', defaultMessage: 'Right' }, - shown: { id: 'app.settings.game-options.choice.shown', defaultMessage: 'Shown' }, - commandsOnly: { - id: 'app.settings.game-options.choice.commands-only', - defaultMessage: 'Commands only', - }, - hidden: { id: 'app.settings.game-options.choice.hidden', defaultMessage: 'Hidden' }, - all: { id: 'app.settings.game-options.choice.all', defaultMessage: 'All' }, - decreased: { id: 'app.settings.game-options.choice.decreased', defaultMessage: 'Decreased' }, - minimal: { id: 'app.settings.game-options.choice.minimal', defaultMessage: 'Minimal' }, - off: { id: 'app.settings.game-options.choice.off', defaultMessage: 'Off' }, - chat: { id: 'app.settings.game-options.choice.chat', defaultMessage: 'Chat' }, - system: { id: 'app.settings.game-options.choice.system', defaultMessage: 'System' }, - on: { id: 'app.settings.game-options.choice.on', defaultMessage: 'On' }, - minimum: { id: 'app.settings.game-options.choice.minimum', defaultMessage: 'Minimum' }, - maximum: { id: 'app.settings.game-options.choice.maximum', defaultMessage: 'Maximum' }, - never: { id: 'app.settings.game-options.choice.never', defaultMessage: 'Never' }, - pause: { id: 'app.settings.game-options.choice.pause', defaultMessage: 'Pause menu' }, - pauseAndToast: { - id: 'app.settings.game-options.choice.pause-and-toast', - defaultMessage: 'Pause menu and toast', - }, - far: { id: 'app.settings.game-options.choice.far', defaultMessage: 'Far' }, - normal: { id: 'app.settings.game-options.choice.normal', defaultMessage: 'Normal' }, - short: { id: 'app.settings.game-options.choice.short', defaultMessage: 'Short' }, - tiny: { id: 'app.settings.game-options.choice.tiny', defaultMessage: 'Tiny' }, - maxFps: { id: 'app.settings.game-options.choice.max-fps', defaultMessage: 'Max FPS' }, - balanced: { id: 'app.settings.game-options.choice.balanced', defaultMessage: 'Balanced' }, - powerSaver: { id: 'app.settings.game-options.choice.power-saver', defaultMessage: 'Power saver' }, - whileAfk: { id: 'app.settings.game-options.choice.while-afk', defaultMessage: 'While AFK' }, - whenMinimized: { - id: 'app.settings.game-options.choice.when-minimized', - defaultMessage: 'When minimized', - }, - none: { id: 'app.settings.game-options.choice.none', defaultMessage: 'None' }, - byPlayer: { id: 'app.settings.game-options.choice.by-player', defaultMessage: 'By player' }, - nearby: { id: 'app.settings.game-options.choice.nearby', defaultMessage: 'Nearby' }, - crosshair: { id: 'app.settings.game-options.choice.crosshair', defaultMessage: 'Crosshair' }, - hotbar: { id: 'app.settings.game-options.choice.hotbar', defaultMessage: 'Hotbar' }, - constant: { id: 'app.settings.game-options.choice.constant', defaultMessage: 'Constant' }, - default: { id: 'app.settings.game-options.choice.default', defaultMessage: 'Default' }, - frequent: { id: 'app.settings.game-options.choice.frequent', defaultMessage: 'Frequent' }, - limited: { id: 'app.settings.game-options.choice.limited', defaultMessage: 'Limited' }, - openGl: { id: 'app.settings.game-options.choice.opengl', defaultMessage: 'OpenGL' }, - vulkan: { id: 'app.settings.game-options.choice.vulkan', defaultMessage: 'Vulkan' }, -}) - export const presentationMessages = defineMessages({ customValuePlaceholder: { id: 'app.settings.game-options.custom-value.placeholder', @@ -1010,277 +212,34 @@ export const presentationMessages = defineMessages({ }, }) -const knownSettings: Record = - { - fov: { label: settingMessages.fovLabel }, - graphics: { - label: settingMessages.graphicsLabel, - description: settingMessages.graphicsDescription, - }, - ambient_occlusion: { label: settingMessages.ambientOcclusionLabel }, - render_distance: { label: settingMessages.renderDistanceLabel }, - simulation_distance: { - label: settingMessages.simulationDistanceLabel, - description: settingMessages.simulationDistanceDescription, - }, - gui_scale: { - label: settingMessages.guiScaleLabel, - description: settingMessages.guiScaleDescription, - }, - particles: { label: settingMessages.particlesLabel }, - clouds: { label: settingMessages.cloudsLabel }, - entity_shadows: { label: settingMessages.entityShadowsLabel }, - view_bobbing: { - label: settingMessages.viewBobbingLabel, - description: settingMessages.viewBobbingDescription, - }, - vsync: { label: settingMessages.vsyncLabel, description: settingMessages.vsyncDescription }, - fullscreen: { label: settingMessages.fullscreenLabel }, - max_framerate: { label: settingMessages.maxFramerateLabel }, - mipmap_levels: { - label: settingMessages.mipmapLevelsLabel, - description: settingMessages.mipmapLevelsDescription, - }, - biome_blend_radius: { - label: settingMessages.biomeBlendRadiusLabel, - description: settingMessages.biomeBlendRadiusDescription, - }, - language: { label: settingMessages.languageLabel }, - master_volume: { label: settingMessages.masterVolumeLabel }, - music_volume: { label: settingMessages.musicVolumeLabel }, - music_toast: { - label: settingMessages.musicToastLabel, - description: settingMessages.musicToastDescription, - }, - record_volume: { label: settingMessages.recordVolumeLabel }, - weather_volume: { label: settingMessages.weatherVolumeLabel }, - blocks_volume: { label: settingMessages.blocksVolumeLabel }, - hostile_volume: { label: settingMessages.hostileVolumeLabel }, - neutral_volume: { label: settingMessages.neutralVolumeLabel }, - players_volume: { label: settingMessages.playersVolumeLabel }, - ambient_volume: { label: settingMessages.ambientVolumeLabel }, - voice_volume: { label: settingMessages.voiceVolumeLabel }, - ui_volume: { label: settingMessages.uiVolumeLabel }, - sensitivity: { label: settingMessages.sensitivityLabel }, - invert_mouse: { - label: settingMessages.invertMouseLabel, - description: settingMessages.invertMouseDescription, - }, - auto_jump: { - label: settingMessages.autoJumpLabel, - description: settingMessages.autoJumpDescription, - }, - toggle_crouch: { - label: settingMessages.toggleCrouchLabel, - description: settingMessages.toggleCrouchDescription, - }, - toggle_sprint: { - label: settingMessages.toggleSprintLabel, - description: settingMessages.toggleSprintDescription, - }, - discrete_mouse_scroll: { - label: settingMessages.discreteMouseScrollLabel, - description: settingMessages.discreteMouseScrollDescription, - }, - 'key.forward': { label: settingMessages.keyForwardLabel }, - 'key.left': { label: settingMessages.keyLeftLabel }, - 'key.back': { label: settingMessages.keyBackLabel }, - 'key.right': { label: settingMessages.keyRightLabel }, - 'key.jump': { label: settingMessages.keyJumpLabel }, - 'key.sneak': { label: settingMessages.keySneakLabel }, - 'key.sprint': { label: settingMessages.keySprintLabel }, - 'key.inventory': { label: settingMessages.keyInventoryLabel }, - 'key.swap_offhand': { label: settingMessages.keySwapOffhandLabel }, - 'key.drop': { label: settingMessages.keyDropLabel }, - 'key.use': { label: settingMessages.keyUseLabel }, - 'key.attack': { label: settingMessages.keyAttackLabel }, - 'key.pick_item': { label: settingMessages.keyPickItemLabel }, - 'key.chat': { label: settingMessages.keyChatLabel }, - 'key.player_list': { label: settingMessages.keyPlayerListLabel }, - 'key.command': { label: settingMessages.keyCommandLabel }, - 'key.screenshot': { label: settingMessages.keyScreenshotLabel }, - 'key.perspective': { label: settingMessages.keyPerspectiveLabel }, - 'key.fullscreen': { label: settingMessages.keyFullscreenLabel }, - 'key.advancements': { label: settingMessages.keyAdvancementsLabel }, - chat_visibility: { label: settingMessages.chatVisibilityLabel }, - chat_colors: { label: settingMessages.chatColorsLabel }, - chat_links: { - label: settingMessages.chatLinksLabel, - description: settingMessages.chatLinksDescription, - }, - chat_links_prompt: { - label: settingMessages.chatLinksPromptLabel, - description: settingMessages.chatLinksPromptDescription, - }, - chat_opacity: { - label: settingMessages.chatOpacityLabel, - description: settingMessages.chatOpacityDescription, - }, - chat_scale: { label: settingMessages.chatScaleLabel }, - narrator: { - label: settingMessages.narratorLabel, - description: settingMessages.narratorDescription, - }, - subtitles: { - label: settingMessages.subtitlesLabel, - description: settingMessages.subtitlesDescription, - }, - high_contrast: { - label: settingMessages.highContrastLabel, - description: settingMessages.highContrastDescription, - }, - dark_splash: { - label: settingMessages.darkSplashLabel, - description: settingMessages.darkSplashDescription, - }, - notification_time: { - label: settingMessages.notificationTimeLabel, - description: settingMessages.notificationTimeDescription, - }, - main_hand: { - label: settingMessages.mainHandLabel, - description: settingMessages.mainHandDescription, - }, - cape: { label: settingMessages.capeLabel, description: settingMessages.capeDescription }, - hat: { label: settingMessages.hatLabel, description: settingMessages.hatDescription }, - jacket: { label: settingMessages.jacketLabel, description: settingMessages.jacketDescription }, - allow_server_listing: { - label: settingMessages.allowServerListingLabel, - description: settingMessages.allowServerListingDescription, - }, - realms_notifications: { label: settingMessages.realmsNotificationsLabel }, - brightness: { label: catalogSettingMessages.brightnessLabel }, - legacy_view_distance: { label: catalogSettingMessages.legacyViewDistanceLabel }, - entity_distance: { label: catalogSettingMessages.entityDistanceLabel }, - debug_gui_scale: { label: catalogSettingMessages.debugGuiScaleLabel }, - graphics_backend: { label: catalogSettingMessages.graphicsBackendLabel }, - cloud_range: { label: catalogSettingMessages.cloudRangeLabel }, - exclusive_fullscreen: { label: catalogSettingMessages.exclusiveFullscreenLabel }, - mac_fullscreen_menu: { label: catalogSettingMessages.macFullscreenMenuLabel }, - legacy_framerate_limit: { label: catalogSettingMessages.legacyFramerateLimitLabel }, - inactivity_framerate_limit: { - label: catalogSettingMessages.inactivityFramerateLimitLabel, - }, - prioritize_chunk_updates: { label: catalogSettingMessages.prioritizeChunkUpdatesLabel }, - attack_indicator: { label: catalogSettingMessages.attackIndicatorLabel }, - reduced_debug_info: { label: catalogSettingMessages.reducedDebugInfoLabel }, - chunk_fade_time: { label: catalogSettingMessages.chunkFadeTimeLabel }, - cutout_leaves: { label: catalogSettingMessages.cutoutLeavesLabel }, - improved_transparency: { label: catalogSettingMessages.improvedTransparencyLabel }, - texture_filtering: { label: catalogSettingMessages.textureFilteringLabel }, - anisotropy: { label: catalogSettingMessages.anisotropyLabel }, - vignette: { label: catalogSettingMessages.vignetteLabel }, - weather_radius: { label: catalogSettingMessages.weatherRadiusLabel }, - advanced_opengl: { label: catalogSettingMessages.advancedOpenGlLabel }, - anaglyph_3d: { label: catalogSettingMessages.anaglyph3dLabel }, - anisotropic_filtering: { label: catalogSettingMessages.anisotropicFilteringLabel }, - alternate_blocks: { label: catalogSettingMessages.alternateBlocksLabel }, - held_item_tooltips: { label: catalogSettingMessages.heldItemTooltipsLabel }, - use_vbo: { label: catalogSettingMessages.useVboLabel }, - force_unicode_font: { label: catalogSettingMessages.forceUnicodeFontLabel }, - japanese_glyph_variants: { label: catalogSettingMessages.japaneseGlyphVariantsLabel }, - music_frequency: { label: catalogSettingMessages.musicFrequencyLabel }, - directional_audio: { label: catalogSettingMessages.directionalAudioLabel }, - invert_horizontal_mouse: { label: catalogSettingMessages.invertHorizontalMouseLabel }, - toggle_attack: { label: catalogSettingMessages.toggleAttackLabel }, - toggle_use: { label: catalogSettingMessages.toggleUseLabel }, - mouse_wheel_sensitivity: { label: catalogSettingMessages.mouseWheelSensitivityLabel }, - raw_mouse_input: { label: catalogSettingMessages.rawMouseInputLabel }, - touchscreen: { label: catalogSettingMessages.touchscreenLabel }, - allow_cursor_changes: { label: catalogSettingMessages.allowCursorChangesLabel }, - sprint_window: { label: catalogSettingMessages.sprintWindowLabel }, - operator_items_tab: { label: catalogSettingMessages.operatorItemsTabLabel }, - ctrl_click_right_click: { label: catalogSettingMessages.ctrlClickRightClickLabel }, - quit_shortcuts: { label: catalogSettingMessages.quitShortcutsLabel }, - chat_width: { label: catalogSettingMessages.chatWidthLabel }, - focused_chat_height: { label: catalogSettingMessages.focusedChatHeightLabel }, - unfocused_chat_height: { label: catalogSettingMessages.unfocusedChatHeightLabel }, - chat_line_spacing: { label: catalogSettingMessages.chatLineSpacingLabel }, - chat_delay: { label: catalogSettingMessages.chatDelayLabel }, - text_background_opacity: { label: catalogSettingMessages.textBackgroundOpacityLabel }, - chat_background_only: { label: catalogSettingMessages.chatBackgroundOnlyLabel }, - auto_suggestions: { label: catalogSettingMessages.autoSuggestionsLabel }, - secure_chat_only: { label: catalogSettingMessages.secureChatOnlyLabel }, - save_chat_drafts: { label: catalogSettingMessages.saveChatDraftsLabel }, - hide_matched_names: { label: catalogSettingMessages.hideMatchedNamesLabel }, - chat_preview: { label: catalogSettingMessages.chatPreviewLabel }, - fov_effects: { label: catalogSettingMessages.fovEffectsLabel }, - screen_effects: { label: catalogSettingMessages.screenEffectsLabel }, - darkness_pulsing: { label: catalogSettingMessages.darknessPulsingLabel }, - damage_tilt: { label: catalogSettingMessages.damageTiltLabel }, - glint_speed: { label: catalogSettingMessages.glintSpeedLabel }, - glint_strength: { label: catalogSettingMessages.glintStrengthLabel }, - hide_lightning_flashes: { label: catalogSettingMessages.hideLightningFlashesLabel }, - hide_splash_texts: { label: catalogSettingMessages.hideSplashTextsLabel }, - high_contrast_outline: { label: catalogSettingMessages.highContrastOutlineLabel }, - narrator_hotkey: { label: catalogSettingMessages.narratorHotkeyLabel }, - autosave_indicator: { label: catalogSettingMessages.autosaveIndicatorLabel }, - panorama_speed: { label: catalogSettingMessages.panoramaSpeedLabel }, - menu_background_blur: { label: catalogSettingMessages.menuBackgroundBlurLabel }, - rotate_with_minecart: { label: catalogSettingMessages.rotateWithMinecartLabel }, - left_sleeve: { label: catalogSettingMessages.leftSleeveLabel }, - right_sleeve: { label: catalogSettingMessages.rightSleeveLabel }, - left_pants_leg: { label: catalogSettingMessages.leftPantsLegLabel }, - right_pants_leg: { label: catalogSettingMessages.rightPantsLegLabel }, - hide_server_address: { label: catalogSettingMessages.hideServerAddressLabel }, - server_textures: { label: catalogSettingMessages.serverTexturesLabel }, - snooper: { label: catalogSettingMessages.snooperLabel }, - extra_telemetry: { label: catalogSettingMessages.extraTelemetryLabel }, - in_game_notifications: { label: catalogSettingMessages.inGameNotificationsLabel }, - share_presence: { label: catalogSettingMessages.sharePresenceLabel }, - 'key.smooth_camera': { label: catalogKeyMessages.smoothCameraLabel }, - 'key.spectator_outlines': { label: catalogKeyMessages.spectatorOutlinesLabel }, - 'key.save_toolbar': { label: catalogKeyMessages.saveToolbarLabel }, - 'key.load_toolbar': { label: catalogKeyMessages.loadToolbarLabel }, - 'key.social_interactions': { label: catalogKeyMessages.socialInteractionsLabel }, - 'key.quick_actions': { label: catalogKeyMessages.quickActionsLabel }, - 'key.spectator_hotbar': { label: catalogKeyMessages.spectatorHotbarLabel }, - 'key.friends': { label: catalogKeyMessages.friendsLabel }, - 'key.toggle_gui': { label: catalogKeyMessages.toggleGuiLabel }, - 'key.toggle_spectator_shader': { label: catalogKeyMessages.toggleSpectatorShaderLabel }, - 'key.hotbar.1': { label: catalogKeyMessages.hotbar1Label }, - 'key.hotbar.2': { label: catalogKeyMessages.hotbar2Label }, - 'key.hotbar.3': { label: catalogKeyMessages.hotbar3Label }, - 'key.hotbar.4': { label: catalogKeyMessages.hotbar4Label }, - 'key.hotbar.5': { label: catalogKeyMessages.hotbar5Label }, - 'key.hotbar.6': { label: catalogKeyMessages.hotbar6Label }, - 'key.hotbar.7': { label: catalogKeyMessages.hotbar7Label }, - 'key.hotbar.8': { label: catalogKeyMessages.hotbar8Label }, - 'key.hotbar.9': { label: catalogKeyMessages.hotbar9Label }, - 'key.debug.overlay': { label: catalogKeyMessages.debugOverlayLabel }, - 'key.debug.modifier': { label: catalogKeyMessages.debugModifierLabel }, - 'key.debug.reload_chunks': { label: catalogKeyMessages.debugReloadChunksLabel }, - 'key.debug.hitboxes': { label: catalogKeyMessages.debugHitboxesLabel }, - 'key.debug.clear_chat': { label: catalogKeyMessages.debugClearChatLabel }, - 'key.debug.crash': { label: catalogKeyMessages.debugCrashLabel }, - 'key.debug.chunk_borders': { label: catalogKeyMessages.debugChunkBordersLabel }, - 'key.debug.advanced_tooltips': { - label: catalogKeyMessages.debugAdvancedTooltipsLabel, - }, - 'key.debug.copy_recreate_command': { - label: catalogKeyMessages.debugCopyRecreateCommandLabel, - }, - 'key.debug.spectate': { label: catalogKeyMessages.debugSpectateLabel }, - 'key.debug.switch_game_mode': { label: catalogKeyMessages.debugSwitchGameModeLabel }, - 'key.debug.options': { label: catalogKeyMessages.debugOptionsLabel }, - 'key.debug.focus_pause': { label: catalogKeyMessages.debugFocusPauseLabel }, - 'key.debug.dump_dynamic_textures': { - label: catalogKeyMessages.debugDumpDynamicTexturesLabel, - }, - 'key.debug.reload_resource_packs': { - label: catalogKeyMessages.debugReloadResourcePacksLabel, - }, - 'key.debug.profiling': { label: catalogKeyMessages.debugProfilingLabel }, - 'key.debug.copy_location': { label: catalogKeyMessages.debugCopyLocationLabel }, - 'key.debug.dump_version': { label: catalogKeyMessages.debugDumpVersionLabel }, - 'key.debug.profiling_chart': { label: catalogKeyMessages.debugProfilingChartLabel }, - 'key.debug.fps_charts': { label: catalogKeyMessages.debugFpsChartsLabel }, - 'key.debug.network_charts': { label: catalogKeyMessages.debugNetworkChartsLabel }, - 'key.debug.lightmap_texture': { label: catalogKeyMessages.debugLightmapTextureLabel }, - 'key.debug.improved_transparency': { - label: catalogKeyMessages.debugImprovedTransparencyLabel, - }, - } +const settingDescriptions: Record = { + graphics: settingMessages.graphicsDescription, + simulation_distance: settingMessages.simulationDistanceDescription, + gui_scale: settingMessages.guiScaleDescription, + view_bobbing: settingMessages.viewBobbingDescription, + vsync: settingMessages.vsyncDescription, + mipmap_levels: settingMessages.mipmapLevelsDescription, + biome_blend_radius: settingMessages.biomeBlendRadiusDescription, + music_toast: settingMessages.musicToastDescription, + invert_mouse: settingMessages.invertMouseDescription, + auto_jump: settingMessages.autoJumpDescription, + toggle_crouch: settingMessages.toggleCrouchDescription, + toggle_sprint: settingMessages.toggleSprintDescription, + discrete_mouse_scroll: settingMessages.discreteMouseScrollDescription, + chat_links: settingMessages.chatLinksDescription, + chat_links_prompt: settingMessages.chatLinksPromptDescription, + chat_opacity: settingMessages.chatOpacityDescription, + narrator: settingMessages.narratorDescription, + subtitles: settingMessages.subtitlesDescription, + high_contrast: settingMessages.highContrastDescription, + dark_splash: settingMessages.darkSplashDescription, + notification_time: settingMessages.notificationTimeDescription, + main_hand: settingMessages.mainHandDescription, + cape: settingMessages.capeDescription, + hat: settingMessages.hatDescription, + jacket: settingMessages.jacketDescription, + allow_server_listing: settingMessages.allowServerListingDescription, +} const categories: Record = { skin_customization: { @@ -1321,62 +280,6 @@ const categories: Record = { - 'graphics:fast': choiceMessages.fast, - 'graphics:fancy': choiceMessages.fancy, - 'graphics:fabulous': choiceMessages.fabulous, - 'graphics:custom': choiceMessages.custom, - 'main_hand:left': choiceMessages.left, - 'main_hand:right': choiceMessages.right, - 'chat_visibility:0': choiceMessages.shown, - 'chat_visibility:1': choiceMessages.commandsOnly, - 'chat_visibility:2': choiceMessages.hidden, - 'particles:0': choiceMessages.all, - 'particles:1': choiceMessages.decreased, - 'particles:2': choiceMessages.minimal, - 'narrator:0': choiceMessages.off, - 'narrator:1': choiceMessages.all, - 'narrator:2': choiceMessages.chat, - 'narrator:3': choiceMessages.system, - 'clouds:false': choiceMessages.off, - 'clouds:fast': choiceMessages.fast, - 'clouds:true': choiceMessages.fancy, - 'ambient_occlusion:off': choiceMessages.off, - 'ambient_occlusion:on': choiceMessages.on, - 'ambient_occlusion:minimum': choiceMessages.minimum, - 'ambient_occlusion:maximum': choiceMessages.maximum, - 'music_toast:never': choiceMessages.never, - 'music_toast:pause': choiceMessages.pause, - 'music_toast:pause_and_toast': choiceMessages.pauseAndToast, - 'legacy_view_distance:0': choiceMessages.far, - 'legacy_view_distance:1': choiceMessages.normal, - 'legacy_view_distance:2': choiceMessages.short, - 'legacy_view_distance:3': choiceMessages.tiny, - 'legacy_framerate_limit:0': choiceMessages.maxFps, - 'legacy_framerate_limit:1': choiceMessages.balanced, - 'legacy_framerate_limit:2': choiceMessages.powerSaver, - 'inactivity_framerate_limit:afk': choiceMessages.whileAfk, - 'inactivity_framerate_limit:minimized': choiceMessages.whenMinimized, - 'prioritize_chunk_updates:0': choiceMessages.none, - 'prioritize_chunk_updates:1': choiceMessages.byPlayer, - 'prioritize_chunk_updates:2': choiceMessages.nearby, - 'attack_indicator:0': choiceMessages.off, - 'attack_indicator:1': choiceMessages.crosshair, - 'attack_indicator:2': choiceMessages.hotbar, - 'chat_preview:0': choiceMessages.off, - 'chat_preview:1': choiceMessages.commandsOnly, - 'chat_preview:2': choiceMessages.on, - 'music_frequency:CONSTANT': choiceMessages.constant, - 'music_frequency:DEFAULT': choiceMessages.default, - 'music_frequency:FREQUENT': choiceMessages.frequent, - 'share_presence:all': choiceMessages.all, - 'share_presence:limited': choiceMessages.limited, - 'share_presence:none': choiceMessages.none, - 'graphics_backend:default': choiceMessages.default, - 'graphics_backend:opengl': choiceMessages.openGl, - 'graphics_backend:vulkan': choiceMessages.vulkan, -} - const validationMessages: Record = { missing_value: presentationMessages.validationMissingValue, no_compatible_instances: presentationMessages.validationNoCompatibleInstances, @@ -1384,22 +287,13 @@ const validationMessages: Record = changed_since_opened: presentationMessages.validationChangedSinceOpened, } -export function formatGameSettingLabel( - formatMessage: FormatMessage, - setting: EditableGameSetting, -): string { - if (setting.kind === 'external') return setting.raw_key ?? setting.option_id - const definition = knownSettings[setting.option_id] - return definition ? formatMessage(definition.label) : setting.option_id -} - export function formatGameSettingDescription( formatMessage: FormatMessage, setting: EditableGameSetting, ): string { if (setting.kind === 'external') return '' - const definition = knownSettings[setting.option_id] - return definition?.description ? formatMessage(definition.description) : '' + const description = settingDescriptions[setting.option_id] + return description ? formatMessage(description) : '' } export function gameSettingCategoryMessage(category: GameSettingCategory): MessageDescriptor { @@ -1411,15 +305,6 @@ export function gameSettingCategoryMessage(category: GameSettingCategory): Messa ) } -export function formatGameSettingChoice( - formatMessage: FormatMessage, - optionId: string, - value: string, -): string { - const message = choices[`${optionId}:${value}`] - return message ? formatMessage(message) : value -} - export function formatGameSettingValidation( formatMessage: FormatMessage, error: GameOptionValidationError | null | undefined, diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue index cfea5f58ff..ef0d768572 100644 --- a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/row.vue @@ -12,7 +12,11 @@ import { } from '@modrinth/ui' import { computed, ref } from 'vue' -import type { EditableGameSetting, GameOptionCanonicalValue } from '@/helpers/game-options' +import type { + EditableGameSetting, + GameOptionCanonicalValue, + GameSettingLocaleLabel, +} from '@/helpers/game-options' import GameSettingBooleanControl from './boolean-control.vue' import { @@ -26,9 +30,7 @@ import { import GameKeybindInput from './keybind-input.vue' import { minecraftLanguageOptions } from './languages' import { - formatGameSettingChoice, formatGameSettingDescription, - formatGameSettingLabel, formatGameSettingValidation, presentationMessages, } from './messages' @@ -36,6 +38,7 @@ import { const props = withDefaults( defineProps<{ setting: EditableGameSetting + localeLabel?: GameSettingLocaleLabel keybindConflicts?: string[] disabled?: boolean showSyncToggle?: boolean @@ -90,7 +93,9 @@ const messages = defineMessages({ }, }) -const settingLabel = computed(() => formatGameSettingLabel(formatMessage, props.setting)) +const settingLabel = computed( + () => props.localeLabel?.label ?? props.setting.raw_key ?? props.setting.option_id, +) const settingDescription = computed(() => formatGameSettingDescription(formatMessage, props.setting), ) @@ -105,7 +110,7 @@ const languageOptions = computed[]>(() => { const enumOptions = computed[]>(() => (props.setting.editor.choices ?? []).map((choice) => ({ value: choice.value, - label: formatGameSettingChoice(formatMessage, props.setting.option_id, choice.value), + label: props.localeLabel?.choices[choice.value] ?? choice.value, })), ) const isNumber = computed( diff --git a/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/use-labels.ts b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/use-labels.ts new file mode 100644 index 0000000000..e9d83bf966 --- /dev/null +++ b/apps/app-frontend/src/components/ui/settings/instances/game-settings-modal/use-labels.ts @@ -0,0 +1,87 @@ +import { useVIntl } from '@modrinth/ui' +import { listen, type UnlistenFn } from '@tauri-apps/api/event' +import { computed, type MaybeRefOrGetter, onScopeDispose, shallowRef, toValue, watch } from 'vue' + +import { + type EditableGameSetting, + type GameSettingLocaleLabel, + get_game_setting_locale_labels, +} from '@/helpers/game-options' + +export function useGameSettingLabels( + opened: MaybeRefOrGetter, + instanceId: MaybeRefOrGetter, + settings: MaybeRefOrGetter, +) { + const { locale } = useVIntl() + const labels = shallowRef>({}) + const optionIds = computed(() => + toValue(settings) + .map((setting) => setting.option_id) + .sort(), + ) + let generation = 0 + let stopListening: UnlistenFn | undefined + let refreshSources = false + + async function refresh() { + if (!toValue(opened) || !optionIds.value.length) return + const request = ++generation + const reindex = refreshSources + refreshSources = false + try { + const result = await get_game_setting_locale_labels( + toValue(instanceId), + locale.value, + optionIds.value, + reindex, + ) + if (request === generation && toValue(opened)) labels.value = result.settings + } catch (error) { + console.debug('Could not load Minecraft setting labels', error) + } + } + + watch( + () => toValue(opened), + (active, _, onCleanup) => { + let cancelled = false + onCleanup(() => { + cancelled = true + stopListening?.() + stopListening = undefined + generation++ + labels.value = {} + }) + if (!active) return + refreshSources = true + void listen('game-option-locales-updated', () => void refresh()) + .then((unlisten) => { + if (cancelled) unlisten() + else { + stopListening = unlisten + void refresh() + } + }) + .catch((error) => { + console.debug('Could not listen for Minecraft setting labels', error) + if (!cancelled) void refresh() + }) + }, + { flush: 'sync' }, + ) + + watch([locale, () => toValue(instanceId), () => optionIds.value.join('\n')], () => { + generation++ + labels.value = {} + void refresh() + }) + + onScopeDispose(() => { + generation++ + stopListening?.() + labels.value = {} + }) + + return labels +} diff --git a/apps/app-frontend/src/components/ui/world/WorldItem.vue b/apps/app-frontend/src/components/ui/world/WorldItem.vue index c7b1282ba2..1cb1b19655 100644 --- a/apps/app-frontend/src/components/ui/world/WorldItem.vue +++ b/apps/app-frontend/src/components/ui/world/WorldItem.vue @@ -6,6 +6,7 @@ import { EyeIcon, FolderOpenIcon, IssuesIcon, + Link2Icon, MoreVerticalIcon, NoSignalIcon, PlayIcon, @@ -252,6 +253,10 @@ const messages = defineMessages({ id: 'instance.worlds.create_shortcut', defaultMessage: 'Create shortcut', }, + syncedServer: { + id: 'instance.worlds.synced_server', + defaultMessage: 'Synced across instances', + }, linkedServer: { id: 'instance.worlds.linked_server', defaultMessage: 'Managed by server project', @@ -498,6 +503,16 @@ function openContextMenu(event: MouseEvent) { >