Merge pull request #10358 from CocofireHD/fix/8713-no-zoom-menu-in-extras-on-mac

Extras: a Zoom row that reaches the mod that replaced the extra
This commit is contained in:
Kacper authored and GitHub committed 2026-11-06 09:16:40 +01:00
commit cc3714e6ad
5 files changed
+102 -1

No files matched your search

@@ -2709,6 +2709,41 @@ impl OptionsUi {
}
rows
}
/// The row that reaches the Zoom mod that replaced the extra: its switch and settings page
/// when it is built in, else a note saying where it is installed (Options > Mods). Zoom
/// became an official native mod, so Extras has no setting of its own for it (#8713).
fn zoom_mod_row(s: &Settings) -> Row {
let Some(i) = s
.mods
.installed
.iter()
.position(|m| m.id == "zoom" && m.native.is_some())
else {
// A note, not a button: Options > Mods already has the one way into the Mods page
// (`every_setting_and_page_is_reached_from_one_place`).
return Row::Note(lang::get("horizon.extras.zoom_mod_install"));
};
let label = || Text::option_name_value(tr("horizon.extras.zoom"), on_off(s.mods.is_on(i)));
let toggle = |width| button(0.0, 0.0, width, label(), Act::ToggleMod(i));
let settings = s.mods.installed[i]
.native
.as_ref()
.is_some_and(|page| !page.keys.is_empty() || !page.buttons.is_empty());
if settings {
Row::Buttons(
toggle(150.0),
Some(button(
0.0,
0.0,
150.0,
tr("horizon.mods.settings"),
Act::ModSettings(i),
)),
)
} else {
Row::Buttons(toggle(310.0), None)
}
}
/// A native mod's page: its name, its keys as Key Binds rows (the
/// player's choice, else the default), then its buttons.
fn native_rows(&self, s: &Settings, i: usize) -> Vec<Row> {
@@ -2781,6 +2816,11 @@ impl OptionsUi {
// (Horizon Settings has it).
let preset = button(0.0, 0.0, 150.0, tr("horizon.pvp.preset"), Act::PvpPreset);
let mut rows = Vec::new();
if self.page() == Page::Extras {
// Zoom, the FPS counter, Keystrokes and the Minimap are official mods now;
// Extras keeps a way to the one players look for here (#8713).
rows.push(Self::zoom_mod_row(s));
}
if self.page() == Page::Pvp {
// The editor moves what the game shows: only from a world.
let edit = button(0.0, 0.0, 150.0, tr("horizon.pvp.editor"), Act::HudEditor);
@@ -6648,6 +6688,60 @@ mod tests {
);
}
#[test]
fn extras_reaches_the_zoom_mod_that_replaced_the_extra() {
let mut s = Settings::default();
let mut ui = OptionsUi::default();
ui.show(Page::Extras);
let english = || lang::Language::load(&[], "en_us");
// Without the mod, Extras says where it is installed (a note, not a second way into
// Options > Mods).
let (widgets, _, _, _) = lang::scoped(english(), || ui.layout(&s, 480.0, 4000.0)).0;
assert!(
widgets.iter().any(|w| matches!(
&w.kind,
WKind::Text { text, .. } if text.plain() == "Zoom: install from Mods"
)),
"Extras has no hint for the Zoom mod"
);
// Built in, Zoom's settings live on its page: Extras opens that page.
s.mods.installed.push(crate::mod_list::Installed {
id: "zoom".into(),
title: "Zoom 2.0.0".into(),
description: String::new(),
problem: None,
dev: false,
native: Some(crate::mod_list::NativePage {
keys: vec![["zoom".into(), "Zoom".into(), "key.keyboard.z".into()]],
buttons: Vec::new(),
}),
});
let (widgets, _, _, _) = lang::scoped(english(), || ui.layout(&s, 480.0, 4000.0)).0;
assert!(
widgets.iter().any(|w| matches!(
&w.kind,
WKind::Button {
act: Act::ModSettings(0),
label,
..
} if label.plain() == "Settings"
)),
"Extras doesn't open the Zoom mod's settings"
);
// The mod's switch is on the same row, so Extras keeps the Zoom setting it had.
assert!(
widgets.iter().any(|w| matches!(
&w.kind,
WKind::Button {
act: Act::ToggleMod(0),
label,
..
} if label.plain().starts_with("Zoom")
)),
"Extras doesn't switch the Zoom mod"
);
}
#[test]
fn exclusive_fullscreen_and_its_tooltips_follow_the_option() {
let mut s = Settings::default();
@@ -222,6 +222,8 @@
"horizon.extras.no_ai": "Keine KI",
"horizon.extras.agent_control": "Agentensteuerung",
"horizon.extras.discord_presence": "Discord Rich Presence",
"horizon.extras.zoom": "Zoom",
"horizon.extras.zoom_mod_install": "Zoom: über Mods installieren",
"horizon.extras.fullbright.tooltip": "Zeigt Blöcke und Objekte bei vollem Licht, selbst an dunklen Orten.",
"horizon.extras.dynamic_lights.tooltip": "Fackeln und andere Lichtquellen, die gehalten, fallen gelassen werden oder brennen, beleuchten die Blöcke um sich herum.",
"horizon.extras.own_name_tag.tooltip": "Zeigt deinen Namen in der dritten Person über deinem Kopf an, so wie andere Spieler ihn sehen. Versteckt, wenn der Server die Namen deines Teams verbirgt oder du unsichtbar bist.",
@@ -322,6 +322,8 @@
"horizon.extras.no_ai": "No AI",
"horizon.extras.agent_control": "Agent Control",
"horizon.extras.discord_presence": "Discord Rich Presence",
"horizon.extras.zoom": "Zoom",
"horizon.extras.zoom_mod_install": "Zoom: install from Mods",
"horizon.extras.splitscreen": "Splitscreen",
"horizon.extras.chat_animation": "Smooth chat",
"horizon.extras.chat_indicator": "Message indicator",
@@ -242,6 +242,8 @@
"horizon.extras.no_ai": "Bez AI",
"horizon.extras.agent_control": "Sterowanie agentem",
"horizon.extras.discord_presence": "Discord Rich Presence",
"horizon.extras.zoom": "Zoom",
"horizon.extras.zoom_mod_install": "Zoom: zainstaluj w Modach",
"horizon.extras.fullbright.tooltip": "Pokazuje bloki i byty w pełnym oświetleniu, nawet w ciemnych miejscach.",
"horizon.extras.dynamic_lights.tooltip": "Pochodnie i inne źródła światła trzymane w dłoni, upuszczone lub płonące oświetlają otaczające bloki.",
"horizon.extras.own_name_tag.tooltip": "Pokazuje twój nick nad głową w widoku z trzeciej osoby, tak jak widzą go inni gracze. Ukryty, gdy serwer ukrywa nazwy twojej drużyny lub jesteś niewidzialny.",
+2 -1
View File
@@ -77,7 +77,8 @@ horizon-rust/horizon-mods under `native/<name>/`, [mods.md](mods.md#horizons-off
options. Players install them from the launcher's Mods page, and the launcher builds them into the game
([native-mods.md](native-mods.md)). The game keeps
the hook points they use (`crates/horizon-client/src/game/native_hooks.rs`), and `horizon-extras.txt` keeps the old
keys and `movedToMods`.
keys and `movedToMods`. The Extras page keeps a **Zoom** row: the mod's switch and Settings button when
it is built in, else a note saying to install it from the Mods page.
The game still draws the minimap, for the native mod (`native_minimap` in `native_hooks.rs`, [mods.md](mods.md)):
- a corner map (top right by default), square or round, small/medium/large, zoom 0.5 to 4 blocks per pixel, rotating