Compare commits

..
Author SHA1 Message Date
Horizon agentandClaude Opus 5.5 8406d2c586 horizon-threads: the stack dump test samples only once the busy loop runs
The worker sent its handle and went straight into the loop, so the signal could land
while it was still waking the receiver (futex_wake in the mpsc send), and the busy
frame was not yet on its stack. It failed that way on CI (run 43194576407).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 14:38:30 +01:00
742 changed files with 9683 additions and 24260 deletions

No files matched your search

+2 -3
View File
@@ -2,9 +2,8 @@
## What and why
<!-- What this changes, and why. Link the issue it fixes ("Fixes #123"). Over about 500 lines of code
(docs and test files don't count): link the issue with its approved spec too ("Spec: #123"), CONTRIBUTING.md
"Large pull requests". -->
<!-- What this changes, and why. Link the issue it fixes ("Fixes #123"). Over about 500 lines: link the issue with its
approved spec too ("Spec: #123"), CONTRIBUTING.md "Large pull requests". -->
## Kind
+3 -4
View File
@@ -34,9 +34,8 @@ Feature → files → harness for the most-changed areas: [docs/architecture.md]
- Everything players run is Rust. Python/Java only for dev tools and harness drivers in `tools/`.
- Horizon-only features follow [docs/design-system.md](docs/design-system.md) and are off by default where
they would change the vanilla look.
- Small PRs (< ~500 lines of code; docs and test files don't count:
[CONTRIBUTING.md](CONTRIBUTING.md#pull-requests)). Labels: `feature` (players get something new), `skip-release`
(they see no change), none for a fix. Agents never add `release-now`: the maintainer decides it. Merges ship in batches of 5, or after
- Small PRs (< ~500 lines). Labels: `feature` (players get something new), `skip-release` (they see no
change), none for a fix. Agents never add `release-now`: the maintainer decides it. Merges ship in batches of 5, or after
6 hours ([docs/release-flow.md](docs/release-flow.md)).
- **No hardcoded user-facing strings.** Keep UI translation-ready from the start. In the launcher (`launcher/`), wrap visible text with `tr("...")` or `trf("... {arg} ...", &[("arg", &val)])` from `crate::i18n` instead of raw string literals or `format!`. In the game, use translation keys (`Text::tr`, `lang::get`), never hardcoded English strings.
- **Claim before you start**: comment `/claim` on the issue (no issue yet: open one, then claim it). An assigned
@@ -215,7 +214,7 @@ state stays separate from the library tests. This compiles gameplay twice for ex
| Resource packs | L: `packs.rs` + `packs/`, `pack_screen.rs`, `atlas_sources.rs`, `sprites.rs`, `mipmap.rs`, `model_library.rs`, `font.rs`, `mobs/cem.rs` + `mobs/cem_anim.rs` (OptiFine/EMF entity models and their animations); `horizon-client-core/src/lang.rs`; crates `horizon-assets`, `horizon-optifine`; G: `packs.rs` |
| Agent control | L: `control.rs` (socket), `bin/horizon-ctl/`; G: `control.rs`, `agent.rs`, `events.rs`, `ui_control.rs` ([docs/agent-control.md](docs/agent-control.md)) |
| Mods | crate `horizon-mods`; G: `mods.rs`; L: `mod_content.rs`, `mod_list.rs` |
| Horizon extras, settings | L: `extras.rs`, `graphics.rs`, `settings.rs`, `minimap.rs`; G: `extras.rs` + `extras/` (each extra's glue: `mouse_tweaks.rs`, `sorting.rs`, `pvp.rs`, `reconnect.rs`), `options.rs` |
| Horizon extras, settings | L: `extras.rs`, `graphics.rs`, `settings.rs`, `minimap.rs`; G: `extras.rs`, `tweaks.rs`, `options.rs` |
## How `Game` is organised
+2 -5
View File
@@ -144,9 +144,7 @@ it (edited on every push, never repeated): talk to its author in the thread befo
- **Small.** One change per pull request, under about 500 lines of code where you can; split bigger work into
pieces that each make sense alone. Small pull requests get reviewed and merged the same day. Bigger than that:
[large pull requests](#large-pull-requests). What counts: lines added plus lines removed, outside Markdown (`.md`)
files and test files (any `tests/` or `test/` folder, and `test_*.py`). Tests written inside a source file do count.
pr_ready counts it the same way and warns when a pull request is over.
[large pull requests](#large-pull-requests).
- **Fill in the template**: what and why, the vanilla reference, the pr_ready block, screenshots for anything you
can see.
- **Tick "Allow edits by maintainers".** When something small is left (a lint, a rebase, a nit) we push the fixup
@@ -171,8 +169,7 @@ How agents, checks, releases and signed updates keep this safe: [security](docs/
### Large pull requests
500 lines of code ([what counts](#pull-requests)) stays the default. A pull request that can't be split below it
starts from a spec:
500 lines stays the default. A pull request that can't be split below it starts from a spec:
1. **Open an issue with the spec** before the code: what changes, the files it touches, the behaviour players and
other code will see, and the tests or harnesses that prove it.
Generated
+2 -1
View File
@@ -1505,6 +1505,7 @@ dependencies = [
"bytemuck",
"chrono",
"crc32fast",
"dunce",
"flate2",
"fs4",
"gilrs",
@@ -1546,6 +1547,7 @@ dependencies = [
"objc2 0.6.5",
"objc2-app-kit 0.3.2",
"objc2-foundation 0.3.2",
"open",
"png",
"pollster",
"rustix 1.1.5",
@@ -1589,7 +1591,6 @@ dependencies = [
"bytemuck",
"chrono",
"crc32fast",
"dunce",
"flate2",
"fs4",
"getrandom 0.3.4",
-5
View File
@@ -62,8 +62,6 @@ The GLSL frontend also resets the common type for each comma-separated declarato
variable's array specifier does not change later variables.
It also reads a struct member outside a constant expression through a pointer to the member,
not out of a loaded copy of the whole struct, so a member an atomic function uses can be read.
The shared interpolation defaults also compile with `glsl-in` alone, without needing the
SPIR-V or WGSL frontend to enable them.
## DirectX Shader Compiler
@@ -358,9 +356,6 @@ Horizon (Copyright (c) 2026 Ludovic Marie and the Horizon contributors).
`crates/horizon-client-render/src/touch.rs` and `touch/tests/` are adapted from the touch input
state of Starling's `crates/horizon-client-render/src/touch.rs` at the same commit.
`crates/horizon-client-render/src/touch/draw.rs` is adapted from the touch control drawing in
Starling's `crates/horizon-client-render/src/touch.rs` at the same commit.
`crates/horizon-client-render/src/android_runtime.rs` and `android_runtime/tests/` are adapted from the
input part of Starling's `crates/horizon-client-render/src/android_runtime.rs` at the same commit.
+1 -33
View File
@@ -206,7 +206,7 @@ impl Config {
Ok(file.anticheat)
}
/// Thresholds can't be negative, and neither can the timer's milliseconds.
/// Thresholds can't be negative.
pub fn check(&self) -> Result<(), String> {
for &c in Check::ALL {
let a = self.actions(c);
@@ -220,18 +220,6 @@ impl Config {
));
}
}
// A negative tolerance flags a client on time every tick, and so does a cap below minus the
// tolerance (the balance rests at the cap); NaN never flags, or never caps the balance. No
// negative number of milliseconds means anything, so all are refused.
if [self.timer.tolerance_ms, self.timer.max_lag_ms]
.iter()
.any(|v| !v.is_finite() || *v < 0.0)
{
return Err(
"anticheat.timer: tolerance_ms and max_lag_ms are numbers of milliseconds from 0 up"
.into(),
);
}
let tolerance = self.prediction.tolerance;
if !tolerance.is_finite() || tolerance <= 0.0 {
return Err("anticheat.prediction: tolerance is a number of blocks above 0".into());
@@ -373,26 +361,6 @@ mod tests {
assert!(Config::from_server_toml("[anticheat.timer]\nkick = -1\n").is_err());
}
/// A negative `tolerance_ms` flags a client on time every tick, and so does a `max_lag_ms` below
/// `-tolerance_ms` (the balance rests at the cap); a NaN turns the check (or its cap) off without a
/// word. Every negative or non-finite value is refused, as a negative threshold is.
#[test]
fn refuses_timer_settings_that_are_not_milliseconds_from_0_up() {
for bad in [
"tolerance_ms = -1",
"tolerance_ms = nan",
"tolerance_ms = inf",
"max_lag_ms = -1",
"max_lag_ms = nan",
] {
let text = format!("[anticheat.timer]\n{bad}\n");
let e = Config::from_server_toml(&text).expect_err(bad);
assert!(e.starts_with("anticheat.timer:"), "{bad}: {e}");
}
let edge = "[anticheat.timer]\ntolerance_ms = 0\nmax_lag_ms = 0\n";
assert!(Config::from_server_toml(edge).is_ok());
}
#[test]
fn levels_rise_decay_and_act_in_order() {
let mut c = on();
+1 -25
View File
@@ -45,11 +45,6 @@ mod tests {
/// `seconds` of server ticks of `server_ms` each, with `per_tick` client ticks handled in each.
fn run(b: &mut Balance, server_ms: f64, per_tick: f64, seconds: f64) -> usize {
run_at(b, 20.0, server_ms, per_tick, seconds)
}
/// [`run`] at the tick rate `rate` (`/tick rate`), which the client's ticks follow.
fn run_at(b: &mut Balance, rate: f32, server_ms: f64, per_tick: f64, seconds: f64) -> usize {
let c = TimerConfig::default();
let mut owed = 0.0;
let mut flags = 0;
@@ -58,31 +53,12 @@ mod tests {
owed += per_tick;
while owed >= 1.0 {
owed -= 1.0;
flags += usize::from(b.tick_end(rate, &c).is_some());
flags += usize::from(b.tick_end(20.0, &c).is_some());
}
}
flags
}
/// At another tick rate a vanilla client ticks at the rate the server sent it, and each of its
/// ticks is worth `1000 / rate` ms: never flagged on time, flagged again and again 1.5 times as fast.
#[test]
fn the_balance_follows_the_tick_rate() {
for rate in [10.0_f32, 60.0] {
let tick_ms = 1000.0 / f64::from(rate);
assert_eq!(
run_at(&mut Balance::default(), rate, tick_ms, 1.0, 600.0),
0,
"on time at {rate}"
);
// Half a tick ahead every server tick: 75 flags in a minute at 10 a second, 94 at 60.
let flags = run_at(&mut Balance::default(), rate, tick_ms, 1.5, 60.0);
assert!(flags >= 50, "1.5 times as fast at {rate}: {flags} flags");
}
// The rate counts: at 10 a second, a client sending 20 ticks a second is twice as fast.
assert!(run_at(&mut Balance::default(), 10.0, 100.0, 2.0, 60.0) >= 50);
}
#[test]
fn a_vanilla_client_is_never_flagged() {
let mut b = Balance::default();
+17 -66
View File
@@ -952,16 +952,8 @@ mod tests {
(en, seen)
}
/// The crates whose `horizon.` keys must be in en_us.json.
const CLIENT_CRATES: [&str; 4] = [
"horizon-client",
"horizon-client-render",
"horizon-client-core",
"horizon-client-input",
];
/// The Rust sources of `krates`, or of every crate under `crates/` when it is empty.
fn crate_sources(krates: &[&str]) -> Vec<std::path::PathBuf> {
#[test]
fn every_horizon_key_the_code_names_is_in_en_us() {
fn rust_files(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
for entry in std::fs::read_dir(dir).into_iter().flatten().flatten() {
let path = entry.path();
@@ -972,68 +964,27 @@ mod tests {
}
}
}
let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut files = Vec::new();
if krates.is_empty() {
for entry in std::fs::read_dir(&crates).unwrap().flatten() {
rust_files(&entry.path().join("src"), &mut files);
}
}
for krate in krates {
rust_files(&crates.join(krate).join("src"), &mut files);
}
assert!(files.len() > 100, "found only {} sources", files.len());
files
}
/// A sentence key (the English text itself, not a `horizon.` id) that no
/// source names as a string literal is text the game no longer shows: its
/// rewording left it behind in every language (#13802).
#[test]
fn every_sentence_key_in_en_us_is_one_the_code_names() {
let en: HashMap<String, String> = serde_json::from_str(
&std::fs::read_to_string(bundled_dir().join("en_us.json")).unwrap(),
)
.unwrap();
// Every crate: a feature moved out of the client crates keeps its strings.
let code: String = crate_sources(&[])
.iter()
.map(|file| std::fs::read_to_string(file).unwrap())
.collect();
let sentences: Vec<&String> = en.keys().filter(|k| !k.starts_with("horizon.")).collect();
assert!(
sentences.len() > 100,
"found only {} sentence keys",
sentences.len()
);
// A JSON string literal escapes `"` and `\` as Rust's does.
let mut dead: Vec<&str> = sentences
.into_iter()
.filter(|key| !code.contains(&serde_json::to_string(key).unwrap()))
.map(String::as_str)
.collect();
dead.sort_unstable();
assert!(
dead.is_empty(),
"en_us.json keys no code asks for: {dead:#?}"
);
}
#[test]
fn every_horizon_key_the_code_names_is_in_en_us() {
let english = |dir: &std::path::Path| -> HashMap<String, String> {
serde_json::from_str(&std::fs::read_to_string(dir.join("en_us.json")).unwrap()).unwrap()
};
let mut en = english(&bundled_dir());
let mut krates = CLIENT_CRATES.to_vec();
// A crate that ships lang files names its keys in its own sources.
let lang_dirs = crate_lang_dirs();
for (name, dir) in &lang_dirs {
en.extend(english(dir));
krates.push(name);
let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut files = Vec::new();
for krate in [
"horizon-client",
"horizon-client-render",
"horizon-client-core",
] {
rust_files(&crates.join(krate).join("src"), &mut files);
}
// A crate that ships lang files names its keys in its own sources.
for (name, dir) in crate_lang_dirs() {
en.extend(english(&dir));
rust_files(&crates.join(name).join("src"), &mut files);
}
assert!(files.len() > 100, "found only {} sources", files.len());
let mut found = 0;
for file in crate_sources(&krates) {
for file in files {
let text = std::fs::read_to_string(&file).unwrap();
for (at, _) in text.match_indices("\"horizon.") {
let rest = &text[at + 1..];
-4
View File
@@ -93,8 +93,6 @@ rustix = { version = "1", default-features = false, features = ["std", "time", "
[target.'cfg(windows)'.dependencies]
# Use the registered URI handler without routing links through Explorer/cmd.
open = { version = "5.4.5", features = ["shellexecute-on-windows"] }
# Resolve virtualized folders to shell-compatible physical paths (desktop.rs).
dunce = "1.0.5"
# DirectX 12, where Vulkan has no adapter or device, or by choice (`graphicsApi`, graphics.rs).
# Shaders compile with FXC (d3dcompiler_47.dll, part of Windows), or on integrated GPUs with DXC
# (dxcompiler.dll beside the game, gfx/dx12_compiler.rs).
@@ -114,8 +112,6 @@ wgpu = { version = "30.0.1", default-features = false, features = ["gles"] }
[features]
default = ["audio", "controllers"]
# Dev-only: the ignored tracker-send benchmark uses the executable's allocator.
tracker-send-bench = []
# Sound output. Without it (and `controllers`) the program links neither libasound nor libudev on
# Linux: the server build (`--no-default-features`, released as horizon-engine; docs/server.md).
audio = ["horizon-client-render/audio"]
@@ -1442,8 +1442,6 @@ impl Audio {
} else {
Err("no output on a dedicated server".into())
};
// Without `audio` a stream can't exist (`Infallible`), so the `Ok` arm never runs.
#[cfg_attr(not(feature = "audio"), allow(unreachable_code))]
let (stream, live) = match opened {
Ok(v) => (Some(v), true),
Err(e) => {
+1 -13
View File
@@ -1279,9 +1279,6 @@ pub struct ChatScreen {
/// `CommandSuggestions.setRestrictions`: what the Chat option allows.
pub abilities: ChatAbilities,
pub layout: SuggestLayout,
/// `MouseHandler.lastClick`: a click within 250 ms of the last one on
/// this screen is a double click.
last_click: Option<std::time::Instant>,
}
/// Local completions waiting for the server's reply to request `id`.
struct Awaiting {
@@ -1404,7 +1401,6 @@ impl ChatScreen {
auto_suggestions: true,
abilities,
layout: SuggestLayout::CHAT,
last_click: None,
};
s.update_command_info(m, c);
s
@@ -1443,7 +1439,6 @@ impl ChatScreen {
auto_suggestions: true,
abilities: ChatAbilities::new(ChatVisibility::Full),
layout: SuggestLayout::COMMAND_BLOCK,
last_click: None,
};
s.update_command_info(m, c);
s
@@ -1971,15 +1966,8 @@ impl ChatScreen {
}
self.suggestions = Some(l);
}
// MouseHandler: the same screen's click within 250 ms is a double
// click, which selects the word under the pointer.
let now = std::time::Instant::now();
let double = self
.last_click
.is_some_and(|at| now.duration_since(at).as_millis() < 250);
self.last_click = Some(now);
if self.input.contains(x, y) {
self.input.click(m, x, false, double);
self.input.click(m, x, false);
return true;
}
false
@@ -305,31 +305,6 @@ fn locate_coordinates_fill_chat_with_teleport_without_submitting() {
}
}
/// `EditBox.onClick`: a double click selects the word under the pointer; a
/// single click only places the caret there.
#[test]
fn a_double_click_in_the_chat_box_selects_the_word() {
let font = font();
let m = Measure(&font);
let registries = Registries::default();
let c = Commands {
dispatcher: crate::command::vanilla::game_dispatcher(),
registries: &registries,
};
let mut screen = ChatScreen::new(&m, &c, "", false, 0, 640, 360, full());
screen.type_text(&m, &c, "hello world");
// The pointer on the last letter: the first click places the caret there,
// the second takes the word.
let x = f64::from(screen.input.x) + f64::from(font.width("hello world")) - 1.0;
let y = f64::from(screen.input.y) + 2.0;
assert!(screen.click(&m, &c, x, y));
assert!((10..=11).contains(&screen.input.cursor));
assert_eq!(screen.input.highlight, screen.input.cursor);
assert!(screen.click(&m, &c, x, y));
assert_eq!((screen.input.highlight, screen.input.cursor), (6, 11));
assert_eq!(screen.input.selected_text(), "world");
}
#[test]
fn history_arrows_recall_messages_and_restore_the_draft() {
use winit::keyboard::KeyCode::{ArrowDown, ArrowUp};
-25
View File
@@ -715,31 +715,6 @@ impl Chunk {
pub fn block(&self, x: i32, y: i32, z: i32) -> BlockStateId {
BlockStateId(self.get(x, y, z))
}
/// The blocks that `matches`, section by section from the bottom, each section's in y, z, x
/// order. A section whose palette holds none is skipped.
pub fn blocks_where(
&self,
matches: impl Fn(BlockStateId) -> bool,
) -> Vec<horizon_core::position::BlockPos> {
let mut out = Vec::new();
for (s, section) in self.sections.iter().enumerate() {
if !section.blocks.maybe_has(|v| matches(BlockStateId(v))) {
continue;
}
let base = self.min_y + 16 * s as i32;
for y in base..base + 16 {
for lz in 0..16 {
for lx in 0..16 {
let (wx, wz) = (self.x * 16 + lx, self.z * 16 + lz);
if matches(self.block(wx, y, wz)) {
out.push(horizon_core::position::BlockPos::new(wx, y, wz));
}
}
}
}
}
out
}
/// The highest y where `matches`, scanning down. Sections holding only
/// `skip` are passed over whole: `matches` must be false for it.
pub fn highest(&self, skip: u32, mut matches: impl FnMut(i32) -> bool) -> Option<i32> {
@@ -413,20 +413,12 @@ pub enum NameOrId {
pub struct Crafter {
pub items: [Option<ItemStack>; 9],
pub disabled: [bool; 9],
/// `containerData` slot 9 as saved (`triggered`): any int, triggered
/// only at 1 ([`Crafter::is_triggered`]).
pub triggered: i32,
pub triggered: bool,
pub crafting_ticks: i32,
/// The block state's `triggered` when last ticked (not saved): the block
/// entity flag follows it only when it changes (`CrafterBlock.neighborChanged`).
pub state_triggered: Option<bool>,
}
impl Crafter {
/// `CrafterBlockEntity.isTriggered`: `containerData.get(9) == 1`.
pub fn is_triggered(&self) -> bool {
self.triggered == 1
}
}
#[derive(Clone, Debug, Default)]
pub struct Banner {
pub layers: Vec<BannerLayer>,
@@ -473,9 +465,6 @@ pub struct Jukebox {
/// reference exists. Keep this separate from legacy playback adoption.
pub song_clock_present: bool,
pub playing: bool,
/// A clock a save brought back, not playing yet: `setSongWithoutPlaying`
/// keeps the song and its clock without the sound's level event 1010.
pub loaded_clock: bool,
}
impl Jukebox {
/// `JukeboxBlockEntity.getTheItem`: the disc it holds.
@@ -291,15 +291,10 @@ impl SceneCollisions<'_, '_> {
}
fn context(&self, bounds: Aabb) -> CollisionContext<'static> {
let y = bounds.min_position().y;
// An entity context is needed wherever PowderSnowBlock or a strider
// reads the entity: boots, the walkable tag, a long fall.
if !self.subject.is_some_and(|s| {
s.lava_walker
|| s.leather_boots
|| s.walkable_type
|| s.falling_block
|| s.fall_distance > 2.5
}) {
if !self
.subject
.is_some_and(|s| s.lava_walker || s.leather_boots)
{
return CollisionContext::position(y);
}
CollisionContext::for_entity(
@@ -3,8 +3,7 @@
//! - a function with `sampler2D` parameters is copied once per set of samplers its callers pass
//! (all of them a shader's global samplers), the copy reading those samplers by name;
//! - an unsized array (`const float[] w = float[](...)`, `float w[] = ...`) takes the size its
//! initializer gives;
//! - an array declared with a `const int`'s size takes the constant's expression.
//! initializer gives.
/// The longest shader rewritten (vanilla's, includes expanded, are a few KiB).
const MAX_LEN: usize = 64 * 1024;
@@ -18,115 +17,7 @@ pub(super) fn fixups(text: &str) -> String {
if text.len() > MAX_LEN {
return text.to_owned();
}
size_by_int_constants(&size_unsized_arrays(&specialize_sampler_params(text)))
}
/// The most `const int`s a shader's arrays are sized by.
const MAX_INT_CONSTANTS: usize = 256;
/// `type name[n]` becomes `type name[(expression)]` where `const int n = expression;` is in scope;
/// accesses (`name[n]`) are left as they are. Two constants of one name and different values in
/// one scope, which only exclusive `#if` branches allow, leave the text as it was; the same one
/// twice is a guarded include pasted twice.
fn size_by_int_constants(text: &str) -> String {
struct Constant<'a> {
name: &'a str,
expression: &'a str,
from: usize,
to: usize,
}
let bytes = text.as_bytes();
let mut constants: Vec<Constant> = Vec::new();
let mut scopes: Vec<Vec<usize>> = vec![Vec::new()];
let mut i = 0;
while i < bytes.len() {
match bytes[i] {
b'{' => scopes.push(Vec::new()),
b'}' => {
for c in scopes.pop().unwrap_or_default() {
constants[c].to = i;
}
if scopes.is_empty() {
return text.to_owned();
}
}
b'c' if text[i..].starts_with("const int ")
&& (i == 0 || !is_ident(char::from(bytes[i - 1]))) =>
{
let start = i + "const int ".len();
let Some(end) = text[start..].find([';', '{', '}']).map(|e| start + e) else {
break;
};
if bytes[end] == b';'
&& let Some((name, expression)) = text[start..end].split_once('=')
{
let (name, expression) = (name.trim(), expression.trim());
if is_name(name) && !expression.is_empty() {
let scope = scopes.last_mut().expect("the global scope stays");
let same = scope.iter().find(|&&c| constants[c].name == name);
match same {
Some(&c) if constants[c].expression == expression => {}
Some(_) => return text.to_owned(),
None if constants.len() == MAX_INT_CONSTANTS => {
return text.to_owned();
}
None => {
scope.push(constants.len());
constants.push(Constant {
name,
expression,
from: end,
to: text.len(),
});
}
}
}
}
i = end;
continue;
}
_ => {}
}
i += 1;
}
if constants.is_empty() {
return text.to_owned();
}
let mut out = String::with_capacity(text.len());
let mut copied = 0;
let mut at = 0;
while let Some(found) = text[at..].find('[') {
let open = at + found;
at = open + 1;
let Some(close) = text[open..].find(']').map(|c| open + c) else {
break;
};
let size = text[open + 1..close].trim();
let Some(constant) = constants
.iter()
.filter(|c| c.name == size && c.from < open && open < c.to)
.max_by_key(|c| c.from)
else {
continue;
};
if !declares_an_array(text, open) {
continue;
}
out.push_str(&text[copied..=open]);
out.push('(');
out.push_str(constant.expression);
out.push(')');
copied = close;
}
out.push_str(&text[copied..]);
out
}
/// Whether the `[` at `open` follows `type name`, so it sizes a declaration.
fn declares_an_array(text: &str, open: usize) -> bool {
ident_before(text, open)
.and_then(|(start, _)| ident_before(text, start))
.is_some_and(|(_, ty)| !matches!(ty, "return" | "else" | "case"))
size_unsized_arrays(&specialize_sampler_params(text))
}
fn is_ident(c: char) -> bool {
@@ -245,72 +245,6 @@ fn thousands_of_calls_are_left_as_they_were() {
);
}
#[test]
fn an_array_sized_by_a_local_int_constant_takes_its_expression() {
let text =
"void main() {\n const int n = COUNT / 4;\n vec4 s[n];\n s[0] = vec4(n);\n}\n";
let out = size_by_int_constants(text);
assert!(out.contains("vec4 s[(COUNT / 4)];"), "{out}");
assert!(out.contains("s[0] = vec4(n);"), "{out}");
}
#[test]
fn each_function_sizes_by_its_own_constant_and_accesses_are_kept() {
let text = "float f() {\n const int n = 2;\n float a[n];\n a[1] = 1.0;\n return a[n - 1];\n}\n\
float g() {\n const int n = 4;\n float b[n];\n b[3] = 1.0;\n float c = b[n];\n return c;\n}\n";
let out = size_by_int_constants(text);
assert!(out.contains("float a[(2)];"), "{out}");
assert!(out.contains("float b[(4)];"), "{out}");
assert!(out.contains("b[3] = 1.0;"), "{out}");
assert!(out.contains("float c = b[n];"), "{out}");
assert!(out.contains("return a[n - 1];"), "{out}");
}
#[test]
fn an_inner_constant_shadows_the_outer_one_only_inside_its_block() {
let text = "void main() {\n const int n = 2;\n {\n const int n = 4;\n float inner[n];\n }\n\
float outer[n];\n}\n";
let out = size_by_int_constants(text);
assert!(out.contains("float inner[(4)];"), "{out}");
assert!(out.contains("float outer[(2)];"), "{out}");
}
#[test]
fn constants_of_exclusive_branches_leave_the_text_as_it_was() {
let text = "void main() {\n#ifdef A\n const int n = 2;\n#else\n const int n = 4;\n#endif\n float a[n];\n}\n";
assert_eq!(size_by_int_constants(text), text);
}
#[test]
fn a_guarded_include_pasted_twice_still_sizes_its_arrays() {
let include = "#ifndef I\n#define I\nconst int bins = 2;\n#endif\n";
let text = format!("{include}{include}void main() {{\n float a[bins];\n}}\n");
assert!(size_by_int_constants(&text).contains("float a[(2)];"));
}
#[test]
fn arrays_sized_by_two_functions_constants_translate_to_their_own_sizes() {
let fsh = "#version 330\nout vec4 fragColor;\n\
float f() {\n const int n = 2;\n float a[n];\n a[1] = 1.0;\n return a[1];\n}\n\
float g() {\n const int n = 4;\n float b[n];\n b[3] = 1.0;\n return b[3];\n}\n\
void main() {\n fragColor = vec4(f() + g());\n}\n";
let program = translate(fsh).unwrap();
let mut sizes: Vec<u32> = program
.fragment
.types
.iter()
.filter_map(|(_, ty)| match ty.inner {
naga::TypeInner::Array {
size: naga::ArraySize::Constant(n),
..
} => Some(n.get()),
_ => None,
})
.collect();
sizes.sort_unstable();
assert_eq!(sizes, [2, 4]);
}
#[test]
fn unsized_arrays_take_their_initializers_size() {
let text = "const float[] w = float[](0.25, 0.5, 0.25);\n\
+177 -3
View File
@@ -210,7 +210,6 @@ mod hdr_icc;
mod hdr_start;
mod hdr_stats;
pub(crate) mod hud_coverage;
mod in_flight;
pub use hdr::{Calibration as HdrCalibration, Output as HdrOutput};
mod hold;
pub use hold::WorldHold;
@@ -12352,6 +12351,133 @@ pub(crate) fn copy_frame(
);
buffer
}
impl Renderer {
/// The frame's readbacks to start right after its submission (on the submit thread when
/// the frame goes there): occlusion culling's results (`cull`) and GPU culling's
/// statistics. GPU frames leave occlusion culling off, so a frame has one at most.
fn after_submit(&mut self) -> Option<submit::AfterSubmit> {
let cull = self.cull.as_mut().and_then(|c| c.submitted());
let gpu = self.gpu_culling.as_mut().and_then(|g| g.submitted());
match (cull, gpu) {
(Some(c), Some(g)) => Some(Box::new(move || {
c();
g();
})),
(Some(c), None) => Some(Box::new(c)),
(None, Some(g)) => Some(Box::new(g)),
(None, None) => None,
}
}
/// Frame `frame`'s statistics shown, unless a newer frame's are: a CPU frame's as it is
/// drawn, a GPU frame's when its counts come back (`GpuCulling::collect`).
fn show_stats(&mut self, frame: u64, [sections, draws, calls]: [usize; 3]) {
if frame > self.stats_frame {
self.stats_frame = frame;
(
self.drawn_sections,
self.section_draws,
self.section_draw_calls,
) = (sections, draws, calls);
}
}
/// Frames between the last one drawn and the one whose statistics are shown: 0 after a
/// CPU frame, one to three in GPU frames, while their counts are on their way back.
pub fn stats_lag(&self) -> u64 {
self.frame_serial - self.stats_frame
}
/// Take in the frame the submit thread submitted: start its readbacks and, offscreen,
/// keep at most two frames ahead of the GPU, as a frame submitted in place does.
fn land_frame(&mut self) {
let Some(offscreen) = self.deferred.take() else {
return;
};
let submission = self.queue.landed();
if let Some(timer) = &mut self.gpu_timer {
timer.submitted(&self.queue);
timer.collect(&self.device, &mut self.gpu_times);
}
if let Some(Some(timer)) = Self::pass_timer(&mut self.pack_post, &mut self.native) {
timer.submitted(&self.queue);
}
if let Some(timer) = &mut self.own_timing {
timer.submitted(&self.queue);
}
if offscreen && let Some(submission) = submission {
self.in_flight.push_back(submission);
if !self.paced_elsewhere {
self.wait_frames();
}
}
}
/// No swapchain paces offscreen frames: keep two on the GPU at most.
pub fn wait_in_flight(&mut self) {
self.land_frame();
self.wait_frames();
}
/// The frame on the submit thread submitted: a surface reconfigure waits for the
/// device and breaks if a frame is submitted while it waits, and the compositor
/// copies views after them. (The end of a frame already lands the frames of the
/// turn before; this is the turn's own.)
pub fn wait_submissions(&mut self) {
self.queue.wait();
}
fn wait_frames(&mut self) {
while self.in_flight.len() > 2 {
let index = self.in_flight.pop_front();
let _ = self.device.poll(wgpu::PollType::Wait {
submission_index: index,
timeout: Some(std::time::Duration::from_secs(5)),
});
}
}
/// Take a screenshot request: queue the frame's copy, or report why the
/// frame cannot be read back.
fn take_readback(
&mut self,
request: ScreenshotRequest,
encoder: &mut wgpu::CommandEncoder,
texture: &wgpu::Texture,
) -> Option<(ScreenshotRequest, wgpu::Buffer)> {
// The copy and PNG writer both assume 8-bit pixels; a float surface would make
// the row stride too small for the copy and abort in validation.
if self.config.format.block_copy_size(None) == Some(4) {
let size = [self.config.width, self.config.height];
let format = self.config.format.remove_srgb_suffix();
// The layered float frame maps the world to SDR, then adds the HUD as drawn.
// Other 16-bit frames keep their clipped 8-bit copy.
let copy = self
.hdr
.as_mut()
.and_then(|hdr| {
hdr.sdr_screenshot(&self.device, encoder, format, request.size.is_some())
})
.or_else(|| {
(texture.format() != format && texture.format() == self.output.frame.format)
.then(|| {
self.readback
.unorm_copy(&self.device, encoder, texture, format)
})
});
let texture = copy.as_ref().unwrap_or(texture);
Some((request, copy_frame(&self.device, encoder, texture, size)))
} else {
let error = format!(
"screenshots need a 32-bit surface format, not {:?}",
self.config.format
);
if request.background {
self.saved_screenshots.push(screenshot_save::Saved {
path: request.path,
result: Err(error),
hdr: None,
});
} else {
self.screenshot_result = Some(Err(error));
}
None
}
}
}
/// `screenshots/2026-10-28_12.00.00.png` -> `screenshots/2026-10-28_12.00.00-hdr.png`.
fn hdr_screenshot_path(path: &std::path::Path) -> PathBuf {
let stem = path.file_stem().unwrap_or_default().to_string_lossy();
@@ -12457,8 +12583,56 @@ fn block_entities_within_reach<'a>(
})
.flatten()
}
mod view_frustum;
pub use view_frustum::Frustum;
/// Camera-relative clip planes (`Frustum`).
#[derive(Clone, Copy, Debug)]
pub struct Frustum {
planes: [Vec4; 6],
}
impl Frustum {
/// Whether the camera-relative box `min..max` is at least partly inside.
pub fn intersects(&self, min: Vec3, max: Vec3) -> bool {
!self.planes.iter().any(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, max, min);
p.truncate().dot(v) + p.w < 0.0
})
}
/// Whether a camera-relative sphere is at least partly inside. Frustum
/// planes are normalized, so each test needs only one dot product and a
/// radius comparison.
pub fn intersects_sphere(&self, center: Vec3, radius: f32) -> bool {
if !center.is_finite() || !radius.is_finite() || radius < 0.0 {
return true;
}
!self
.planes
.iter()
.any(|plane| plane.truncate().dot(center) + plane.w < -radius)
}
/// Depth clip planes alone: X/Y projection jitter cannot change this test.
/// Retaining side-of-screen geometry makes this safe before TAA selects a phase.
pub fn intersects_depth(&self, min: Vec3, max: Vec3) -> bool {
if !min.is_finite() || !max.is_finite() || !min.cmple(max).all() {
return true;
}
!self.planes[4..].iter().any(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, max, min);
p.truncate().dot(v) + p.w < 0.0
})
}
/// Whether the camera-relative box `min..max` is entirely inside. Then
/// `intersects` accepts every box within it: each plane's distance only
/// grows from this box's nearest corner to the inner box's farthest, and
/// rounding keeps that order.
pub fn contains(&self, min: Vec3, max: Vec3) -> bool {
self.planes.iter().all(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, min, max);
p.truncate().dot(v) + p.w >= 0.0
})
}
}
/// Vanilla's `Projection`: reversed depth (near maps to 1, far to 0, tests
/// are GREATER_THAN_OR_EQUAL), which keeps far faces a hair apart, like
/// fire_side's 0.01 pixel in front of its block, from z-fighting.
@@ -1,132 +0,0 @@
//! Frames in flight: the readbacks a submission starts, landing frames the submit thread
//! submitted, keeping offscreen frames at most two ahead of the GPU, and a screenshot's copy.
use super::{Renderer, ScreenshotRequest, copy_frame, screenshot_save, submit};
impl Renderer {
/// The frame's readbacks to start right after its submission (on the submit thread when
/// the frame goes there): occlusion culling's results (`cull`) and GPU culling's
/// statistics. GPU frames leave occlusion culling off, so a frame has one at most.
pub(super) fn after_submit(&mut self) -> Option<submit::AfterSubmit> {
let cull = self.cull.as_mut().and_then(|c| c.submitted());
let gpu = self.gpu_culling.as_mut().and_then(|g| g.submitted());
match (cull, gpu) {
(Some(c), Some(g)) => Some(Box::new(move || {
c();
g();
})),
(Some(c), None) => Some(Box::new(c)),
(None, Some(g)) => Some(Box::new(g)),
(None, None) => None,
}
}
/// Frame `frame`'s statistics shown, unless a newer frame's are: a CPU frame's as it is
/// drawn, a GPU frame's when its counts come back (`GpuCulling::collect`).
pub(super) fn show_stats(&mut self, frame: u64, [sections, draws, calls]: [usize; 3]) {
if frame > self.stats_frame {
self.stats_frame = frame;
(
self.drawn_sections,
self.section_draws,
self.section_draw_calls,
) = (sections, draws, calls);
}
}
/// Frames between the last one drawn and the one whose statistics are shown: 0 after a
/// CPU frame, one to three in GPU frames, while their counts are on their way back.
pub fn stats_lag(&self) -> u64 {
self.frame_serial - self.stats_frame
}
/// Take in the frame the submit thread submitted: start its readbacks and, offscreen,
/// keep at most two frames ahead of the GPU, as a frame submitted in place does.
pub(super) fn land_frame(&mut self) {
let Some(offscreen) = self.deferred.take() else {
return;
};
let submission = self.queue.landed();
if let Some(timer) = &mut self.gpu_timer {
timer.submitted(&self.queue);
timer.collect(&self.device, &mut self.gpu_times);
}
if let Some(Some(timer)) = Self::pass_timer(&mut self.pack_post, &mut self.native) {
timer.submitted(&self.queue);
}
if let Some(timer) = &mut self.own_timing {
timer.submitted(&self.queue);
}
if offscreen && let Some(submission) = submission {
self.in_flight.push_back(submission);
if !self.paced_elsewhere {
self.wait_frames();
}
}
}
/// No swapchain paces offscreen frames: keep two on the GPU at most.
pub fn wait_in_flight(&mut self) {
self.land_frame();
self.wait_frames();
}
/// The frame on the submit thread submitted: a surface reconfigure waits for the
/// device and breaks if a frame is submitted while it waits, and the compositor
/// copies views after them. (The end of a frame already lands the frames of the
/// turn before; this is the turn's own.)
pub fn wait_submissions(&mut self) {
self.queue.wait();
}
pub(super) fn wait_frames(&mut self) {
while self.in_flight.len() > 2 {
let index = self.in_flight.pop_front();
let _ = self.device.poll(wgpu::PollType::Wait {
submission_index: index,
timeout: Some(std::time::Duration::from_secs(5)),
});
}
}
/// Take a screenshot request: queue the frame's copy, or report why the
/// frame cannot be read back.
pub(super) fn take_readback(
&mut self,
request: ScreenshotRequest,
encoder: &mut wgpu::CommandEncoder,
texture: &wgpu::Texture,
) -> Option<(ScreenshotRequest, wgpu::Buffer)> {
// The copy and PNG writer both assume 8-bit pixels; a float surface would make
// the row stride too small for the copy and abort in validation.
if self.config.format.block_copy_size(None) == Some(4) {
let size = [self.config.width, self.config.height];
let format = self.config.format.remove_srgb_suffix();
// The layered float frame maps the world to SDR, then adds the HUD as drawn.
// Other 16-bit frames keep their clipped 8-bit copy.
let copy = self
.hdr
.as_mut()
.and_then(|hdr| {
hdr.sdr_screenshot(&self.device, encoder, format, request.size.is_some())
})
.or_else(|| {
(texture.format() != format && texture.format() == self.output.frame.format)
.then(|| {
self.readback
.unorm_copy(&self.device, encoder, texture, format)
})
});
let texture = copy.as_ref().unwrap_or(texture);
Some((request, copy_frame(&self.device, encoder, texture, size)))
} else {
let error = format!(
"screenshots need a 32-bit surface format, not {:?}",
self.config.format
);
if request.background {
self.saved_screenshots.push(screenshot_save::Saved {
path: request.path,
result: Err(error),
hdr: None,
});
} else {
self.screenshot_result = Some(Err(error));
}
None
}
}
}
@@ -1,252 +0,0 @@
//! The camera's view frustum, as camera-relative clip planes.
use glam::{Vec3, Vec4};
/// Camera-relative clip planes (`Frustum`).
#[derive(Clone, Copy, Debug)]
pub struct Frustum {
pub(super) planes: [Vec4; 6],
}
impl Frustum {
/// Whether the camera-relative box `min..max` is at least partly inside.
pub fn intersects(&self, min: Vec3, max: Vec3) -> bool {
!self.planes.iter().any(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, max, min);
p.truncate().dot(v) + p.w < 0.0
})
}
/// Whether a camera-relative sphere is at least partly inside. Frustum
/// planes are normalized, so each test needs only one dot product and a
/// radius comparison.
pub fn intersects_sphere(&self, center: Vec3, radius: f32) -> bool {
if !center.is_finite() || !radius.is_finite() || radius < 0.0 {
return true;
}
!self
.planes
.iter()
.any(|plane| plane.truncate().dot(center) + plane.w < -radius)
}
/// Depth clip planes alone: X/Y projection jitter cannot change this test.
/// Retaining side-of-screen geometry makes this safe before TAA selects a phase.
pub fn intersects_depth(&self, min: Vec3, max: Vec3) -> bool {
if !min.is_finite() || !max.is_finite() || !min.cmple(max).all() {
return true;
}
!self.planes[4..].iter().any(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, max, min);
p.truncate().dot(v) + p.w < 0.0
})
}
/// Whether the camera-relative box `min..max` is entirely inside. Then
/// `intersects` accepts every box within it: each plane's distance only
/// grows from this box's nearest corner to the inner box's farthest, and
/// rounding keeps that order.
pub fn contains(&self, min: Vec3, max: Vec3) -> bool {
self.planes.iter().all(|p| {
let sign = p.truncate().cmpge(Vec3::ZERO);
let v = Vec3::select(sign, min, max);
p.truncate().dot(v) + p.w >= 0.0
})
}
/// Whether the camera-relative `point` is on or inside every plane (vanilla's
/// `Frustum.pointInFrustum`). A point that is not finite is kept: a test that cannot
/// tell must not hide the particle.
pub fn contains_point(&self, point: Vec3) -> bool {
if !point.is_finite() {
return true;
}
self.planes
.iter()
.all(|plane| plane.truncate().dot(point) + plane.w >= 0.0)
}
/// The same frustum seen from a camera moved `blocks` back along the view direction
/// (vanilla's `Frustum.offset`): the sides open up near the camera and the near plane
/// moves behind it, so what sits just behind or beside the camera stays inside.
///
/// The view direction is the normal of the depth planes (the two are opposite), signed
/// towards where the side planes point. A frustum that has no direction to pull along
/// comes back unchanged: a box with no depth planes (the shadow pass's), and a box whose
/// sides are parallel to the view direction (an orthographic projection), where the side
/// normals cancel and say nothing about which way is forward.
pub fn pulled_back(&self, blocks: f32) -> Frustum {
let sides: Vec3 = self.planes[..4].iter().map(|p| p.truncate()).sum();
let depth = self.planes[4].truncate();
let along = depth.dot(sides);
// A perspective frustum's four side normals each lean forward, so this is well above 1.
if along.abs() < 1.0e-3 {
return *self;
}
let toward_sides = if along > 0.0 { depth } else { -depth };
let axis = toward_sides.normalize_or_zero();
let mut planes = self.planes;
for plane in &mut planes {
plane.w += blocks * plane.truncate().dot(axis);
}
Frustum { planes }
}
/// The frustum of a camera-relative `view_proj`, for tests outside this module.
#[cfg(test)]
pub(crate) fn from_view_projection(view_proj: glam::Mat4) -> Frustum {
Frustum {
planes: super::frustum(view_proj),
}
}
}
#[cfg(test)]
mod tests {
use super::{Frustum, Vec3};
use crate::gfx::world_projection;
use glam::Mat4;
const FOV: f32 = 70.0;
const ASPECT: f32 = 16.0 / 9.0;
const FAR: f32 = 512.0;
const EPS: f32 = 0.01;
fn looking_down_minus_z() -> Frustum {
Frustum::from_view_projection(world_projection(FOV, ASPECT, FAR))
}
fn tangents() -> (f32, f32) {
let up = (FOV / 2.0).to_radians().tan();
(up * ASPECT, up)
}
/// Each of the six planes of the unmoved frustum, a point just inside and one just outside,
/// from the field of view worked out by hand.
#[test]
fn a_point_is_inside_only_within_all_six_planes() {
let view = looking_down_minus_z();
let (tan_x, tan_y) = tangents();
let depth = 10.0;
let inside = [
Vec3::new(0.0, 0.0, -depth),
Vec3::new(depth * tan_x - EPS, 0.0, -depth),
Vec3::new(-(depth * tan_x - EPS), 0.0, -depth),
Vec3::new(0.0, depth * tan_y - EPS, -depth),
Vec3::new(0.0, -(depth * tan_y - EPS), -depth),
Vec3::new(0.0, 0.0, -0.06),
Vec3::new(0.0, 0.0, -(FAR - 0.1)),
];
let outside = [
Vec3::new(depth * tan_x + EPS, 0.0, -depth),
Vec3::new(-(depth * tan_x + EPS), 0.0, -depth),
Vec3::new(0.0, depth * tan_y + EPS, -depth),
Vec3::new(0.0, -(depth * tan_y + EPS), -depth),
Vec3::new(0.0, 0.0, -0.04),
Vec3::new(0.0, 0.0, -(FAR + 0.1)),
Vec3::new(0.0, 0.0, 1.0),
Vec3::new(0.0, 0.0, 0.0),
];
for p in inside {
assert!(view.contains_point(p), "{p} should be inside");
}
for p in outside {
assert!(!view.contains_point(p), "{p} should be outside");
}
assert!(view.contains_point(Vec3::NAN), "an unknown point is kept");
}
/// Camera 3 blocks back: its apex is at z = 3, so the sides open by 3 * tan, the near
/// plane is at z = 3 - 0.05 and the far plane at z = 3 - FAR.
#[test]
fn pulling_the_camera_back_moves_every_plane() {
let (tan_x, tan_y) = tangents();
let back = looking_down_minus_z().pulled_back(3.0);
let inside = [
Vec3::new(0.0, 0.0, 2.9),
Vec3::new(3.0 * tan_x - EPS, 0.0, 0.0),
Vec3::new(-(3.0 * tan_x - EPS), 0.0, 0.0),
Vec3::new(0.0, 3.0 * tan_y - EPS, 0.0),
Vec3::new(0.0, -(3.0 * tan_y - EPS), 0.0),
Vec3::new(0.0, 0.0, 3.0 - FAR + 0.1),
];
let outside = [
Vec3::new(0.0, 0.0, 3.0),
Vec3::new(3.0 * tan_x + EPS, 0.0, 0.0),
Vec3::new(-(3.0 * tan_x + EPS), 0.0, 0.0),
Vec3::new(0.0, 3.0 * tan_y + EPS, 0.0),
Vec3::new(0.0, -(3.0 * tan_y + EPS), 0.0),
Vec3::new(0.0, 0.0, 3.0 - FAR - 0.1),
];
for p in inside {
assert!(back.contains_point(p), "{p} should be inside");
}
for p in outside {
assert!(!back.contains_point(p), "{p} should be outside");
}
// The unmoved frustum does not have the point that only the offset one has.
assert!(!looking_down_minus_z().contains_point(Vec3::new(0.0, 0.0, 2.9)));
// An offset of nothing changes no verdict.
let same = looking_down_minus_z();
let unmoved = same.pulled_back(0.0);
for p in [
Vec3::new(1.0, 2.0, -3.0),
Vec3::new(0.0, 0.0, 1.0),
Vec3::new(40.0, 0.0, -5.0),
] {
assert_eq!(same.contains_point(p), unmoved.contains_point(p));
}
}
/// The offset follows the camera's own view direction, whatever way it looks.
#[test]
fn the_offset_is_along_the_view_direction() {
for (yaw, pitch) in [(0.3_f32, 0.0_f32), (2.0, -0.5), (-1.2, 0.9), (3.0, 1.2)] {
let pose = Mat4::from_rotation_x(pitch) * Mat4::from_rotation_y(yaw);
let view = Frustum::from_view_projection(world_projection(FOV, ASPECT, FAR) * pose);
let forward = pose.inverse().transform_vector3(-Vec3::Z);
let back = view.pulled_back(3.0);
assert!(
back.contains_point(forward * -2.9),
"{yaw} {pitch}: 2.9 behind"
);
assert!(
!back.contains_point(forward * -3.0),
"{yaw} {pitch}: 3 behind"
);
assert!(
!view.contains_point(forward * -2.9),
"{yaw} {pitch}: unmoved"
);
assert!(back.contains_point(forward * 20.0) && view.contains_point(forward * 20.0));
}
}
/// An orthographic box has no apex to pull back from: its side normals cancel, so there is
/// no direction, and the frustum must come back as it was.
#[test]
fn an_orthographic_frustum_stays_where_it_is() {
let ortho =
Frustum::from_view_projection(Mat4::orthographic_rh(-8.0, 8.0, -4.5, 4.5, 100.0, 0.05));
let moved = ortho.pulled_back(3.0);
for p in [
Vec3::new(0.0, 0.0, 2.0),
Vec3::new(0.0, 0.0, -9.0),
Vec3::new(7.9, 4.4, -9.0),
Vec3::new(8.1, 0.0, -9.0),
Vec3::new(0.0, 0.0, -101.0),
] {
assert_eq!(ortho.contains_point(p), moved.contains_point(p), "{p}");
}
}
/// The shadow pass's box has no depth planes, so no direction: it must not move.
#[test]
fn a_frustum_without_depth_planes_stays_where_it_is() {
let mut flat = looking_down_minus_z();
flat.planes[4] = glam::Vec4::W;
flat.planes[5] = glam::Vec4::W;
let moved = flat.pulled_back(3.0);
for p in [
Vec3::new(0.0, 0.0, 2.0),
Vec3::new(0.0, 0.0, -9.0),
Vec3::new(80.0, 0.0, -9.0),
] {
assert_eq!(flat.contains_point(p), moved.contains_point(p));
}
}
}
+36 -59
View File
@@ -90,8 +90,6 @@ fn nits_setting(nits: u32) -> u32 {
/// Simple-level presets. `Custom` leaves every option as the player set it.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum Preset {
/// Every saving on, over the lowest settings (`preset::table`).
FullPerformance,
Performance,
Balanced,
Quality,
@@ -100,8 +98,7 @@ pub enum Preset {
Custom,
}
impl Preset {
pub const ALL: [Preset; 6] = [
Preset::FullPerformance,
pub const ALL: [Preset; 5] = [
Preset::Performance,
Preset::Balanced,
Preset::Quality,
@@ -110,7 +107,6 @@ impl Preset {
];
pub fn name(self) -> &'static str {
match self {
Preset::FullPerformance => "full_performance",
Preset::Performance => "performance",
Preset::Balanced => "balanced",
Preset::Quality => "quality",
@@ -120,7 +116,6 @@ impl Preset {
}
pub fn label(self) -> &'static str {
match self {
Preset::FullPerformance => "Full Performance",
Preset::Performance => "Performance",
Preset::Balanced => "Balanced",
Preset::Quality => "Quality",
@@ -591,45 +586,6 @@ pub fn translucent_batching_offered() -> bool {
TRANSLUCENT_BATCHING_OFFERED.load(std::sync::atomic::Ordering::Relaxed)
}
/// Parallel Tick's setting, for the worlds this game runs itself (single player, open to LAN):
/// whether the server tick's phases that give the same result in any order share their work
/// among helper threads (`parallel`). Auto shares it only while the tick is heavy and sharing
/// makes it faster; a quiet world stays on one thread and starts no helper.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum ParallelTickMode {
#[default]
Off = 0,
Auto = 1,
On = 2,
}
impl ParallelTickMode {
pub const ALL: [ParallelTickMode; 3] = [
ParallelTickMode::Off,
ParallelTickMode::Auto,
ParallelTickMode::On,
];
pub fn name(self) -> &'static str {
match self {
Self::Off => "off",
Self::Auto => "auto",
Self::On => "on",
}
}
pub fn label(self) -> &'static str {
match self {
Self::Off => "Off",
Self::Auto => "Auto",
Self::On => "On",
}
}
fn parse(s: &str) -> Self {
Self::ALL
.into_iter()
.find(|m| m.name() == s)
.unwrap_or_default()
}
}
/// GPU Culling's setting: off, on where it is offered, or Auto, which has it on only where the
/// CPU limits the frame and it makes the frame faster (`autotune::GpuCullingAuto`).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
@@ -817,9 +773,9 @@ pub struct Graphics {
pub cave_culling: bool,
/// Near solid terrain culled, and its draws listed, on the GPU (`gfx::gpu_culling`), where it
/// is offered (`gpu_culling_offer`). Off by default (GPU Culling, Performance graphics); it
/// applies at once, and every preset sets it to Auto. Every save writes it, so a default
/// turned on later needs a new key, as `batchTranslucent` did. Auto turns it on only where
/// the CPU limits the frame and it makes the frame faster (`autotune`).
/// applies at once, and no preset sets it. Every save writes it, so a default turned on later
/// needs a new key, as `batchTranslucent` did. Auto turns it on only where the CPU limits the
/// frame and it makes the frame faster (`autotune`).
pub gpu_culling: GpuCullingMode,
/// Skip drawing entities hidden behind opaque terrain, synchronously or asynchronously.
pub entity_culling: EntityCullingMode,
@@ -865,9 +821,6 @@ pub struct Graphics {
pub pacing: Pacing,
/// Chunk worker threads; 0 uses every core but one. Applies at the next start.
pub workers: u32,
/// Parallel Tick (Performance graphics, beside Worker Threads): applies from the next tick,
/// and no preset sets it.
pub parallel_tick: ParallelTickMode,
pub overlay: Overlay,
/// World resolution as a percentage of the window's (50..=200).
pub resolution_scale: u32,
@@ -970,7 +923,6 @@ impl Default for Graphics {
present_mode: PresentMode::Auto,
pacing: Pacing::Efficient,
workers: 0,
parallel_tick: ParallelTickMode::Off,
overlay: Overlay::Off,
resolution_scale: 100,
dynamic_resolution: false,
@@ -1093,7 +1045,6 @@ impl Graphics {
"particleCulling" => g.particle_culling = ParticleCullingMode::parse(value),
"leafCulling" => g.leaf_culling = LeafCullingMode::parse(value),
"opaqueIce" => g.opaque_ice = flag(g.opaque_ice),
"parallelTick" => g.parallel_tick = ParallelTickMode::parse(value),
"blockEntityCache" => {
let enabled = flag(false);
g.cache_shulker_boxes = enabled;
@@ -1193,7 +1144,7 @@ impl Graphics {
}
pub fn serialize(&self) -> String {
let mut text = format!(
"preset:{}\nlodDistance:{}\nfarDetail:{}\ncaveCulling:{}\nentityCulling:{}\nentityCullingPrecheck:{}\nparticleCulling:{}\nleafCulling:{}\nopaqueIce:{}\nblockEntityCacheShulkerBoxes:{}\nblockEntityCacheSigns:{}\nblockEntityCacheDecoratedPots:{}\nblockEntityCacheBells:{}\nblockEntityCacheChests:{}\nblockEntityCacheBanners:{}\nblockEntityCacheCopperGolemStatues:{}\nchunkUpdates:{}\nuploadBudgetKiB:{}\ntextureBudgetMiB:{}\nsky:{}\nfog:{}\nweather:{}\nanimatedTextures:{}\nditherCutoutMips:{}\npresentMode:{}\nframePacing:{}\nworkers:{}\noverlay:{}\nresolutionScale:{}\ndynamicResolution:{}\ntargetFps:{}\nfxaa:{}\ntaa:{}\nupscaling:{}\nupscalingSharpness:{}\nscreenshotQuality:{}\nframeGeneration:{}\nhdr:{}\nhdrPaperWhite:{}\nhdrPeak:{}\nhdrBlackLevel:{}\nhdrUiNits:{}\nhdrLighting:{}\nbatteryMode:{}\nshadowCache:{}\ngraphicsApi:{}\npickedShaderPack:{}\nbatchTranslucent:{}\nhdrSmoothGradients:{}\ngpuCulling:{}\nparallelTick:{}\n",
"preset:{}\nlodDistance:{}\nfarDetail:{}\ncaveCulling:{}\nentityCulling:{}\nentityCullingPrecheck:{}\nparticleCulling:{}\nleafCulling:{}\nopaqueIce:{}\nblockEntityCacheShulkerBoxes:{}\nblockEntityCacheSigns:{}\nblockEntityCacheDecoratedPots:{}\nblockEntityCacheBells:{}\nblockEntityCacheChests:{}\nblockEntityCacheBanners:{}\nblockEntityCacheCopperGolemStatues:{}\nchunkUpdates:{}\nuploadBudgetKiB:{}\ntextureBudgetMiB:{}\nsky:{}\nfog:{}\nweather:{}\nanimatedTextures:{}\nditherCutoutMips:{}\npresentMode:{}\nframePacing:{}\nworkers:{}\noverlay:{}\nresolutionScale:{}\ndynamicResolution:{}\ntargetFps:{}\nfxaa:{}\ntaa:{}\nupscaling:{}\nupscalingSharpness:{}\nscreenshotQuality:{}\nframeGeneration:{}\nhdr:{}\nhdrPaperWhite:{}\nhdrPeak:{}\nhdrBlackLevel:{}\nhdrUiNits:{}\nhdrLighting:{}\nbatteryMode:{}\nshadowCache:{}\ngraphicsApi:{}\npickedShaderPack:{}\nbatchTranslucent:{}\nhdrSmoothGradients:{}\ngpuCulling:{}\n",
self.preset.name(),
self.lod_distance,
self.far_detail.name(),
@@ -1251,7 +1202,6 @@ impl Graphics {
bool_text(self.translucent_batching),
bool_text(self.hdr_smooth_gradients),
self.gpu_culling.key(),
self.parallel_tick.name(),
);
if let Some(driver) = &self.hdr_failed_start {
text += &format!("hdrFailedStart:{driver}\n");
@@ -1330,9 +1280,37 @@ impl Graphics {
}
}
#[path = "graphics_preset.rs"]
mod preset;
pub use preset::apply_preset;
/// A preset's values for vanilla's options and Horizon's own.
pub fn apply_preset(preset: Preset, s: &mut crate::settings::Settings) {
let (rd, sim, clouds, particles, shadows, blend, mipmaps, entity, leaves, weather_r) =
match preset {
Preset::Performance => (8, 6, "false", 2, false, 0, 0, 0.5, false, 3),
Preset::Balanced => (12, 8, "fast", 1, true, 1, 2, 0.75, true, 5),
Preset::Quality => (16, 12, "true", 0, true, 2, 4, 1.0, true, 10),
Preset::Ultra => (24, 12, "true", 0, true, 3, 4, 1.5, true, 10),
Preset::Custom => return,
};
s.render_distance = rd;
s.simulation_distance = sim;
s.clouds = clouds.into();
s.particles = particles;
s.entity_shadows = shadows;
s.biome_blend = blend;
s.mipmap_levels = mipmaps;
s.entity_distance = entity;
s.cutout_leaves = leaves;
s.weather_radius = weather_r;
s.graphics_preset = "custom".into();
let g = &mut s.horizon;
g.preset = preset;
g.cave_culling = true;
g.animated_textures = true;
g.chunk_updates = 0;
g.upload_budget_kib = 0;
g.sky = true;
g.fog = true;
g.weather = true;
}
#[cfg(test)]
mod tests {
@@ -1568,7 +1546,6 @@ mod tests {
present_mode: PresentMode::Mailbox,
pacing: Pacing::Precise,
workers: 6,
parallel_tick: ParallelTickMode::Auto,
overlay: Overlay::Graph,
resolution_scale: 75,
dynamic_resolution: false,
@@ -1,169 +0,0 @@
//! The graphics presets: each one a fixed table of the options it sets, vanilla's and
//! Horizon's own, so that picking one gives the same settings whatever was set before.
//! Every preset turns on the optimizations that leave the picture as it is; Full
//! Performance adds the ones that change it. What no table names keeps the player's
//! choice: the display preferences (`graphics_ui`'s `touched`), Far Detail and Leaf
//! Culling, which follow the machine and the look the player picked, and Translucent
//! Batching, on unless the player turned it off.
use super::{EntityCullingMode, GpuCullingMode, ParticleCullingMode, Preset, Upscaling};
use crate::settings::Settings;
/// What differs between the presets. Every one of them also turns on entity and particle
/// culling on a worker, the block-entity caches and GPU Culling's Auto (which tries it only
/// where it makes frames faster), keeps cave culling, the sky, the fog, the weather and the
/// animated textures on, uploads meshes unthrottled and draws at a fixed resolution without
/// TAA.
struct Table {
render_distance: i32,
simulation_distance: i32,
/// `options.txt`'s `renderClouds`: `false`, `fast` or `true`.
clouds: &'static str,
/// 0 all, 1 decreased, 2 minimal.
particles: u8,
entity_shadows: bool,
biome_blend: i32,
mipmap_levels: i32,
entity_distance: f32,
cutout_leaves: bool,
weather_radius: i32,
/// Far terrain's range in chunks; 0 is off.
lod_distance: u32,
opaque_ice: bool,
resolution_scale: u32,
fxaa: bool,
dither_cutout_mips: bool,
}
fn table(preset: Preset) -> Option<Table> {
Some(match preset {
Preset::FullPerformance => Table {
render_distance: 6,
simulation_distance: 5,
clouds: "false",
particles: 2,
entity_shadows: false,
biome_blend: 0,
mipmap_levels: 0,
entity_distance: 0.5,
cutout_leaves: false,
weather_radius: 3,
lod_distance: 0,
opaque_ice: true,
resolution_scale: 75,
fxaa: false,
dither_cutout_mips: false,
},
Preset::Performance => Table {
render_distance: 8,
simulation_distance: 6,
clouds: "false",
particles: 2,
entity_shadows: false,
biome_blend: 0,
mipmap_levels: 0,
entity_distance: 0.5,
cutout_leaves: false,
weather_radius: 3,
lod_distance: 0,
opaque_ice: false,
resolution_scale: 100,
fxaa: false,
dither_cutout_mips: false,
},
Preset::Balanced => Table {
render_distance: 12,
simulation_distance: 8,
clouds: "fast",
particles: 1,
entity_shadows: true,
biome_blend: 1,
mipmap_levels: 2,
entity_distance: 0.75,
cutout_leaves: true,
weather_radius: 5,
lod_distance: 0,
opaque_ice: false,
resolution_scale: 100,
fxaa: false,
dither_cutout_mips: false,
},
Preset::Quality => Table {
render_distance: 16,
simulation_distance: 12,
clouds: "true",
particles: 0,
entity_shadows: true,
biome_blend: 2,
mipmap_levels: 4,
entity_distance: 1.0,
cutout_leaves: true,
weather_radius: 10,
lod_distance: 64,
opaque_ice: false,
resolution_scale: 100,
fxaa: true,
dither_cutout_mips: false,
},
Preset::Ultra => Table {
render_distance: 24,
simulation_distance: 12,
clouds: "true",
particles: 0,
entity_shadows: true,
biome_blend: 3,
mipmap_levels: 4,
entity_distance: 1.5,
cutout_leaves: true,
weather_radius: 10,
lod_distance: 128,
opaque_ice: false,
resolution_scale: 100,
fxaa: true,
dither_cutout_mips: true,
},
Preset::Custom => return None,
})
}
/// Sets what `preset`'s table names, in vanilla's options and Horizon's own.
pub fn apply_preset(preset: Preset, s: &mut Settings) {
let Some(t) = table(preset) else { return };
s.render_distance = t.render_distance;
s.simulation_distance = t.simulation_distance;
s.clouds = t.clouds.into();
s.particles = t.particles;
s.entity_shadows = t.entity_shadows;
s.biome_blend = t.biome_blend;
s.mipmap_levels = t.mipmap_levels;
s.entity_distance = t.entity_distance;
s.cutout_leaves = t.cutout_leaves;
s.weather_radius = t.weather_radius;
s.graphics_preset = "custom".into();
let g = &mut s.horizon;
g.preset = preset;
g.lod_distance = t.lod_distance;
g.cave_culling = true;
g.gpu_culling = GpuCullingMode::Auto;
g.entity_culling = EntityCullingMode::Asynchronous;
g.particle_culling = ParticleCullingMode::Asynchronous;
g.opaque_ice = t.opaque_ice;
g.cache_shulker_boxes = true;
g.cache_signs = true;
g.cache_decorated_pots = true;
g.cache_bells = true;
g.cache_chests = true;
g.cache_banners = true;
g.cache_copper_golem_statues = true;
g.chunk_updates = 0;
g.upload_budget_kib = 0;
g.sky = true;
g.fog = true;
g.weather = true;
g.animated_textures = true;
g.dither_cutout_mips = t.dither_cutout_mips;
g.resolution_scale = t.resolution_scale;
g.dynamic_resolution = false;
g.fxaa = t.fxaa;
g.taa = false;
g.upscaling = Upscaling::Native;
}
+30 -45
View File
@@ -8,8 +8,8 @@ use crate::{
gfx::EffectiveOutput,
graphics::{
EntityCullingMode, FarDetail, FrameGeneration, GpuCullingMode, GraphicsApi, HdrMode,
HdrSetup as Setup, LeafCullingMode, Overlay, Pacing, ParallelTickMode, ParticleCullingMode,
PresentMode, Preset, Upscaling,
HdrSetup as Setup, LeafCullingMode, Overlay, Pacing, ParticleCullingMode, PresentMode,
Preset, Upscaling,
},
graphics_style::Cost,
lang,
@@ -98,7 +98,6 @@ pub enum H {
PresentMode,
Pacing,
Workers,
ParallelTick,
Overlay,
ResolutionScale,
DynamicResolution,
@@ -434,11 +433,6 @@ pub fn rows() -> Vec<(Page, Vec<(&'static str, Vec<Setting>)>)> {
None,
"Threads that generate, light and mesh chunks. Next start.",
),
h(
H::ParallelTick,
Saves,
"Shares your world's tick among threads. Auto: only while that is faster.",
),
],
),
(
@@ -859,7 +853,7 @@ impl H {
fn label(self, s: &Settings, out: &EffectiveOutput) -> Text {
let g = &s.horizon;
match self {
H::Preset => labelled("Horizon Preset", g.preset.label()),
H::Preset => labelled("Preset", g.preset.label()),
H::LodDistance => match g.lod_distance {
0 => labelled("LOD Distance", "Off"),
n => labelled("LOD Distance", lang::tr("%s chunks", &[&n])),
@@ -893,7 +887,6 @@ impl H {
H::ParticleCulling => labelled("Particle Culling", g.particle_culling.label()),
H::LeafCulling => labelled("Leaf Culling", g.leaf_culling.label()),
H::OpaqueIce => labelled("Opaque Ice", on_off(g.opaque_ice)),
H::ParallelTick => labelled("Parallel Tick", g.parallel_tick.label()),
H::CacheShulkerBoxes => labelled("Shulker Boxes", on_off(g.cache_shulker_boxes)),
H::CacheSigns => labelled("Signs", on_off(g.cache_signs)),
H::CacheDecoratedPots => labelled("Decorated Pots", on_off(g.cache_decorated_pots)),
@@ -1048,9 +1041,6 @@ impl H {
g.leaf_culling = step(&LeafCullingMode::ALL, g.leaf_culling, back);
}
H::OpaqueIce => g.opaque_ice = !g.opaque_ice,
H::ParallelTick => {
g.parallel_tick = step(&ParallelTickMode::ALL, g.parallel_tick, back)
}
H::CacheShulkerBoxes => g.cache_shulker_boxes = !g.cache_shulker_boxes,
H::CacheSigns => g.cache_signs = !g.cache_signs,
H::CacheDecoratedPots => g.cache_decorated_pots = !g.cache_decorated_pots,
@@ -1300,13 +1290,13 @@ impl Item {
| H::Pacing
| H::PresentMode
| H::Workers
| H::ParallelTick
| H::FrameGeneration
| H::BatteryMode
| H::ShadowCache
| H::GraphicsApi
| H::TranslucentBatching
| H::HdrSmoothGradients
| H::GpuCulling
)
| Item::Vanilla(
Opt::GuiScale
@@ -1763,14 +1753,6 @@ mod tests {
ui.set_search("tearing");
let found = ui.listed(&s, SIZE);
assert!(found.iter().any(|(_, i)| *i == Item::Vanilla(Opt::Vsync)));
// Both presets answer "preset"; Horizon's own, named apart from vanilla's, answers its name.
ui.set_search("preset");
let found = ui.listed(&s, SIZE);
let general = |item| (Page::General, item);
assert!(found.contains(&general(Item::Horizon(H::Preset))));
assert!(found.contains(&general(Item::Vanilla(Opt::Preset))));
ui.set_search("horizon preset");
assert_eq!(ui.listed(&s, SIZE), [general(Item::Horizon(H::Preset))]);
ui.set_search("hdr");
let [x, y, w, h] = cols.page(Page::ALL.len() - 1);
press(&mut ui, &mut s, (x + w / 2.0, y + h / 2.0));
@@ -2243,18 +2225,9 @@ mod tests {
fn presets_set_vanilla_and_horizon_options() {
let mut s = Settings::default();
Item::Horizon(H::Preset).cycle(&mut s, false, [854, 480], &NONE);
assert_eq!(s.horizon.preset, Preset::FullPerformance);
assert_eq!(s.render_distance, 6);
assert_eq!(s.clouds, "false");
assert_eq!(s.horizon.resolution_scale, 75);
assert_eq!(s.horizon.entity_culling, EntityCullingMode::Asynchronous);
assert!(s.horizon.opaque_ice && s.horizon.cache_chests);
// The next one puts back what only Full Performance lowers.
Item::Horizon(H::Preset).cycle(&mut s, false, [854, 480], &NONE);
assert_eq!(s.horizon.preset, Preset::Performance);
assert_eq!(s.render_distance, 8);
assert_eq!(s.horizon.resolution_scale, 100);
assert!(!s.horizon.opaque_ice && s.horizon.cache_chests);
assert_eq!(s.clouds, "false");
// Any quality change leaves the preset.
Item::Vanilla(Opt::Clouds).cycle(&mut s, false, [854, 480], &NONE);
assert_eq!(s.horizon.preset, Preset::Custom);
@@ -2262,14 +2235,6 @@ mod tests {
Item::Horizon(H::Preset).cycle(&mut s, true, [854, 480], &NONE);
Item::Vanilla(Opt::Vsync).cycle(&mut s, false, [854, 480], &NONE);
assert_eq!(s.horizon.preset, Preset::Ultra);
// Ultra keeps the optimizations that leave the picture as it is, and no others.
assert_eq!(s.horizon.entity_culling, EntityCullingMode::Asynchronous);
assert_eq!(s.horizon.gpu_culling, GpuCullingMode::Auto);
assert_eq!((s.horizon.lod_distance, s.horizon.fxaa), (128, true));
assert_eq!(
(s.horizon.resolution_scale, s.horizon.opaque_ice),
(100, false)
);
}
#[test]
@@ -2284,7 +2249,7 @@ mod tests {
assert_eq!(seen, [2, 4, 8, 1]);
Item::Horizon(H::ScreenshotQuality).cycle(&mut s, true, [854, 480], &NONE);
assert_eq!(s.horizon.screenshot_quality, 8);
assert_eq!(s.horizon.preset, Preset::FullPerformance);
assert_eq!(s.horizon.preset, Preset::Performance);
}
#[test]
@@ -2332,6 +2297,14 @@ mod tests {
let item = Item::Horizon(H::EntityCulling);
assert_eq!(s.horizon.entity_culling, EntityCullingMode::Off);
assert_eq!(item.label(&s, &NONE).plain(), "Entity Culling: Off");
for mode in EntityCullingMode::ALL {
s.horizon.entity_culling = mode;
for preset in Preset::ALL {
crate::graphics::apply_preset(preset, &mut s);
assert_eq!(s.horizon.entity_culling, mode);
}
}
s.horizon.entity_culling = EntityCullingMode::Off;
let mut ui = ui();
let r = row(&mut ui, &s, item);
for mode in [
@@ -2360,6 +2333,10 @@ mod tests {
assert_eq!(item.label(&s, &NONE).plain(), "Particle Culling: Off");
for mode in ParticleCullingMode::ALL {
s.horizon.particle_culling = mode;
for preset in Preset::ALL {
crate::graphics::apply_preset(preset, &mut s);
assert_eq!(s.horizon.particle_culling, mode);
}
assert_eq!(
crate::graphics::Graphics::parse(&s.horizon.serialize()).particle_culling,
mode
@@ -2553,8 +2530,8 @@ mod tests {
}
}
/// GPU Culling: Off, On or Auto right after Cave Culling, off by default, and greyed out
/// with its reason, reading Off, wherever it isn't offered.
/// GPU Culling: Off, On or Auto right after Cave Culling, off by default, no part of a
/// preset, and greyed out with its reason, reading Off, wherever it isn't offered.
#[test]
fn gpu_culling_steps_off_on_auto_where_it_is_offered() {
use crate::graphics::GpuCullingOffer;
@@ -2593,7 +2570,7 @@ mod tests {
assert!(key(&mut ui, &mut s, K::Enter).is_empty());
assert_eq!(s.horizon.gpu_culling, GpuCullingMode::On, "{offer:?}");
}
// Where it is, it steps through its three values and leaves the preset.
// Where it is, it steps through its three values and keeps the preset.
crate::graphics::offer_gpu_culling(GpuCullingOffer::Offered);
assert_eq!(item.blocked(&s, &NONE), None);
for label in ["Auto", "Off", "On"] {
@@ -2609,10 +2586,18 @@ mod tests {
}
item.cycle(&mut s, true, FB, &NONE);
assert_eq!(s.horizon.gpu_culling, GpuCullingMode::Off);
assert_eq!(s.horizon.preset, Preset::Custom);
assert_eq!(s.horizon.preset, Preset::Balanced);
// Auto says what it does.
s.horizon.gpu_culling = GpuCullingMode::Auto;
assert!(description(item, &s, &NONE, "").starts_with("Auto: "));
// No preset sets it.
for mode in GpuCullingMode::ALL {
s.horizon.gpu_culling = mode;
for preset in Preset::ALL {
crate::graphics::apply_preset(preset, &mut s);
assert_eq!(s.horizon.gpu_culling, mode, "{preset:?}");
}
}
}
#[test]
+5 -31
View File
@@ -16,7 +16,6 @@ use model_reducing::reducible_model_sprites;
mod animate;
pub mod cit_glint;
mod gui_sprite;
mod model_reducing;
mod pack_text;
pub mod pictures;
@@ -56,7 +55,7 @@ pub struct TextureFlags {
impl TextureFlags {
/// The `texture` section of a `.png.mcmeta` file, if it sets either flag.
pub fn from_mcmeta(json: &str) -> Option<Self> {
let meta: serde_json::Value = crate::packs::first_json(json.as_bytes()).ok()?;
let meta = crate::packs::first_json(json.as_bytes())?;
let section = meta.get("texture")?;
let flag = |key| section.get(key).and_then(serde_json::Value::as_bool) == Some(true);
let flags = Self {
@@ -389,7 +388,7 @@ fn strip_frame(pixels: &[u8], stride: u32, x: u32, y: u32, w: u32, h: u32) -> Ve
}
/// The `animation` section of a texture's `.mcmeta`.
fn animation_of(mcmeta: Option<&str>) -> Option<AnimationMetadata> {
let meta: serde_json::Value = crate::packs::first_json(mcmeta?.as_bytes()).ok()?;
let meta = crate::packs::first_json(mcmeta?.as_bytes())?;
AnimationMetadata::from_json(&meta.get("animation")?.to_string()).ok()
}
/// An animated strip's first frame: the region the mcmeta's frame size picks
@@ -2467,8 +2466,9 @@ impl HudBatch {
);
}
}
InlineObject::Atlas { .. } => {
if let Some(rect) = atlas.inline_object_sprite(object) {
InlineObject::Atlas { sprite, .. } => {
let key = sprite.strip_prefix("minecraft:").unwrap_or(sprite);
if let Some(rect) = atlas.sprites.get(key).copied() {
self.rect_uv(x, y, 8.0, 8.0, rect, tint);
}
}
@@ -3773,32 +3773,6 @@ mod tests {
assert_eq!(banner.texels((atlas.width, atlas.height)), (16, 32));
}
#[test]
fn an_inline_atlas_sprite_resolves_in_its_named_atlas() {
let root =
std::env::temp_dir().join(format!("horizon-atlas-inline-{}", std::process::id()));
let gui = root.join("assets/minecraft/textures/gui/sprites/boss_bar");
fs::create_dir_all(&gui).unwrap();
write_strip(
&gui.join("pink_background.png"),
16,
16,
&[[1, 2, 3, 255]],
None,
);
let atlas = HudAtlas::build(&root).unwrap();
let _ = fs::remove_dir_all(&root);
let packed = atlas.sprites["gui/sprites/boss_bar/pink_background"];
let missing = atlas.sprites[MISSING_SPRITE];
let found = atlas
.inline_sprite("minecraft:gui", "minecraft:boss_bar/pink_background")
.unwrap();
assert_eq!((found.u0, found.v0), (packed.u0, packed.v0));
let none = atlas
.inline_sprite("minecraft:gui", "minecraft:boss_bar/nope")
.unwrap();
assert_eq!((none.u0, none.v0), (missing.u0, missing.v0));
}
#[test]
fn a_root_single_sprite_strip_taller_than_the_atlas_packs_one_frame() {
let root = animated_root();
let atlases = root.join("assets/minecraft/atlases");
@@ -1,41 +0,0 @@
use super::{HudAtlas, MISSING_SPRITE, Rect};
/// The packed key of a GUI sprite id: `minecraft:boss_bar/pink_background` is
/// `gui/sprites/boss_bar/pink_background`, another namespace's `ns:gui/sprites/...`.
fn atlas_key_of_gui_sprite(id: &str) -> String {
match id.split_once(':') {
Some(("minecraft", path)) => format!("gui/sprites/{path}"),
Some((namespace, path)) => format!("{namespace}:gui/sprites/{path}"),
None => format!("gui/sprites/{id}"),
}
}
impl HudAtlas {
/// `AtlasGlyphProvider`: the sprite `sprite` of the atlas named `atlas`
/// (`minecraft:gui` keeps its sprites under `gui/sprites/`), or the missing
/// sprite when that atlas has none by that name.
pub fn inline_sprite(&self, atlas: &str, sprite: &str) -> Option<Rect> {
let plain = sprite.strip_prefix("minecraft:").unwrap_or(sprite);
let gui = atlas_key_of_gui_sprite(sprite);
let gui_atlas = atlas.strip_prefix("minecraft:").unwrap_or(atlas) == "gui";
let (first, second) = if gui_atlas {
(gui.as_str(), plain)
} else {
(plain, gui.as_str())
};
self.sprites
.get(first)
.or_else(|| self.sprites.get(second))
.or_else(|| self.sprites.get(MISSING_SPRITE))
.copied()
}
/// `inline_sprite` for an inline atlas object; `None` for any other object.
pub(super) fn inline_object_sprite(&self, object: &crate::text::InlineObject) -> Option<Rect> {
match object {
crate::text::InlineObject::Atlas { atlas, sprite, .. } => {
self.inline_sprite(atlas, sprite)
}
_ => None,
}
}
}
@@ -39,13 +39,14 @@ pub fn text_with_backdrop(
background: u32,
) {
if background != 0 {
// GuiGraphicsExtractor.textWithBackdrop adds two pixels around the
// text's advance and the font's nine-pixel line height.
// Font.PreparedTextBuilder.markBackground: one pixel above and left of
// the glyphs, the glyph advance to the right and nine high: not a
// fixed two-pixel frame.
out.push(fill(
x - 2,
y - 2,
x + w + 2,
y + 11,
x - 1,
y - 1,
x + w,
y + 9,
multiply(background, color),
));
}
@@ -1490,10 +1491,10 @@ mod boss_bar_room_tests {
mod backdrop_tests {
use super::*;
/// `GuiGraphicsExtractor.textWithBackdrop`: two pixels around the advance
/// and the nine-pixel font line, independently of glyph-background drawing.
/// `markBackground`: the backdrop reaches one pixel above and left of the
/// glyphs, their advance to the right and nine down, not 2 on every side.
#[test]
fn the_backdrop_frames_the_text_by_two_pixels() {
fn the_backdrop_frames_the_glyphs_by_one_pixel() {
let mut out = Vec::new();
text_with_backdrop(
&mut out,
@@ -1507,6 +1508,6 @@ mod backdrop_tests {
let Some(GuiDraw::Fill { x0, y0, x1, y1, .. }) = out.first() else {
panic!("a backdrop is a fill first");
};
assert_eq!((*x0, *y0, *x1, *y1), (8, 18, 18, 31));
assert_eq!((*x0, *y0, *x1, *y1), (9, 19, 16, 29));
}
}
+7 -31
View File
@@ -9,7 +9,6 @@ use crate::{
};
pub mod bake;
pub mod cache;
mod detail;
mod kept;
mod mesh;
pub mod packed;
@@ -2388,6 +2387,13 @@ impl Lod {
self.shared.mesh_wake.notify_all();
}
}
/// Reduced far detail (`graphics::FarDetail::Reduced`): the next update
/// replans when it changes, and tiles sampled from then on approximate
/// wide cells (`GeneratorWorker::lod_grid`).
pub fn set_reduced_detail(&mut self, reduced: bool) {
self.reduced_detail = reduced;
self.shared.approximate.store(reduced, Ordering::Relaxed);
}
fn held(&self) -> bool {
self.small && self.near_loading
}
@@ -6109,34 +6115,4 @@ mod tests {
assert!(lod.stale.contains(&key));
assert_eq!(queued(&mut lod), [key]);
}
#[test]
fn changing_far_detail_samples_tiles_again() {
for level in [0, 1, 2, 3, 5] {
let mut lod = Lod::scheduler_for_test();
let key = TileKey { x: 0, z: 0, level };
lod.plan.nodes.insert(key);
lod.active.insert(key);
lod.ready.insert(key, Arc::new(samples(70)));
assert!(
queued(&mut lod).is_empty(),
"level {level}: sampled tile is not asked again"
);
lod.set_reduced_detail(true);
assert!(
lod.ready.contains_key(&key),
"level {level}: old samples stay"
);
assert_eq!(queued(&mut lod), [key], "level {level}: not sampled again");
lod.finish_sample(key, samples(70));
lod.set_reduced_detail(true);
assert!(queued(&mut lod).is_empty(), "level {level}: same value");
lod.set_reduced_detail(false);
assert_eq!(
queued(&mut lod),
[key],
"level {level}: not sampled again on the way back"
);
}
}
}
@@ -1,23 +0,0 @@
//! Reduced far detail.
use super::*;
impl Lod {
/// Reduced far detail (`graphics::FarDetail::Reduced`): the next update
/// replans when it changes, and tiles sampled from then on approximate
/// wide cells (`GeneratorWorker::lod_grid`).
pub fn set_reduced_detail(&mut self, reduced: bool) {
if self.reduced_detail != reduced {
let keys: Vec<_> = self
.ready
.keys()
.chain(self.pending.iter())
.copied()
.collect();
for key in keys {
self.mark_stale(key);
}
}
self.reduced_detail = reduced;
self.shared.approximate.store(reduced, Ordering::Relaxed);
}
}
+46 -34
View File
@@ -1594,9 +1594,9 @@ pub struct OptionsUi {
radial_pick: shell::Shell<crate::radial_editor::PickScreen>,
/// Shaders: the shader packs and the picked one's options, on the settings shell.
shader: shell::Shell<crate::shader_ui::ShaderScreen>,
/// Pack Options, on the settings shell, and the packs' Polytone config entries by pack id
/// (the game fills them beside `pack_infos`).
pack_options: shell::Shell<crate::pack_options_ui::PackOptionsScreen>,
/// The Pack Options page, and the packs' Polytone config entries by pack id (the game
/// fills them beside `pack_infos`).
pub pack_options: crate::pack_options_ui::PackOptionsUi,
pub pack_configs: std::collections::BTreeMap<String, horizon_polytone::pack::Configs>,
pub split_profiles: crate::split_profiles::SplitProfiles,
/// HDR calibration while its page is open.
@@ -3401,6 +3401,10 @@ impl OptionsUi {
c.draw(batch, atlas, cursor);
return;
}
if self.page() == Page::PackOptions {
self.pack_options.draw(batch, atlas, cursor, self.in_world);
return;
}
let waiting = self.waiting();
let in_world = self.in_world;
if self.draw_radial_name(batch, atlas, cursor, in_world) {
@@ -3782,6 +3786,20 @@ impl OptionsUi {
});
return self.shell_events(s, outputs);
}
if self.page() == Page::PackOptions {
let mut events = Vec::new();
for action in self
.pack_options
.click((x, y), size, drag, right || self.shift)
{
match action {
crate::pack_options_ui::Action::ButtonClick => events.push(Event::ButtonClick),
crate::pack_options_ui::Action::SliderDrag => {}
crate::pack_options_ui::Action::Done => events.extend(self.back(s)),
}
}
return events;
}
if self.page() == Page::Packs {
let mut events = Vec::new();
if drag {
@@ -3811,7 +3829,14 @@ impl OptionsUi {
crate::pack_screen::Action::BrowsePick(i) => {
events.push(Event::DownloadPack(i));
}
crate::pack_screen::Action::Options(id) => self.open_pack_options(&id),
crate::pack_screen::Action::Options(id) => {
let mut configs = horizon_polytone::pack::Configs::default();
if let Some(own) = self.pack_configs.get(&id) {
configs.merge(own);
}
self.pack_options = crate::pack_options_ui::PackOptionsUi::open(configs);
self.push(Page::PackOptions);
}
crate::pack_screen::Action::None => {}
}
return events;
@@ -4049,6 +4074,7 @@ impl OptionsUi {
// release, even if the pointer has left the widget or its value stayed.
let slider = self.dragging.take().is_some();
let shell_slider = self.shell_mut().and_then(|shell| shell.release());
self.pack_options.release();
let calibration_slider = self.calibration.as_mut().is_some_and(|c| c.release());
let split_drop = self.split_setup.release();
if slider || shell_slider.is_some() || calibration_slider {
@@ -4142,6 +4168,10 @@ impl OptionsUi {
self.studio.wheel(amount);
return Vec::new();
}
if self.page() == Page::PackOptions {
self.pack_options.scroll(size, amount);
return Vec::new();
}
let plain = self.resource_error.is_none()
&& !(self.pack_screen.is_some() && self.stack.last() == Some(&Page::Packs));
if !plain {
@@ -4225,6 +4255,10 @@ impl OptionsUi {
self.studio.wheel(amount);
return;
}
if self.page() == Page::PackOptions {
self.pack_options.scroll(size, amount);
return;
}
match &mut self.pack_screen {
Some(p) if self.stack.last() == Some(&Page::Packs) => {
p.scroll(cursor.0 as f64, cursor.1 as f64, amount as f64)
@@ -4359,8 +4393,14 @@ impl OptionsUi {
self.can_change_value = false;
match page {
Page::PackOptions => {
let screen = std::mem::take(&mut self.pack_options.screen);
events.extend(screen.finished());
let ui = std::mem::take(&mut self.pack_options);
if ui.changed {
let entries = ui.configs.entries().keys().cloned().collect();
events.push(Event::PackOptions {
entries,
chosen: ui.configs.chosen(),
});
}
}
Page::ShaderOptions | Page::ShaderPacks => {
if s.shader_options.as_ref().is_some_and(|o| o.changed) {
@@ -4920,34 +4960,6 @@ mod tests {
/// A renderer whose destination offers nothing and whose display reports nothing.
const NONE: EffectiveOutput = EffectiveOutput::NONE;
#[test]
fn pack_options_leave_with_a_change_and_with_nothing_after_its_undo() {
use crate::settings_shell::Screen as _;
let mut s = Settings::default();
let atlas = HudAtlas::build(std::path::Path::new("/nonexistent/horizon-test-assets"));
let atlas = atlas.unwrap();
let mut ui = OptionsUi::default();
let mut configs = horizon_polytone::pack::Configs::default();
let birds = serde_json::json!({"default_value": true});
configs.add_entry("p:birds".into(), &birds);
ui.pack_configs.insert("pack".into(), configs);
for undone in [false, true] {
ui.open_pack_options("pack");
assert!(ui.shell().is_some(), "Pack Options is on the shell");
let birds = crate::pack_options_ui::Item::Entry(0);
ui.pack_options.screen.press(&mut s, birds, false);
if undone {
let before = s.clone();
ui.pack_options.screen.undo(&mut s, &before);
}
let events = ui.key(&mut s, &atlas, winit::keyboard::KeyCode::Escape, None);
let sent = events
.iter()
.any(|e| matches!(e, Event::PackOptions { .. }));
assert_eq!(sent, !undone, "undone: {undone}");
}
}
/// The window allows the input method only while `typing` says a search
/// box has the focus (`Game::text_field_focused`), so a page without one
/// must not claim the keys: the movement and menu keys keep working there.
@@ -23,7 +23,6 @@ impl OptionsUi {
Page::ControllerRadialPick => Some(&self.radial_pick),
page if Self::controller_page(page).is_some() => Some(&self.controller),
page if Self::shader_page(page).is_some() => Some(&self.shader),
Page::PackOptions => Some(&self.pack_options),
_ => None,
}
}
@@ -36,20 +35,9 @@ impl OptionsUi {
Page::ControllerRadialPick => Some(&mut self.radial_pick),
page if Self::controller_page(page).is_some() => Some(&mut self.controller),
page if Self::shader_page(page).is_some() => Some(&mut self.shader),
Page::PackOptions => Some(&mut self.pack_options),
_ => None,
}
}
/// Pack Options for the pack `id`, from the pack screen: its Polytone config entries.
pub(super) fn open_pack_options(&mut self, id: &str) {
let mut configs = horizon_polytone::pack::Configs::default();
if let Some(own) = self.pack_configs.get(id) {
configs.merge(own);
}
// Opening a shell starts it afresh: the entries go in after.
self.push(Page::PackOptions);
self.pack_options.screen = crate::pack_options_ui::PackOptionsScreen::open(configs);
}
/// Where the open shell screen asked the focus to open (a radial slot's list, on the slot's
/// action), for a controller's focus to land there.
pub fn shell_opened_focus(&self) -> Option<[f32; 4]> {
@@ -65,14 +53,13 @@ impl OptionsUi {
return;
}
// Every shell: the click may have changed the page.
let shells: [&mut dyn shell::Hosted; 7] = [
let shells: [&mut dyn shell::Hosted; 6] = [
&mut self.extras,
&mut self.graphics,
&mut self.controller,
&mut self.radial,
&mut self.radial_pick,
&mut self.shader,
&mut self.pack_options,
];
for shell in shells {
shell.clicks_step(false);
@@ -1,36 +1,45 @@
//! The Pack Options screen (#11486), on the settings shell (`settings_shell`): the config entries
//! of the selected resource packs' Polytone `config_entries` (wiki "Polytone Configs"). Each
//! `section` is a page, named by the packs' own translations; numbers are sliders that stop at
//! the entry's `step`, value lists are choices, booleans switch and free text reads. The first
//! page starts with the pack-wide presets and Reset all. The shell gives it the keyboard, a
//! controller's focus, the search, the strip's descriptions and Undo; leaving keeps what differs
//! from how the screen opened, and the packs load again with it.
//! The Pack Options page (#11486): the config entries of the selected resource packs' Polytone
//! `config_entries` (wiki "Polytone Configs"), in the frame of Horizon's settings screens
//! (`settings_shell`). Numbers are sliders, texts cycle, booleans switch; the entries sit in
//! their `section`s, named by the packs' own translations. Leaving with Done keeps what changed,
//! and the packs load again with it.
use crate::widgets::Action as Declared;
use crate::{
graphics_style as style,
hud::{HudAtlas, HudBatch},
lang,
settings::Settings,
settings_shell::{self as shell, Group, Output, Row, Sheet, Value},
settings_shell::{self as shell, Columns, Line, Lines},
text::Text,
ui,
};
use horizon_polytone::pack::{ConfigKind, ConfigValue, Configs};
/// A row: the pack-wide presets, Reset all, or the entry at an index of `ids`.
/// What a click asks of the options screen.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) enum Item {
Presets,
ResetAll,
Entry(u16),
pub enum Action {
ButtonClick,
SliderDrag,
/// Done: leave, keeping what changed.
Done,
}
const TITLE: &str = "horizon.pack.options.title";
/// The first page's group of rows for the whole pack, and every page's group of entries.
const WHOLE_PACK: &str = "Whole pack";
const PACK_OPTIONS: &str = "Pack settings";
const RESET_ALL: &str = "Reset all";
const RESET_ABOUT: &str = "Puts every option of this pack back to its default.";
const AT_DEFAULTS: &str = "Every option is at its default already.";
const PRESETS_ABOUT: &str = "Sets many options at once, as the pack groups them.";
const PACK_SETTINGS: &str = "Settings made by the pack's author: they change only this pack.";
/// A pack's tooltips, with the performance line after them, run longer than Horizon's own.
const NOTE_LINES: usize = 3;
/// The page's state: the entries being edited, how they are listed, and the pointer's hold.
#[derive(Default)]
pub struct PackOptionsUi {
/// The selected packs' entries and the values being picked.
pub configs: Configs,
/// Entry ids, by the row index the list uses.
ids: Vec<String>,
/// The sections in order: the `section` id (none for entries without one) and its rows.
sections: Vec<(Option<String>, Vec<u16>)>,
scroll: ui::Scroll,
dragging: Option<u16>,
/// A value changed since the page opened.
pub changed: bool,
}
/// The presets' row (and its section): past every entry's index.
const PRESETS: u16 = u16::MAX;
/// A translation, or `fallback` where no language has the key.
fn translated(key: &str, fallback: impl FnOnce() -> String) -> String {
@@ -56,34 +65,9 @@ fn readable(path: &str) -> String {
.unwrap_or_default()
}
/// A number as its entry shows it: whole with a whole step, else up to two decimals.
fn number_text(n: f64, step: f64) -> String {
if step >= 1.0 && step.fract() == 0.0 {
format!("{n:.0}")
} else {
let text = format!("{n:.2}");
text.trim_end_matches('0').trim_end_matches('.').to_owned()
}
}
/// The screen: the entries being edited, as they were when it opened (for Undo and for whether
/// leaving changes anything), and how they are paged.
#[derive(Default)]
pub(crate) struct PackOptionsScreen {
/// The selected packs' entries and the values being picked.
pub(crate) configs: Configs,
opened: Configs,
/// Entry ids, by `Item::Entry`'s index.
ids: Vec<String>,
/// The sections in order: the `section` id (none for entries without one) and its entries.
sections: Vec<(Option<String>, Vec<u16>)>,
/// Bumped on every change, for `stamp`: the values are floats, which don't hash.
revision: u64,
}
impl PackOptionsScreen {
/// The screen opens on `configs`, the selected packs' entries with the player's values.
pub(crate) fn open(configs: Configs) -> Self {
impl PackOptionsUi {
/// The page opens on `configs`, the selected packs' entries with the player's values.
pub fn open(configs: Configs) -> Self {
let mut ids: Vec<(String, Option<String>, i64)> = configs
.entries()
.iter()
@@ -112,21 +96,25 @@ impl PackOptionsScreen {
(None, None) => a.0.cmp(&b.0),
});
Self {
opened: configs.clone(),
configs,
ids: ids.into_iter().map(|(id, ..)| id).collect(),
sections: sections.into_iter().map(|(s, _, rows)| (s, rows)).collect(),
revision: 0,
..Self::default()
}
}
/// What leaving sends: the entries and the player's choices, if they differ from how the
/// screen opened (an Undo, or a value stepped back, leaves nothing to send).
pub(crate) fn finished(&self) -> Option<crate::options_ui::Event> {
(self.configs != self.opened).then(|| crate::options_ui::Event::PackOptions {
entries: self.configs.entries().keys().cloned().collect(),
chosen: self.configs.chosen(),
})
fn layout(&self, w: f32, h: f32) -> (Columns, Vec<Line<u16, u16>>, f32) {
let cols = Columns::of(w, h);
let mut lines = Lines::new();
// The pack-wide presets first, when the entries have some.
if !self.configs.presets().is_empty() {
lines.titled(PRESETS, vec![PRESETS]);
}
for (i, (_, rows)) in self.sections.iter().enumerate() {
lines.titled(i as u16, rows.clone());
}
let (lines, content) = lines.finish();
(cols, lines, content)
}
/// The namespace the presets' translations are under: of the first entry with presets.
@@ -178,14 +166,21 @@ impl PackOptionsScreen {
None if back => n - 1,
None => 0,
};
let before = self.configs.clone();
self.configs.apply_preset(&presets[next]);
self.revision += 1;
if self.configs != before {
self.changed = true;
}
}
/// A section's page name: `config.<namespace>.section.<id>`, by its first entry's namespace.
fn section_name(&self, section: usize) -> String {
let Some((id, rows)) = self.sections.get(section) else {
return lang::get("horizon.pack.options.general");
/// A section's heading: `config.<namespace>.section.<id>`, by its first entry's namespace.
fn section_name(&self, section: u16) -> String {
if section == PRESETS {
let key = format!("{}.presets", self.presets_namespace());
return translated(&key, || lang::get("horizon.pack.options.presets"));
}
let Some((id, rows)) = self.sections.get(usize::from(section)) else {
return String::new();
};
let Some(id) = id else {
return lang::get("horizon.pack.options.general");
@@ -197,218 +192,367 @@ impl PackOptionsScreen {
translated(&format!("config.{namespace}.section.{id}"), || readable(id))
}
/// The tooltip (`config.<namespace>.<name>.tooltip`) and the performance line after it.
fn description(&self, id: &str) -> String {
/// An entry's name (`config.<namespace>.<name>`) and its value's label.
fn parts(&self, row: u16) -> (String, Option<String>) {
if row == PRESETS {
let label = self.preset_label(self.current_preset().as_deref());
return (self.section_name(PRESETS), Some(label));
}
let Some(id) = self.ids.get(usize::from(row)) else {
return (String::new(), None);
};
let (namespace, path) = split(id);
let name = translated(&format!("config.{namespace}.{path}"), || readable(path));
let entry = &self.configs.entries()[id];
let value = match self.configs.get(id) {
Some(ConfigValue::Number(n)) => {
let step = match entry.kind {
ConfigKind::Number { step, .. } => step,
_ => 1.0,
};
let text = if step >= 1.0 && step.fract() == 0.0 {
format!("{n:.0}")
} else {
format!("{n:.2}")
.trim_end_matches('0')
.trim_end_matches('.')
.to_owned()
};
Some(text)
}
Some(ConfigValue::Text(t)) => Some(t.clone()),
Some(ConfigValue::Bool(_)) | None => None,
};
let value = value.map(|v| match &entry.value_translation {
Some(key) if lang::has(key) => lang::tr(key, &[&v]),
_ => v,
});
(name, value)
}
/// The tooltip (`config.<namespace>.<name>.tooltip`) and the performance hint.
fn description(&self, row: u16) -> String {
let Some(id) = self.ids.get(usize::from(row)) else {
return String::new();
};
let (namespace, path) = split(id);
let key = format!("config.{namespace}.{path}.tooltip");
let tooltip = if lang::has(&key) {
let mut text = if lang::has(&key) {
lang::get(&key)
} else {
String::new()
};
let impact = self.configs.entries()[id]
.performance_impact
.as_ref()
.map(|impact| {
let level = lang::get(&format!("horizon.pack.options.impact.{impact}"));
lang::tr("horizon.pack.options.impact", &[&level])
});
match impact {
Some(line) if tooltip.is_empty() => line,
Some(line) => format!("{tooltip} {line}"),
None => tooltip,
if let Some(impact) = &self.configs.entries()[id].performance_impact {
let level = lang::get(&format!("horizon.pack.options.impact.{impact}"));
let line = lang::tr("horizon.pack.options.impact", &[&level]);
text = if text.is_empty() {
line
} else {
format!("{text} {line}")
};
}
text
}
/// A slider's place (0 to 1) for a number entry.
fn slider(&self, row: u16) -> Option<f32> {
let id = self.ids.get(usize::from(row))?;
let ConfigKind::Number { min, max, .. } = self.configs.entries()[id].kind else {
return None;
};
let Some(ConfigValue::Number(n)) = self.configs.get(id) else {
return None;
};
Some(if max > min {
((n - min) / (max - min)) as f32
} else {
0.0
})
}
fn switch(&self, row: u16) -> Option<bool> {
match self.configs.get(self.ids.get(usize::from(row))?)? {
ConfigValue::Bool(b) => Some(*b),
_ => None,
}
}
/// Entry `i`'s row: a switch, a slider in its steps, a choice, or text to read.
fn entry_row(&self, i: u16) -> Option<Row<Item>> {
let id = self.ids.get(usize::from(i))?;
let (namespace, path) = split(id);
let name = translated(&format!("config.{namespace}.{path}"), || readable(path));
let entry = &self.configs.entries()[id];
let shown = |text: String| match &entry.value_translation {
Some(key) if lang::has(key) => lang::tr(key, &[&text]),
_ => text,
};
let value = match (&entry.kind, self.configs.get(id)?) {
(_, ConfigValue::Bool(on)) => Value::Switch(*on),
(&ConfigKind::Number { min, max, step }, &ConfigValue::Number(n)) => {
let span = max - min;
let stops = if step > 0.0 {
(span / step).round()
} else {
0.0
};
Value::Slider {
position: if span > 0.0 {
((n - min) / span) as f32
} else {
0.0
},
steps: (stops >= 1.0).then_some(stops as u32),
text: shown(number_text(n, step)),
pub fn draw(
&mut self,
batch: &mut HudBatch,
atlas: &HudAtlas,
cursor: (f32, f32),
in_world: bool,
) {
let (w, h) = (batch.width, batch.height);
let (cols, lines, content) = self.layout(w, h);
self.scroll.clamp(cols.top, cols.bottom, content);
shell::backdrop(batch, atlas, in_world);
shell::mark(
batch,
atlas,
&cols,
&lang::get("horizon.pack.options.title"),
);
shell::plate(
batch,
atlas,
&cols,
&lang::get("horizon.pack.options.title"),
);
let over_list = cursor.1 >= cols.top && cursor.1 < cols.bottom;
let mut described = None;
shell::list(
batch,
atlas,
&cols,
&lines,
self.scroll.amount,
|section| self.section_name(section),
|batch, row: u16, y| {
let [rx, ry, rw, rh] = cols.row(y);
let hover = over_list && ui::hovered(cursor, rx, ry, rw, rh);
if hover || self.dragging == Some(row) {
described = Some(row);
}
let (name, value) = self.parts(row);
let label = match &value {
Some(v) => format!("{name}: {v}"),
None => name.clone(),
};
let view = shell::RowView {
label: &label,
name: &name,
value: value.as_deref(),
switch: self.switch(row),
slider: self.slider(row),
live: true,
hover,
focused: false,
held: self.dragging == Some(row),
key: None,
};
shell::row(batch, atlas, &cols, y, &view);
},
);
shell::scroller(batch, atlas, &cols, content, self.scroll.amount);
// The strip: the pointed-at entry's tooltip.
let [x, y, ..] = cols.dock;
style::panel(batch, atlas, cols.dock);
if let Some(row) = described {
let name = Text::literal(self.parts(row).0);
batch.text_styled(atlas, &name, x + 12.0, y + 8.0, style::WHITE, true);
shell::dock_note(batch, atlas, &cols, self.description(row), style::GREY);
}
let mut foot = vec![(cols.button(0), "gui.done", Some(Declared::Done))];
if self
.configs
.chosen()
.iter()
.any(|(id, _)| self.ids.contains(id))
{
foot.push((cols.button(1), "controls.reset", None));
}
for (rect, key, declared) in foot {
if let Some(declared) = declared {
crate::widgets::declare_action(declared, rect, true);
}
(ConfigKind::Text { allowed }, ConfigValue::Text(t)) if !allowed.is_empty() => {
Value::Choice(shown(t.clone()))
}
(_, value) => Value::Read(shown(match value {
ConfigValue::Number(n) => number_text(*n, 1.0),
ConfigValue::Text(t) => t.clone(),
ConfigValue::Bool(b) => b.to_string(),
})),
};
Some(Row::new(Item::Entry(i), name, value).about(self.description(id)))
let label = Text::literal(lang::get(key));
shell::foot_button(batch, atlas, rect, &label, cursor, (false, true));
}
}
/// The rows for the whole pack: its presets, when it has some, and Reset all.
fn whole_pack(&self) -> Group<Item> {
let mut rows = Vec::new();
if !self.configs.presets().is_empty() {
let key = format!("{}.presets", self.presets_namespace());
let name = translated(&key, || lang::get("horizon.pack.options.presets"));
let label = self.preset_label(self.current_preset().as_deref());
rows.push(
Row::new(Item::Presets, name, Value::Choice(label)).about(lang::get(PRESETS_ABOUT)),
);
/// A press (or a drag with `drag`) at `(x, y)`; `back` turns a cycle backwards.
pub fn click(
&mut self,
(x, y): (f32, f32),
(w, h): (f32, f32),
drag: bool,
back: bool,
) -> Vec<Action> {
let (cols, lines, content) = self.layout(w, h);
let at = |[rx, ry, rw, rh]: [f32; 4]| ui::hovered((x, y), rx, ry, rw, rh);
if drag {
if self.scroll.held() {
self.scroll.drag(y, cols.top, cols.bottom, content);
} else if let Some(row) = self.dragging {
self.set_slider(row, cols.slider_at(x));
return vec![Action::SliderDrag];
}
return Vec::new();
}
let at_defaults = self.configs.chosen().is_empty();
let reset = Row::new(Item::ResetAll, lang::get(RESET_ALL), Value::Press)
.about(lang::get(RESET_ABOUT))
.blocked(at_defaults.then(|| lang::get(AT_DEFAULTS)));
rows.push(reset);
Group {
name: WHOLE_PACK,
rows,
if cols.scrolls()
&& self
.scroll
.press((x, y), cols.bar_x(), cols.top, cols.bottom, content)
{
return Vec::new();
}
if at(cols.button(0)) {
return vec![Action::ButtonClick, Action::Done];
}
if at(cols.button(1)) {
self.reset();
return vec![Action::ButtonClick];
}
if y < cols.top || y >= cols.bottom {
return Vec::new();
}
let Some(row) = lines.iter().find_map(|line| {
let row = line.setting?;
at(cols.row(cols.top + line.y - self.scroll.amount)).then_some(row)
}) else {
return Vec::new();
};
if row == PRESETS {
self.cycle_preset(back);
return vec![Action::ButtonClick];
}
let Some(id) = self.ids.get(usize::from(row)).cloned() else {
return Vec::new();
};
let entry = self.configs.entries()[&id].clone();
match (&entry.kind, self.configs.get(&id).cloned()) {
(ConfigKind::Number { .. }, _) => {
self.dragging = Some(row);
self.set_slider(row, cols.slider_at(x));
return vec![Action::SliderDrag];
}
(ConfigKind::Bool, Some(ConfigValue::Bool(b))) => {
self.set(&id, ConfigValue::Bool(!b));
}
(ConfigKind::Text { allowed }, Some(ConfigValue::Text(t))) if !allowed.is_empty() => {
let i = allowed.iter().position(|a| *a == t).unwrap_or(0);
let n = allowed.len();
let next = if back { (i + n - 1) % n } else { (i + 1) % n };
self.set(&id, ConfigValue::Text(allowed[next].clone()));
}
_ => return Vec::new(),
}
vec![Action::ButtonClick]
}
fn set(&mut self, id: &str, value: ConfigValue) {
let before = self.configs.get(id).cloned();
self.configs.set(id, value);
self.revision += 1;
if self.configs.get(id).cloned() != before {
self.changed = true;
}
}
/// Number entry `row` at slider place `at` (0 to 1).
fn set_slider(&mut self, row: u16, at: f32) {
let Some(id) = self.ids.get(usize::from(row)).cloned() else {
return;
};
if let ConfigKind::Number { min, max, .. } = self.configs.entries()[&id].kind {
self.set(&id, ConfigValue::Number(min + f64::from(at) * (max - min)));
}
}
/// Every entry back to its default.
fn reset(&mut self) {
let defaults: Vec<_> = (self.configs.entries().iter())
let defaults: Vec<_> = self
.configs
.entries()
.iter()
.map(|(id, e)| (id.clone(), e.default.clone()))
.collect();
for (id, value) in defaults {
self.set(&id, value);
}
}
}
impl shell::Screen for PackOptionsScreen {
type Page = u16;
type Row = Item;
fn title(&self) -> &'static str {
TITLE
/// The pointer lets go.
pub fn release(&mut self) {
self.scroll.release();
self.dragging = None;
}
fn note_lines(&self) -> usize {
NOTE_LINES
}
/// The rows read only the screen's own entries, which change through it alone.
fn stamp(&self, _s: &Settings) -> u64 {
self.revision
}
/// A page per section; the first starts with the rows for the whole pack.
fn sheets(&self, _s: &Settings) -> Vec<Sheet<u16, Item>> {
let about = lang::get(PACK_SETTINGS);
let mut sheets = Vec::new();
for (i, (_, entries)) in self.sections.iter().enumerate() {
let rows = entries.iter().filter_map(|&e| self.entry_row(e)).collect();
let mut groups = vec![Group {
name: PACK_OPTIONS,
rows,
}];
if i == 0 {
groups.insert(0, self.whole_pack());
}
sheets.push(Sheet::new(
i as u16,
self.section_name(i),
about.clone(),
groups,
));
}
if sheets.is_empty() {
let groups = vec![self.whole_pack()];
sheets.push(Sheet::new(0, self.section_name(0), about, groups));
}
sheets
}
/// A switch flips, a choice and the presets step (back with Shift, or Left), Reset all
/// resets.
fn press(&mut self, _s: &mut Settings, item: Item, back: bool) -> Vec<Output> {
let i = match item {
Item::Presets => {
self.cycle_preset(back);
return Vec::new();
}
Item::ResetAll => {
self.reset();
return Vec::new();
}
Item::Entry(i) => i,
};
let Some(id) = self.ids.get(usize::from(i)).cloned() else {
return Vec::new();
};
let kind = self.configs.entries()[&id].kind.clone();
match (kind, self.configs.get(&id).cloned()) {
(_, Some(ConfigValue::Bool(on))) => self.set(&id, ConfigValue::Bool(!on)),
(ConfigKind::Text { allowed }, Some(ConfigValue::Text(t))) if !allowed.is_empty() => {
let at = allowed.iter().position(|a| *a == t).unwrap_or(0);
let n = allowed.len();
let next = if back { (at + n - 1) % n } else { (at + 1) % n };
self.set(&id, ConfigValue::Text(allowed[next].clone()));
}
_ => {}
}
Vec::new()
}
/// A slider moves its entry to the step nearest it (`Configs::set` snaps it).
fn slide(&mut self, _s: &mut Settings, item: Item, position: f32) {
let Item::Entry(i) = item else { return };
let Some(id) = self.ids.get(usize::from(i)).cloned() else {
return;
};
if let ConfigKind::Number { min, max, .. } = self.configs.entries()[&id].kind {
let value = min + f64::from(position.clamp(0.0, 1.0)) * (max - min);
self.set(&id, ConfigValue::Number(value));
}
}
/// With the "Scroll wheel changes settings" extra, the wheel steps a choice and the presets.
fn wheel_step(&mut self, s: &mut Settings, item: Item, back: bool) -> Option<Vec<Output>> {
let steps = match item {
Item::Presets => true,
Item::Entry(i) => self
.entry_row(i)
.is_some_and(|row| matches!(row.value, Value::Choice(_))),
Item::ResetAll => false,
};
if !steps {
return None;
}
let mut outputs = vec![Output::Event(crate::options_ui::Event::ButtonClick)];
outputs.extend(self.press(s, item, back));
Some(outputs)
}
fn undoes(&self) -> bool {
true
}
/// The entries as the screen opened with them.
fn undo(&mut self, _s: &mut Settings, _before: &Settings) -> Vec<Output> {
self.configs = self.opened.clone();
self.revision += 1;
Vec::new()
}
/// Undo shows exactly while an entry differs from how the screen opened.
fn differs(&self, _s: &Settings, _before: &Settings) -> Option<bool> {
Some(self.configs != self.opened)
/// The mouse wheel scrolls the list.
pub fn scroll(&mut self, (w, h): (f32, f32), amount: f32) {
let (cols, _, content) = self.layout(w, h);
self.scroll
.wheel(amount, 18.0, cols.top, cols.bottom, content);
}
}
#[cfg(test)]
mod tests;
mod tests {
use super::*;
fn configs() -> Configs {
let mut c = Configs::default();
c.add_entry(
"p:fog".into(),
&serde_json::json!({"default_value": 0.5, "section": "sky", "section_order": 2}),
);
c.add_entry("p:rain".into(), &serde_json::json!({"default_value": "drops", "allowed_values": ["drops", "streaks"], "section": "weather", "section_order": 1}));
c.add_entry(
"p:birds".into(),
&serde_json::json!({"default_value": true}),
);
c
}
#[test]
fn sections_sort_by_their_order_and_the_unsectioned_last() {
let ui = PackOptionsUi::open(configs());
let order: Vec<_> = ui.sections.iter().map(|(s, _)| s.as_deref()).collect();
assert_eq!(order, [Some("weather"), Some("sky"), None]);
}
#[test]
fn rows_switch_cycle_and_slide() {
let mut ui = PackOptionsUi::open(configs());
let size = (480.0, 270.0);
let (cols, lines, _) = ui.layout(size.0, size.1);
let ids = ui.ids.clone();
let point = |id: &str| {
let row = ids.iter().position(|i| i == id).unwrap() as u16;
let line = lines.iter().find(|l| l.setting == Some(row)).unwrap();
let [x, y, w, h] = cols.row(cols.top + line.y);
(x + w - 4.0, y + h / 2.0)
};
let (birds, rain) = (point("p:birds"), point("p:rain"));
ui.click(birds, size, false, false);
assert_eq!(ui.configs.get("p:birds"), Some(&ConfigValue::Bool(false)));
ui.click(rain, size, false, false);
assert_eq!(
ui.configs.get("p:rain"),
Some(&ConfigValue::Text("streaks".into()))
);
// The slider's far right end is its maximum.
let fog = point("p:fog");
let (tx, tw) = cols.track();
ui.click((tx + tw, fog.1), size, false, false);
ui.release();
assert_eq!(ui.configs.get("p:fog"), Some(&ConfigValue::Number(1.0)));
assert!(ui.changed);
assert_eq!(ui.configs.chosen().len(), 3);
ui.reset();
assert!(ui.configs.chosen().is_empty());
}
#[test]
fn the_presets_row_cycles_the_pack_wide_presets_and_shows_custom_otherwise() {
let mut c = Configs::default();
let entry = |default: f64, fast: f64, pretty: f64| serde_json::json!({"default_value": default, "presets": {"fast": fast, "pretty": pretty}});
c.add_entry("p:fog".into(), &entry(0.5, 0.0, 1.0));
c.add_entry("p:dust".into(), &entry(0.5, 0.0, 0.8));
let mut ui = PackOptionsUi::open(c);
// The defaults are no preset.
assert_eq!(ui.current_preset(), None);
ui.cycle_preset(false);
assert_eq!(ui.current_preset().as_deref(), Some("fast"));
assert_eq!(ui.configs.get("p:fog"), Some(&ConfigValue::Number(0.0)));
ui.cycle_preset(false);
assert_eq!(ui.current_preset().as_deref(), Some("pretty"));
ui.cycle_preset(true);
assert_eq!(ui.current_preset().as_deref(), Some("fast"));
// One value off the preset: custom again.
ui.set("p:dust", ConfigValue::Number(0.3));
assert_eq!(ui.current_preset(), None);
assert!(ui.changed);
}
}
@@ -1,281 +0,0 @@
use super::*;
use crate::options_ui::Event;
use crate::settings_shell::{Columns, Hosted, Screen as _, Shell, Target};
use winit::keyboard::KeyCode as K;
const SIZE: (f32, f32) = (854.0, 480.0);
/// Fog (a number) under Sky, rain (a list of values) under Weather, birds (a boolean) in no
/// section.
fn configs() -> Configs {
let mut c = Configs::default();
c.add_entry(
"p:fog".into(),
&serde_json::json!({"default_value": 0.5, "section": "sky", "section_order": 2}),
);
c.add_entry("p:rain".into(), &serde_json::json!({"default_value": "drops", "allowed_values": ["drops", "streaks"], "section": "weather", "section_order": 1}));
c.add_entry(
"p:birds".into(),
&serde_json::json!({"default_value": true}),
);
c
}
/// Two entries with the pack-wide presets `fast` and `pretty`.
fn with_presets() -> Configs {
let mut c = Configs::default();
let entry = |default: f64, fast: f64, pretty: f64| serde_json::json!({"default_value": default, "presets": {"fast": fast, "pretty": pretty}});
c.add_entry("p:fog".into(), &entry(0.5, 0.0, 1.0));
c.add_entry("p:dust".into(), &entry(0.5, 0.0, 0.8));
c
}
fn shell_of(configs: Configs) -> Shell<PackOptionsScreen> {
let mut shell = Shell::default();
shell.screen = PackOptionsScreen::open(configs);
shell
}
/// The row of entry `id`, and the page it is on.
fn entry(shell: &Shell<PackOptionsScreen>, id: &str) -> (u16, Item) {
let i = shell.screen.ids.iter().position(|e| e == id).unwrap() as u16;
let page = shell.screen.sections.iter().position(|s| s.1.contains(&i));
(page.unwrap() as u16, Item::Entry(i))
}
fn press(shell: &mut Shell<PackOptionsScreen>, s: &mut Settings, item: Item) -> Vec<Output> {
let at = shell.point_at(s, SIZE, item);
shell.click(s, at, SIZE, false, false, false)
}
fn value<'a>(shell: &'a Shell<PackOptionsScreen>, id: &str) -> Option<&'a ConfigValue> {
shell.screen.configs.get(id)
}
#[test]
fn sections_sort_by_their_order_and_the_unsectioned_last() {
let screen = PackOptionsScreen::open(configs());
let order: Vec<_> = screen.sections.iter().map(|(s, _)| s.as_deref()).collect();
assert_eq!(order, [Some("weather"), Some("sky"), None]);
// Each section is a page, the first one holding Reset all before its entries.
let sheets = screen.sheets(&Settings::default());
let names: Vec<_> = sheets.iter().map(|p| p.name.as_str()).collect();
assert_eq!(names, ["Weather", "Sky", "horizon.pack.options.general"]);
let first: Vec<Vec<Item>> = (sheets[0].groups.iter())
.map(|g| g.rows.iter().map(|r| r.id).collect())
.collect();
let rain = screen.ids.iter().position(|e| e == "p:rain").unwrap() as u16;
assert_eq!(first, [vec![Item::ResetAll], vec![Item::Entry(rain)]]);
}
#[test]
fn rows_switch_cycle_and_slide() {
let mut s = Settings::default();
let mut shell = shell_of(configs());
let (page, birds) = entry(&shell, "p:birds");
shell.show(page);
assert_eq!(
press(&mut shell, &mut s, birds)[0],
Output::Event(Event::ButtonClick)
);
assert_eq!(value(&shell, "p:birds"), Some(&ConfigValue::Bool(false)));
let (page, rain) = entry(&shell, "p:rain");
shell.show(page);
press(&mut shell, &mut s, rain);
let streaks = ConfigValue::Text("streaks".into());
assert_eq!(value(&shell, "p:rain"), Some(&streaks));
// The slider's far right end is its maximum.
let (page, fog) = entry(&shell, "p:fog");
shell.show(page);
let at = shell.point_at(&s, SIZE, fog);
let (track, width) = Columns::of(SIZE.0, SIZE.1).track();
shell.click(&mut s, (track + width, at.1), SIZE, false, false, false);
shell.release();
assert_eq!(value(&shell, "p:fog"), Some(&ConfigValue::Number(1.0)));
assert_eq!(shell.screen.configs.chosen().len(), 3);
// Reset all, on the first page, puts them all back, and is greyed once they are.
shell.show(0);
press(&mut shell, &mut s, Item::ResetAll);
assert!(shell.screen.configs.chosen().is_empty());
let sheets = shell.screen.sheets(&s);
assert!(!sheets[0].groups[0].rows[0].live);
}
#[test]
fn the_presets_row_cycles_the_pack_wide_presets_and_shows_custom_otherwise() {
let mut screen = PackOptionsScreen::open(with_presets());
// The defaults are no preset.
assert_eq!(screen.current_preset(), None);
screen.cycle_preset(false);
assert_eq!(screen.current_preset().as_deref(), Some("fast"));
assert_eq!(screen.configs.get("p:fog"), Some(&ConfigValue::Number(0.0)));
screen.cycle_preset(false);
assert_eq!(screen.current_preset().as_deref(), Some("pretty"));
screen.cycle_preset(true);
assert_eq!(screen.current_preset().as_deref(), Some("fast"));
// One value off the preset: custom again.
screen.set("p:dust", ConfigValue::Number(0.3));
assert_eq!(screen.current_preset(), None);
let presets = &screen.sheets(&Settings::default())[0].groups[0].rows[0];
assert_eq!(presets.id, Item::Presets);
let custom = lang::get("horizon.pack.options.presets.custom");
assert_eq!(presets.value, Value::Choice(custom));
}
#[test]
fn left_and_right_step_the_presets() {
let mut s = Settings::default();
let mut shell = shell_of(with_presets());
shell.set_focus(Some(Target::Row(Item::Presets)));
shell.key(&mut s, K::ArrowRight, None, false, SIZE);
assert_eq!(shell.screen.current_preset().as_deref(), Some("fast"));
shell.key(&mut s, K::ArrowRight, None, false, SIZE);
assert_eq!(shell.screen.current_preset().as_deref(), Some("pretty"));
shell.key(&mut s, K::ArrowLeft, None, false, SIZE);
assert_eq!(shell.screen.current_preset().as_deref(), Some("fast"));
assert_eq!(shell.focused_row(), Some(Item::Presets));
}
#[test]
fn sliders_stop_at_the_entrys_step() {
let mut c = Configs::default();
let json = serde_json::json!({"default_value": 4.0, "min": 0.0, "max": 10.0, "step": 2.0});
c.add_entry("p:clouds".into(), &json);
let mut s = Settings::default();
let mut shell = shell_of(c);
let row = &shell.screen.sheets(&s)[0].groups[1].rows[0];
let stops = Value::Slider {
position: 0.4,
steps: Some(5),
text: "4".into(),
};
assert_eq!(row.value, stops);
// A press a little past the middle of the track lands on the step nearest it.
let at = shell.point_at(&s, SIZE, Item::Entry(0));
let (track, width) = Columns::of(SIZE.0, SIZE.1).track();
shell.click(
&mut s,
(track + width * 0.55, at.1),
SIZE,
false,
false,
false,
);
shell.release();
assert_eq!(value(&shell, "p:clouds"), Some(&ConfigValue::Number(6.0)));
// Held by the press, Right goes one step on and Left one back.
shell.set_focus(Some(Target::Row(Item::Entry(0))));
shell.key(&mut s, K::ArrowRight, None, false, SIZE);
assert_eq!(value(&shell, "p:clouds"), Some(&ConfigValue::Number(8.0)));
shell.key(&mut s, K::ArrowLeft, None, false, SIZE);
shell.key(&mut s, K::ArrowLeft, None, false, SIZE);
assert_eq!(value(&shell, "p:clouds"), Some(&ConfigValue::Number(4.0)));
}
/// A language with the pack's own strings: a name, a section and a tooltip.
struct PackLang;
impl lang::ResourceSource for PackLang {
fn read(&self, path: &str) -> Option<Vec<u8>> {
(path == "assets/minecraft/lang/en_us.json").then(|| {
let strings = serde_json::json!({
"config.minecraft.haze": "Haze",
"config.minecraft.haze.tooltip": "Thickens the distant air.",
"config.minecraft.section.sky": "Sky and fog",
});
serde_json::to_vec(&strings).unwrap()
})
}
}
fn haze() -> Configs {
let mut c = configs();
let json =
serde_json::json!({"default_value": false, "section": "sky", "performance_impact": "high"});
c.add_entry("minecraft:haze".into(), &json);
c
}
#[test]
fn the_search_finds_an_entry_by_its_tooltip_and_the_strip_has_its_impact() {
let language = lang::Language::load(&[&PackLang], "en_us");
lang::scoped(language, || {
let s = Settings::default();
let mut shell = shell_of(haze());
let (page, haze) = entry(&shell, "minecraft:haze");
shell.set_search("distant air");
assert_eq!(shell.listed(&s, SIZE), [(page, haze)]);
let sheets = shell.screen.sheets(&s);
assert_eq!(sheets[usize::from(page)].name, "Sky and fog");
let row = sheets.iter().flat_map(|p| &p.groups).flat_map(|g| &g.rows);
let row = row.into_iter().find(|r| r.id == haze).unwrap();
assert_eq!(row.name, "Haze");
assert_eq!(
row.about,
"Thickens the distant air. Performance impact: high"
);
});
}
#[test]
fn tab_reaches_every_row_of_every_page() {
let mut s = Settings::default();
let mut shell = shell_of(haze());
let pages = shell.screen.sheets(&s).len() as u16;
let mut seen = Vec::new();
for page in 0..pages {
shell.show(page);
shell.set_focus(None);
for _ in 0..8 {
shell.key(&mut s, K::Tab, None, false, SIZE);
if let Some(row) = shell.focused_row()
&& !seen.contains(&row)
{
seen.push(row);
}
}
}
// Reset all is greyed at the defaults; every entry is reached.
let mut entries: Vec<Item> = (0..shell.screen.ids.len() as u16)
.map(Item::Entry)
.collect();
seen.sort_by_key(|item| format!("{item:?}"));
entries.sort_by_key(|item| format!("{item:?}"));
assert_eq!(seen, entries);
}
#[test]
fn undo_puts_the_entries_back_and_then_leaving_sends_nothing() {
let mut s = Settings::default();
let mut shell = shell_of(configs());
let (page, birds) = entry(&shell, "p:birds");
shell.show(page);
press(&mut shell, &mut s, birds);
assert!(shell.foot_at(&s, SIZE).iter().any(|f| f.0 == Target::Undo));
assert!(shell.screen.finished().is_some());
let undo = shell
.foot_at(&s, SIZE)
.into_iter()
.find(|f| f.0 == Target::Undo);
let [x, y, w, h] = undo.unwrap().1;
shell.click(
&mut s,
(x + w / 2.0, y + h / 2.0),
SIZE,
false,
false,
false,
);
assert_eq!(value(&shell, "p:birds"), Some(&ConfigValue::Bool(true)));
assert!(!shell.foot_at(&s, SIZE).iter().any(|f| f.0 == Target::Undo));
assert_eq!(shell.screen.finished(), None);
// Stepped there and back by hand, it sends nothing either.
press(&mut shell, &mut s, birds);
press(&mut shell, &mut s, birds);
assert_eq!(shell.screen.finished(), None);
press(&mut shell, &mut s, birds);
let Some(Event::PackOptions { entries, chosen }) = shell.screen.finished() else {
panic!("a change is sent");
};
assert_eq!(entries.len(), 3);
assert_eq!(chosen.get("p:birds"), Some(&ConfigValue::Bool(false)));
}
@@ -677,7 +677,7 @@ impl PackScreen {
return action;
}
if self.search.contains(x, y) {
self.search.click(m, x, false, false);
self.search.click(m, x, false);
self.set_focus(Focus::Search);
return Action::None;
}
@@ -1137,7 +1137,7 @@ impl PackScreen {
if d::inside(point, qx, qy, BROWSER_SEARCH_W, 18) {
self.browser_search.x = qx;
self.browser_search.y = qy;
self.browser_search.click(m, x, false, false);
self.browser_search.click(m, x, false);
self.browser_focus = true;
return Some(Action::None);
}
+16 -232
View File
@@ -468,20 +468,17 @@ fn read_meta(source: &Source) -> Option<serde_json::Value> {
/// file with a comment after the closing brace. Gson reads past a UTF-8 byte order mark;
/// serde_json rejects it.
pub(crate) fn parse_meta(bytes: &[u8]) -> Option<serde_json::Value> {
first_json(bytes).ok()
first_json(bytes)
}
/// The first JSON value of a `.mcmeta` file, as `ResourceMetadata.fromJsonStream` reads it:
/// Gson's `TypeAdapter.read` stops after the value, so text after it (packs leave `//` notes
/// there) is never read, and a UTF-8 byte order mark is skipped.
pub(crate) fn first_json<T: serde::de::DeserializeOwned>(bytes: &[u8]) -> serde_json::Result<T> {
let bytes = bytes.strip_prefix(b"\xEF\xBB\xBF").unwrap_or(bytes);
match serde_json::Deserializer::from_slice(bytes)
/// Reads the first JSON value from resource metadata, matching Gson's
/// `JsonReader` (which ignores a trailing signature or comment). Resource
/// packs commonly append such text to texture metadata as well as pack.mcmeta.
pub(crate) fn first_json(bytes: &[u8]) -> Option<serde_json::Value> {
serde_json::Deserializer::from_slice(bytes.strip_prefix(b"\xEF\xBB\xBF").unwrap_or(bytes))
.into_iter()
.next()
{
Some(value) => value,
None => Err(serde::de::Error::custom("empty metadata")),
}
.next()?
.ok()
}
/// A pack's Polytone config entries (`assets/<namespace>/polytone/config_entries/<name>.json`,
/// in the pack's base, not its overlays) at their default values.
@@ -830,6 +827,13 @@ fn build_overlay_uncached(
}
// Vanilla sits below every pack, so filters hide its files too.
let filters: Vec<&Filter> = packs.iter().flat_map(|p| &p.filter).collect();
let touched_dirs: BTreeSet<String> = files
.keys()
.flat_map(|f| {
let parts: Vec<&str> = f.split('/').collect();
(1..parts.len()).map(move |n| parts[..n].join("/"))
})
.collect();
let zips: Vec<Option<Zip>> = packs
.iter()
.map(|p| {
@@ -878,21 +882,6 @@ fn build_overlay_uncached(
merged.insert(name.clone(), bytes);
}
}
add_sprite_renames(
vanilla,
&merged,
&filters,
&mut files,
&mut hidden,
dependencies,
);
let touched_dirs: BTreeSet<String> = files
.keys()
.flat_map(|f| {
let parts: Vec<&str> = f.split('/').collect();
(1..parts.len()).map(move |n| parts[..n].join("/"))
})
.collect();
/// A zip entry to write: its pack, its name in the zip and where it goes.
type Extract<'a> = (usize, &'a str, PathBuf);
#[allow(clippy::too_many_arguments)]
@@ -1043,123 +1032,6 @@ fn build_overlay_uncached(
}
extracted
}
/// `SingleFile` with a `sprite`: the atlas holds the resource's pixels, and the resource's
/// `.mcmeta`, under the sprite's id. Every other sprite of the blocks and items atlases is its
/// texture's own id, and the loaders read a model's sprite from `textures/<sprite>.png`, so the
/// overlay gives a renamed sprite that file. ItemsAdder and Nexo packs name their models'
/// textures only through these renames (#14485).
///
/// A sprite gets its resource's file only when the whole source list, in order, ends on the
/// rename (`SpriteSourceList.list`: a later source of the same id replaces it), when the other
/// atlas, which reads the same file, lists it from that resource too or not at all, and when it
/// has no texture of its own. A texture that is there may be read as itself (another source's
/// resource, an unstitched or paletted sprite's input), so no alias ever replaces one; such a
/// sprite draws its own texture, as before aliases.
fn add_sprite_renames(
vanilla: &Path,
merged: &BTreeMap<String, Vec<u8>>,
filters: &[&Filter],
files: &mut BTreeMap<String, (usize, Provided)>,
hidden: &mut BTreeSet<String>,
dependencies: &mut cache::Dependencies,
) {
use crate::atlas_sources::{
SpriteOrigin, SpriteSource, decode, list, list_textures, texture_path,
};
let png = |id: &str| {
texture_path(Path::new(""), id, "textures")
.to_string_lossy()
.replace('\\', "/")
};
let atlases: Vec<_> = ["blocks", "items"]
.into_iter()
.filter_map(|atlas| merged.get(&format!("assets/minecraft/atlases/{atlas}.json")))
.filter_map(|bytes| decode(std::str::from_utf8(bytes).ok()?))
.collect();
let renamed = |source: &SpriteSource| matches!(source, SpriteSource::Single { resource, sprite: Some(sprite) } if sprite != resource);
if !atlases.iter().flatten().any(renamed) {
return;
}
// The textures a source can list: the packs' and vanilla's the packs leave visible.
let mut textures: Vec<String> = list_textures(vanilla)
.into_iter()
.filter(|id| {
let name = png(id);
!hidden.contains(&name) && !filters.iter().any(|f| f.blocks(&name))
})
.chain(files.keys().filter_map(|name| {
let (namespace, rest) = name.strip_prefix("assets/")?.split_once('/')?;
let path = rest.strip_prefix("textures/")?.strip_suffix(".png")?;
Some(format!("{namespace}:{path}"))
}))
.collect();
textures.sort();
textures.dedup();
// Each sprite's resource, `None` where an atlas lists it any other way.
let mut renames: BTreeMap<String, Option<String>> = BTreeMap::new();
for sources in &atlases {
for (sprite, origin) in list(sources, &textures) {
let from = match origin {
SpriteOrigin::File(resource) if resource != sprite => Some(resource),
_ => None,
};
renames
.entry(sprite)
.and_modify(|seen| {
if *seen != from {
*seen = None;
}
})
.or_insert(from);
}
}
let renames = renames
.into_iter()
.filter(|(sprite, _)| textures.binary_search(sprite).is_err())
.filter_map(|(sprite, resource)| Some((png(&resource?), png(&sprite))));
// Each resource is the file the packs give, never another rename's sprite.
let mut found = Vec::new();
for (from, to) in renames {
// `texture_path` names an id that would leave the root as a file that is never there.
if !stays_inside(&from) || !stays_inside(&to) {
continue;
}
let from_meta = format!("{from}.mcmeta");
// A pack's texture with its own `.mcmeta`, or vanilla's below every pack.
let (file, meta) = match files.get(&from) {
Some(file) => (file.clone(), files.get(&from_meta).cloned()),
None => {
let (path, meta_path) = (vanilla.join(&from), vanilla.join(&from_meta));
dependencies.file(&path);
dependencies.file(&meta_path);
if !path.is_file() || filters.iter().any(|f| f.blocks(&from)) {
continue;
}
// `createStackMetadataFinder`: a pack's filter hides vanilla's `.mcmeta` too.
let meta = files.get(&from_meta).cloned().or_else(|| {
(meta_path.is_file() && !filters.iter().any(|f| f.blocks(&from_meta)))
.then(|| (0, (Some(meta_path), from_meta.clone())))
});
((0, (Some(path), from.clone())), meta)
}
};
found.push((to, file, meta));
}
for (to, file, meta) in found {
let to_meta = format!("{to}.mcmeta");
files.insert(to, file);
match meta {
Some(meta) => {
hidden.remove(&to_meta);
files.insert(to_meta, meta);
}
None => {
files.remove(&to_meta);
hidden.insert(to_meta);
}
}
}
}
/// The most the zip packs in `packs` may unpack to in one overlay: 16 times their size on disk
/// (real packs are mostly PNGs and JSON, a few times smaller zipped at most), at least 64 MiB
/// for a small pack of text, and never past 8 GiB.
@@ -2034,94 +1906,6 @@ mod tests {
let _ = fs::remove_dir_all(base);
}
#[test]
fn a_renamed_atlas_sprite_reads_its_resource() {
let base =
std::env::temp_dir().join(format!("horizon-sprite-rename-{}", std::process::id()));
let _ = fs::remove_dir_all(&base);
let write = |path: PathBuf, bytes: &[u8]| {
fs::create_dir_all(path.parent().unwrap()).unwrap();
fs::write(path, bytes).unwrap();
};
let vanilla = base.join("vanilla");
let textures = vanilla.join("assets/minecraft/textures");
let animation = b"{\"animation\":{}}";
write(textures.join("block/sea_lantern.png"), b"lantern");
write(textures.join("block/sea_lantern.png.mcmeta"), animation);
write(textures.join("item/stick.png"), b"vanilla stick");
write(textures.join("item/stick.png.mcmeta"), animation);
let meta = br#"{"pack":{"description":"d","pack_format":97}}"#;
let pack = base.join("packs/IA");
write(pack.join("pack.mcmeta"), meta);
write(pack.join("assets/iageneric/textures/item/box.png"), b"box");
// An ItemsAdder pack's items atlas: its models name only the `ia:` sprites.
write(
pack.join("assets/minecraft/atlases/items.json"),
br#"{"sources":[
{"type":"single","resource":"iageneric:item/box","sprite":"ia:0"},
{"type":"single","resource":"minecraft:block/sea_lantern","sprite":"ia:1199"},
{"type":"single","resource":"iageneric:item/box","sprite":"minecraft:item/stick"},
{"type":"single","resource":"minecraft:item/stick","sprite":"ia:3"},
{"type":"single","resource":"iageneric:item/gone","sprite":"ia:2"},
{"type":"single","resource":"iageneric:item/box","sprite":"ia:../../../escape"},
{"type":"single","resource":"iageneric:item/box","sprite":"ia:7"},
{"type":"single","resource":"iageneric:item/box","sprite":"ia:8"},
{"type":"single","resource":"iageneric:item/box","sprite":"ia:9"}
]}"#,
);
// A pack above it: later sources of three of those sprites, a blocks atlas that
// disagrees about another, and a filter hiding vanilla's animation of the stick.
let higher = base.join("packs/Top");
write(
higher.join("pack.mcmeta"),
br#"{"pack":{"description":"d","pack_format":97},
"filter":{"block":[{"path":"textures/item/stick\\.png\\.mcmeta"}]}}"#,
);
write(
higher.join("assets/minecraft/atlases/items.json"),
br#"{"sources":[
{"type":"single","resource":"minecraft:block/sea_lantern","sprite":"ia:8"},
{"type":"filter","pattern":{"namespace":"ia","path":"7"}}
]}"#,
);
write(
higher.join("assets/minecraft/atlases/blocks.json"),
br#"{"sources":[
{"type":"single","resource":"minecraft:block/sea_lantern","sprite":"ia:9"}
]}"#,
);
let packs = discover(&vanilla, &base.join("packs"));
let out = base.join("overlay");
build_overlay(&vanilla, &packs, &out).unwrap();
let read = |rel: &str| fs::read(out.join(rel)).ok();
let texture = |id: &str| read(&format!("assets/ia/textures/{id}.png"));
assert_eq!(texture("0").as_deref(), Some(&b"box"[..]));
assert_eq!(read("assets/ia/textures/0.png.mcmeta"), None);
// A vanilla resource comes with its animation.
assert_eq!(texture("1199").as_deref(), Some(&b"lantern"[..]));
assert_eq!(
read("assets/ia/textures/1199.png.mcmeta").as_deref(),
Some(&animation[..])
);
// A texture that is there stays itself: other sources may read it (here as `ia:3`'s
// resource; an unstitched or paletted sprite's input alike).
assert_eq!(
read("assets/minecraft/textures/item/stick.png").as_deref(),
Some(&b"vanilla stick"[..])
);
// ...with its `.mcmeta` only where no filter hides it.
assert_eq!(texture("3").as_deref(), Some(&b"vanilla stick"[..]));
assert_eq!(read("assets/ia/textures/3.png.mcmeta"), None);
// A missing resource adds nothing, and no rename leaves the overlay.
assert_eq!(texture("2"), None);
assert!(!out.join("escape.png").exists());
// The last source of a sprite wins: a filter drops it, a later rename replaces it.
assert_eq!(texture("7"), None);
assert_eq!(texture("8").as_deref(), Some(&b"lantern"[..]));
// The two atlases read one file, and disagree about `ia:9`: it gets neither.
assert_eq!(texture("9"), None);
let _ = fs::remove_dir_all(base);
}
#[test]
fn every_file_of_a_big_stack_comes_from_its_top_pack() {
use std::io::Write as _;
let base = std::env::temp_dir().join(format!("horizon-pack-stack-{}", std::process::id()));
@@ -13,8 +13,7 @@ use std::{collections::BTreeSet, fs, io, path::Path, path::PathBuf};
// Version 5 read every vanilla file to stamp it on Windows.
// Version 6 stamps vanilla's files by their metadata on Windows too.
// Version 7 stacks blockstate files (every pack's definition, bottom first).
// Version 8 left an atlas `single` source's renamed sprite without its texture file (#14485).
const VERSION: u32 = 9;
const VERSION: u32 = 8;
#[derive(Default, Serialize, Deserialize)]
pub(super) struct Dependencies {
+105 -119
View File
@@ -1402,8 +1402,100 @@ impl ParticleLightCache {
}
}
mod view_cull;
use view_cull::{PARTICLE_FRUSTUM_OFFSET, ParticleSectionFrustumCache, SectionFrustumResult};
const PARTICLE_SECTION_CACHE_SIZE: usize = 128;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum SectionFrustumResult {
Outside,
Intersects,
Inside,
}
#[derive(Clone, Copy)]
struct CachedSectionFrustum {
section: [i32; 3],
radius_quarters: i32,
result: SectionFrustumResult,
}
struct ParticleSectionFrustumCache {
entries: [Option<CachedSectionFrustum>; PARTICLE_SECTION_CACHE_SIZE],
}
impl Default for ParticleSectionFrustumCache {
fn default() -> Self {
Self {
entries: [None; PARTICLE_SECTION_CACHE_SIZE],
}
}
}
impl ParticleSectionFrustumCache {
fn result(
&mut self,
world: [f64; 3],
camera: DVec3,
radius: f64,
frustum: &crate::gfx::Frustum,
) -> SectionFrustumResult {
let Some(section) = world_section(world) else {
return SectionFrustumResult::Intersects;
};
if !radius.is_finite() || radius < 0.0 || radius * 4.0 > f64::from(i32::MAX) {
return SectionFrustumResult::Intersects;
}
let radius_quarters = (radius * 4.0).ceil() as i32;
let hash = (section[0] as u32).wrapping_mul(73_856_093)
^ (section[1] as u32).wrapping_mul(19_349_663)
^ (section[2] as u32).wrapping_mul(83_492_791)
^ (radius_quarters as u32).wrapping_mul(2_654_435_761);
let slot = hash as usize & (PARTICLE_SECTION_CACHE_SIZE - 1);
if let Some(entry) = self.entries[slot]
&& entry.section == section
&& entry.radius_quarters == radius_quarters
{
return entry.result;
}
let pad = f64::from(radius_quarters) * 0.25;
let camera = camera.to_array();
let min = array::from_fn(|axis| f64::from(section[axis]) * 16.0 - pad - camera[axis]);
let max = array::from_fn(|axis| min[axis] + 16.0 + 2.0 * pad);
let result = if min.into_iter().chain(max).any(|v| !v.is_finite()) {
SectionFrustumResult::Intersects
} else {
let min = FVec3::from_array(min.map(|v| v as f32));
let max = FVec3::from_array(max.map(|v| v as f32));
if !min.is_finite() || !max.is_finite() {
SectionFrustumResult::Intersects
} else if frustum.contains(min, max) {
SectionFrustumResult::Inside
} else if frustum.intersects(min, max) {
SectionFrustumResult::Intersects
} else {
SectionFrustumResult::Outside
}
};
self.entries[slot] = Some(CachedSectionFrustum {
section,
radius_quarters,
result,
});
result
}
}
fn world_section(position: [f64; 3]) -> Option<[i32; 3]> {
let mut block = [0; 3];
for axis in 0..3 {
let value = position[axis].floor();
if !value.is_finite() || value < f64::from(i32::MIN) || value > f64::from(i32::MAX) {
return None;
}
block[axis] = value as i32;
}
Some([block[0] >> 4, block[1] >> 4, block[2] >> 4])
}
fn below_half_pixel(radius: f64, distance_squared: f64, pixel_focal_length: f32) -> bool {
let projected_limit = 4.0 * radius * f64::from(pixel_focal_length);
@@ -4611,7 +4703,16 @@ impl ParticleEngine {
light_at: &dyn Fn([i32; 3]) -> u8,
out: &mut Vec<Vertex>,
) {
self.render_in_view(camera, base, partial, None, light_at, out);
self.render_inner::<false>(
camera,
base,
partial,
0.0,
None,
&mut |_, _| false,
light_at,
out,
);
}
/// Render particles after rejecting view-frustum misses and any particles
@@ -4629,7 +4730,7 @@ impl ParticleEngine {
out: &mut Vec<Vertex>,
) {
if !culling_enabled {
self.render_in_view(camera, base, partial, frustum, light_at, out);
self.render(camera, base, partial, light_at, out);
return;
}
self.render_inner::<true>(
@@ -4660,16 +4761,10 @@ impl ParticleEngine {
additive.clear();
let mut section_cache =
(CULL && frustum.is_some()).then(ParticleSectionFrustumCache::default);
let view = frustum.map(|f| f.pulled_back(PARTICLE_FRUSTUM_OFFSET));
for p in &self.particles {
if p.no_render {
continue;
}
if let Some(view) = &view
&& !view_cull::in_view(view, p, camera)
{
continue;
}
// SparkParticle.extract: twinkling sparks blink after a third of their life.
if let Behaviour::Spark { twinkle: true, .. } = p.behaviour
&& p.age >= p.lifetime / 3
@@ -5104,115 +5199,6 @@ mod tests {
assert_eq!(attributes(&disabled), attributes(&regular));
}
/// An engine whose smoke particles stand at `positions`, camera-relative (the camera is at
/// the origin looking down -z, like `Mat4::IDENTITY` as a view).
fn smoke_at(positions: &[[f64; 3]]) -> ParticleEngine {
let mut engine = ParticleEngine::new(Path::new(""), &HashMap::new(), &HashSet::new());
let sprite = "test:smoke".to_owned();
engine.atlas.insert(
sprite.clone(),
(
Rect {
u0: 0.0,
v0: 0.0,
u1: 1.0,
v1: 1.0,
w: 16,
h: 16,
},
false,
),
);
let mut random = LegacyRandom::new(7);
for &at in positions {
let mut particle = Particle::moving(&mut random, ParticleType::Smoke, at, [0.0; 3]);
particle.sprite = Sprite::Named(sprite.clone());
engine.particles.push(particle);
}
engine
}
fn quad_vertices(engine: &ParticleEngine, view: Option<&crate::gfx::Frustum>) -> usize {
let mut out = Vec::new();
engine.render_in_view(DVec3::ZERO, Quat::IDENTITY, 0.5, view, &|_| 0xf0, &mut out);
out.len()
}
#[test]
fn particles_outside_the_pulled_back_frustum_make_no_quads() {
use crate::gfx::{Frustum, world_projection};
let view = Frustum::from_view_projection(world_projection(70.0, 16.0 / 9.0, 512.0));
let kept = [
[0.0, 0.0, -5.0], // straight ahead
[0.0, 0.0, 2.5], // behind the camera, inside the 3 blocks of offset
[0.0, 0.0, -300.0], // far, inside the far plane
];
let dropped = [
[0.0, 0.0, 10.0], // well behind the camera
[0.0, 0.0, 3.5], // just past the offset
[100.0, 0.0, -5.0], // far to the side
[0.0, 60.0, -5.0], // far above
[0.0, 0.0, -600.0], // beyond the far plane
];
let all: Vec<_> = kept.iter().chain(&dropped).copied().collect();
let engine = smoke_at(&all);
let only_kept = quad_vertices(&smoke_at(&kept), None);
assert!(only_kept > 0);
assert_eq!(quad_vertices(&engine, Some(&view)), only_kept);
// Without a view every particle is drawn, as before.
assert_eq!(
quad_vertices(&engine, None),
only_kept * all.len() / kept.len()
);
// `render` is the same as no view.
let mut regular = Vec::new();
engine.render(DVec3::ZERO, Quat::IDENTITY, 0.5, &|_| 0xf0, &mut regular);
assert_eq!(regular.len(), quad_vertices(&engine, None));
}
#[test]
fn the_culled_path_applies_the_same_frustum_test() {
use crate::gfx::{Frustum, world_projection};
let view = Frustum::from_view_projection(world_projection(70.0, 16.0 / 9.0, 512.0));
let engine = smoke_at(&[[0.0, 0.0, -5.0], [0.0, 0.0, 10.0]]);
let mut out = Vec::new();
// The disabled setting still keeps vanilla's always-on test.
engine.render_culled(
DVec3::ZERO,
Quat::IDENTITY,
0.5,
900.0,
false,
Some(&view),
|_, _| panic!("disabled culling must not query particle visibility"),
&|_| 0xf0,
&mut out,
);
assert_eq!(
out.len(),
quad_vertices(&smoke_at(&[[0.0, 0.0, -5.0]]), None)
);
}
#[test]
fn a_particle_is_tested_at_its_position_this_tick_not_an_interpolated_one() {
use crate::gfx::{Frustum, world_projection};
let view = Frustum::from_view_projection(world_projection(70.0, 16.0 / 9.0, 512.0));
// The frame is drawn half way (0.5) between `previous` and `position`.
// Ahead now, far behind a tick ago (half way: 12.5 behind, outside): kept.
let mut coming = smoke_at(&[[0.0, 0.0, -5.0]]);
coming.particles[0].previous = [0.0, 0.0, 30.0];
assert!(quad_vertices(&coming, None) > 0);
assert_eq!(
quad_vertices(&coming, Some(&view)),
quad_vertices(&coming, None)
);
// Behind now, ahead a tick ago (half way: 5 ahead, inside): dropped.
let mut going = smoke_at(&[[0.0, 0.0, 10.0]]);
going.particles[0].previous = [0.0, 0.0, -20.0];
assert_eq!(quad_vertices(&going, Some(&view)), 0);
}
#[test]
fn quads_face_the_rotation_they_are_given() {
let mut engine = ParticleEngine::new(Path::new(""), &HashMap::new(), &HashSet::new());
@@ -1,138 +0,0 @@
//! The camera's view frustum for particles: vanilla's always-on point test, and the section
//! cache behind the opt-in Particle Culling setting.
use super::{Particle, ParticleEngine, Vertex};
use glam::{DVec3, Quat, Vec3 as FVec3};
use std::array;
const PARTICLE_SECTION_CACHE_SIZE: usize = 128;
/// How far back, in blocks, the camera's frustum is pulled for the particle test (vanilla's
/// `Frustum.offset` in `ParticleEngine.extract`).
pub(super) const PARTICLE_FRUSTUM_OFFSET: f32 = 3.0;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(super) enum SectionFrustumResult {
Outside,
Intersects,
Inside,
}
#[derive(Clone, Copy)]
struct CachedSectionFrustum {
section: [i32; 3],
radius_quarters: i32,
result: SectionFrustumResult,
}
pub(super) struct ParticleSectionFrustumCache {
entries: [Option<CachedSectionFrustum>; PARTICLE_SECTION_CACHE_SIZE],
}
impl Default for ParticleSectionFrustumCache {
fn default() -> Self {
Self {
entries: [None; PARTICLE_SECTION_CACHE_SIZE],
}
}
}
impl ParticleSectionFrustumCache {
pub(super) fn result(
&mut self,
world: [f64; 3],
camera: DVec3,
radius: f64,
frustum: &crate::gfx::Frustum,
) -> SectionFrustumResult {
let Some(section) = world_section(world) else {
return SectionFrustumResult::Intersects;
};
if !radius.is_finite() || radius < 0.0 || radius * 4.0 > f64::from(i32::MAX) {
return SectionFrustumResult::Intersects;
}
let radius_quarters = (radius * 4.0).ceil() as i32;
let hash = (section[0] as u32).wrapping_mul(73_856_093)
^ (section[1] as u32).wrapping_mul(19_349_663)
^ (section[2] as u32).wrapping_mul(83_492_791)
^ (radius_quarters as u32).wrapping_mul(2_654_435_761);
let slot = hash as usize & (PARTICLE_SECTION_CACHE_SIZE - 1);
if let Some(entry) = self.entries[slot]
&& entry.section == section
&& entry.radius_quarters == radius_quarters
{
return entry.result;
}
let pad = f64::from(radius_quarters) * 0.25;
let camera = camera.to_array();
let min = array::from_fn(|axis| f64::from(section[axis]) * 16.0 - pad - camera[axis]);
let max = array::from_fn(|axis| min[axis] + 16.0 + 2.0 * pad);
let result = if min.into_iter().chain(max).any(|v| !v.is_finite()) {
SectionFrustumResult::Intersects
} else {
let min = FVec3::from_array(min.map(|v| v as f32));
let max = FVec3::from_array(max.map(|v| v as f32));
if !min.is_finite() || !max.is_finite() {
SectionFrustumResult::Intersects
} else if frustum.contains(min, max) {
SectionFrustumResult::Inside
} else if frustum.intersects(min, max) {
SectionFrustumResult::Intersects
} else {
SectionFrustumResult::Outside
}
};
self.entries[slot] = Some(CachedSectionFrustum {
section,
radius_quarters,
result,
});
result
}
}
fn world_section(position: [f64; 3]) -> Option<[i32; 3]> {
let mut block = [0; 3];
for axis in 0..3 {
let value = position[axis].floor();
if !value.is_finite() || value < f64::from(i32::MIN) || value > f64::from(i32::MAX) {
return None;
}
block[axis] = value as i32;
}
Some([block[0] >> 4, block[1] >> 4, block[2] >> 4])
}
/// Whether `QuadParticleGroup`'s test keeps `particle`: its position this tick (camera-relative, not
/// interpolated) is on or inside `view`, the camera's frustum pulled back [`PARTICLE_FRUSTUM_OFFSET`] blocks.
pub(super) fn in_view(view: &crate::gfx::Frustum, particle: &Particle, camera: DVec3) -> bool {
let at = DVec3::from_array(particle.position) - camera;
view.contains_point(at.as_vec3())
}
impl ParticleEngine {
/// [`Self::render`], keeping only the particles inside `view`, the camera's frustum pulled
/// back [`PARTICLE_FRUSTUM_OFFSET`] blocks (vanilla's `ParticleEngine.extract` and
/// `QuadParticleGroup`): the test runs whatever the Particle Culling setting says. With
/// `None`, every particle is drawn.
pub fn render_in_view(
&self,
camera: DVec3,
base: Quat,
partial: f32,
view: Option<&crate::gfx::Frustum>,
light_at: &dyn Fn([i32; 3]) -> u8,
out: &mut Vec<Vertex>,
) {
self.render_inner::<false>(
camera,
base,
partial,
0.0,
view,
&mut |_, _| false,
light_at,
out,
);
}
}
@@ -864,21 +864,11 @@ impl TextField {
self.set_highlight(m, pos);
}
/// `onClick`: the cursor where the mouse is (`findClickedPositionInText`).
/// `EditBox.onClick` / `MultiLineEditBox.onClick`: a double click selects
/// the word the pointer is in (`EditBox.selectWord`), any other click
/// places the caret there.
pub fn click(&mut self, m: &Measure, x: f64, extend: bool, double: bool) {
pub fn click(&mut self, m: &Measure, x: f64, extend: bool) {
let pos = (x.floor() as i32 - self.text_x()).min(self.inner_width());
let rest = sub(&self.value, self.display, chars(&self.value));
let at = self.display + m.plain(&rest, pos, false);
if double {
let start = crate::ui::word_position(&self.value, -1, at);
let end = crate::ui::word_position(&self.value, 1, at);
self.move_cursor_to(m, start, false);
self.move_cursor_to(m, end, true);
} else {
self.move_cursor_to(m, at, extend);
}
self.move_cursor_to(m, at, extend);
}
pub fn contains(&self, x: f64, y: f64) -> bool {
x >= self.x as f64
@@ -222,6 +222,11 @@ impl<P: Copy, S: Copy> Lines<P, S> {
}
self.y += style::GROUP_GAP;
}
/// A group of rows under its page's own name (`list`'s `page_name`), for pages named at run
/// time, such as a resource pack's config entries (`pack_options_ui`).
pub(crate) fn titled(&mut self, page: P, rows: Vec<S>) {
self.group(page, "", rows);
}
/// The lines and the content's height.
pub(crate) fn finish(self) -> (Vec<Line<P, S>>, f32) {
(self.lines, (self.y - style::GROUP_GAP).max(0.0))
@@ -347,7 +352,8 @@ pub(crate) fn plate(batch: &mut HudBatch, atlas: &HudAtlas, cols: &Columns, head
}
/// The list, clipped to its view: each group's panel, then its names and rows on it. `row`
/// draws a setting at its `y`; `page_name` names a page, in the player's language.
/// draws a setting at its `y`; `page_name` names a page, and a group without a name of its own
/// (`Lines::titled`), in the player's language.
pub(crate) fn list<P: Copy, S: Copy>(
batch: &mut HudBatch,
atlas: &HudAtlas,
@@ -380,6 +386,7 @@ pub(crate) fn list<P: Copy, S: Copy>(
}
let Some(setting) = line.setting else {
let (name, color, dy) = match line.group {
Some(("", _)) => (page_name(line.page), style::muted(), 3.0),
Some((name, _)) => (lang::get(name), style::muted(), 3.0),
None => (page_name(line.page), style::accent(), 4.0),
};
@@ -945,10 +952,22 @@ pub(crate) fn dock_note(
}
}
/// Done, Undo or Apply at the foot of the page list, registered for a controller. Its label
/// leaves `room` at its left for a controller's glyph: a button that declared its job gets one,
/// as vanilla's do (`ui::action_button`), which a half-width Undo or Apply needs.
/// Done or Undo at the foot of the page list.
pub(crate) fn foot_button(
batch: &mut HudBatch,
atlas: &HudAtlas,
rect: [f32; 4],
label: &Text,
cursor: (f32, f32),
flags: (bool, bool),
) {
foot_button_with_room(batch, atlas, rect, label, cursor, flags, 0.0);
}
/// A foot button whose label leaves `room` at its left for a controller's glyph: a button that
/// declared its job gets one, as vanilla's do (`ui::action_button`), which a half-width Undo or
/// Apply needs.
fn foot_button_with_room(
batch: &mut HudBatch,
atlas: &HudAtlas,
rect: [f32; 4],
@@ -2395,7 +2414,7 @@ impl<S: Screen + Default> Hosted for Shell<S> {
}
None => 0.0,
};
foot_button(batch, atlas, rect, &label, cursor, flags, room);
foot_button_with_room(batch, atlas, rect, &label, cursor, flags, room);
}
}
fn click(
+17 -11
View File
@@ -93,17 +93,18 @@ pub fn unpack(value: &str, signature: Signature, valid_uris: &[impl AsRef<str>])
signed: signature == Signature::Signed,
..empty.clone()
};
// Authlib's MinecraftServicesSessionService validates every URL in
// unpackTextures before returning any textures. A bad cape rejects the skin too.
// Each texture is loaded independently: an invalid or disallowed URL for one
// texture (cape, elytra) must not drop another (the skin). Vanilla's
// SkinManager works the same way.
for (kind, texture) in textures {
let Some(url) = texture.get("url").and_then(|u| u.as_str()) else {
return empty;
continue;
};
let allowed = valid_uris
.iter()
.any(|u| url.starts_with(&u.as_ref().replace("{textureId}", "")));
if !allowed {
return empty;
continue;
}
if kind == "SKIN" {
out.slim = texture
@@ -1387,9 +1388,10 @@ mod tests {
&super::TEXTURE_URIS,
);
assert_eq!(textures.slim, slim && !url.contains("evil"));
// Authlib rejects the whole payload if any URL is invalid,
// including the allowed cape when the skin is disallowed.
assert_eq!(textures.cape.is_some(), !url.contains("evil"));
// Textures are judged per URL (vanilla's SkinManager): the
// cape's URL is always allowed here, so it is kept even when
// the skin's URL is not.
assert!(textures.cape.is_some());
assert_eq!(parsed.skin.is_some(), !url.contains("evil"));
assert!(std::sync::Arc::ptr_eq(&parsed, &cache.get(&profile)));
}
@@ -1542,14 +1544,18 @@ mod tests {
assert!(t.slim);
assert!(!unpack(wide, Signature::Signed, &TEXTURE_URIS).slim);
}
/// Authlib's `MinecraftServicesSessionService` rejects the whole profile in
/// `unpackTextures` when any texture URL is outside the allowed origins.
/// `unpack` keeps each texture independently: a cape from another origin
/// must not drop the skin.
#[test]
fn unpack_rejects_the_skin_when_another_texture_is_rejected() {
fn unpack_keeps_the_skin_when_another_texture_is_rejected() {
use super::{Signature, TEXTURE_URIS, unpack};
let mixed = "eyJ0ZXh0dXJlcyI6IHsiU0tJTiI6IHsidXJsIjogImh0dHBzOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL3NraW4xIn0sICJDQVBFIjogeyJ1cmwiOiAiaHR0cHM6Ly9ldmlsLmV4YW1wbGUvdGV4dHVyZS9jYXBlMSJ9fX0=";
let t = unpack(mixed, Signature::Unsigned, &TEXTURE_URIS);
assert_eq!(t, super::Textures::default());
assert_eq!(
t.skin.as_deref(),
Some("https://textures.minecraft.net/texture/skin1")
);
assert_eq!(t.cape, None);
}
#[test]
fn profiles_parse_like_resolvable_profiles() {
+4 -4
View File
@@ -478,9 +478,9 @@ impl Sprites {
let metadata = match horizon_core::prepared_files::read_to_string(
&path.with_extension("png.mcmeta"),
) {
Ok(text) => Some(crate::packs::first_json::<
Ok(text) => Some(serde_json::from_str::<
BTreeMap<String, Box<serde_json::value::RawValue>>,
>(text.as_bytes())?),
>(&text)?),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => None,
Err(error) => return Err(error.into()),
};
@@ -589,9 +589,9 @@ impl Sprites {
let metadata = match horizon_core::prepared_files::read_to_string(
&path.with_extension("png.mcmeta"),
) {
Ok(text) => Some(crate::packs::first_json::<
Ok(text) => Some(serde_json::from_str::<
BTreeMap<String, Box<serde_json::value::RawValue>>,
>(text.as_bytes())?),
>(&text)?),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => None,
Err(error) => return Err(error.into()),
};
@@ -1438,7 +1438,7 @@ impl Streaming {
let entities = std::mem::take(&mut chunk.entities);
world.entities_pending.insert((chunk.x, chunk.z));
if !entities.is_empty() {
world.queue_entity_nbt((chunk.x, chunk.z), entities);
world.loaded_entities.push(((chunk.x, chunk.z), entities));
}
self.generated_total += 1;
// A chunk saved with its light needs no light job; its unlit
@@ -1779,7 +1779,10 @@ impl Streaming {
> r4 * r4)
&& !ranges.in_extra(x, z, 4)
&& !ranges.in_band(x, z, 4)
&& !ranges.forced_within(x, z, FORCED_TERRAIN_RING)
&& !ranges.forced_chunks().any(|f| {
(x - f.0).abs() <= FORCED_TERRAIN_RING
&& (z - f.1).abs() <= FORCED_TERRAIN_RING
})
})
.map(|(k, _)| *k)
.collect();
@@ -6,20 +6,16 @@ use std::collections::HashSet;
/// `Streaming::forced` and `mod_forced` as the Chebyshev distance from each column within
/// `REACH` of one to the nearest: `Ranges::in_main_range` answers by one lookup instead of going
/// through every forced chunk (it is asked for every column, several times a tick). Past `MOST`
/// forced chunks, and for a reach past `REACH`, their tiles answer.
/// through every forced chunk (it is asked for every column, several times a tick).
pub(super) struct ForcedCover {
forced: HashSet<(i32, i32)>,
mod_forced: HashSet<(i32, i32)>,
/// None past `MOST`.
near: Option<FxHashMap<(i32, i32), u8>>,
tiles: Tiles,
near: FxHashMap<(i32, i32), u8>,
}
impl ForcedCover {
/// The widest ring `in_main_range` asks of a forced chunk (margins 1 to 4).
const REACH: i32 = FORCED_TERRAIN_RING + 1;
/// Past this many forced chunks the distance map is not made (it holds up to
/// `(2 * REACH + 1)^2` entries a forced chunk): the tiles answer.
/// Past this many forced chunks the cover is not made: the scan answers.
const MOST: usize = 4096;
pub(super) fn refresh(
cover: &mut Option<Self>,
@@ -32,85 +28,33 @@ impl ForcedCover {
{
return;
}
let near = (forced.len() + mod_forced.len() <= Self::MOST).then(|| {
let mut near = FxHashMap::default();
for &(fx, fz) in forced.iter().chain(mod_forced) {
for dx in -Self::REACH..=Self::REACH {
for dz in -Self::REACH..=Self::REACH {
let d = dx.abs().max(dz.abs()) as u8;
near.entry((fx + dx, fz + dz))
.and_modify(|e: &mut u8| *e = (*e).min(d))
.or_insert(d);
}
if forced.len() + mod_forced.len() > Self::MOST {
*cover = None;
return;
}
let mut near = FxHashMap::default();
for &(fx, fz) in forced.iter().chain(mod_forced) {
for dx in -Self::REACH..=Self::REACH {
for dz in -Self::REACH..=Self::REACH {
let d = dx.abs().max(dz.abs()) as u8;
near.entry((fx + dx, fz + dz))
.and_modify(|e: &mut u8| *e = (*e).min(d))
.or_insert(d);
}
}
near
});
}
*cover = Some(Self {
forced: forced.clone(),
mod_forced: mod_forced.clone(),
near,
tiles: Tiles::new(forced.iter().chain(mod_forced)),
});
}
/// Whether a forced chunk lies within `reach` of `(x, z)` (Chebyshev).
pub(super) fn within(&self, x: i32, z: i32, reach: i32) -> bool {
match &self.near {
Some(near) if reach <= Self::REACH => {
near.get(&(x, z)).is_some_and(|&d| i32::from(d) <= reach)
}
_ => self.tiles.within(x, z, reach),
}
}
}
/// The forced chunks as bits, 8 by 8 columns a word: `(x, z)`'s bit is `(z & 7) * 8 + (x & 7)`
/// of the word at `(x >> 3, z >> 3)`. A question reads only the words its square overlaps (four
/// at most for a reach up to 4, nine up to 8), however many chunks are forced. It holds one word
/// and its key for each tile with a forced chunk in it.
struct Tiles(FxHashMap<(i32, i32), u64>);
impl Tiles {
fn new<'a>(chunks: impl Iterator<Item = &'a (i32, i32)>) -> Self {
let mut tiles = FxHashMap::default();
for &(x, z) in chunks {
*tiles.entry((x >> 3, z >> 3)).or_insert(0) |= 1u64 << ((z & 7) * 8 + (x & 7));
}
Self(tiles)
}
/// Whether a chunk's bit is set within `reach` of `(x, z)` (Chebyshev).
fn within(&self, x: i32, z: i32, reach: i32) -> bool {
if reach < 0 {
return false;
}
let (x0, x1) = (x.saturating_sub(reach), x.saturating_add(reach));
let (z0, z1) = (z.saturating_sub(reach), z.saturating_add(reach));
// The square's bits in the tile at (tx, tz).
let hit = |(tx, tz): (i32, i32), bits: u64| {
let (bx, bz) = (i64::from(tx) * 8, i64::from(tz) * 8);
let lx0 = (i64::from(x0) - bx).max(0);
let lx1 = (i64::from(x1) - bx).min(7);
let lz0 = (i64::from(z0) - bz).max(0);
let lz1 = (i64::from(z1) - bz).min(7);
if lx0 > lx1 || lz0 > lz1 {
return false;
}
// Columns lx0..=lx1 of one row, copied to every row, then rows lz0..=lz1.
let row = (0xFFu64 >> (7 - (lx1 - lx0))) << lx0;
let rows = (u64::MAX >> (8 * (7 - (lz1 - lz0)))) << (8 * lz0);
bits & row.wrapping_mul(0x0101_0101_0101_0101) & rows != 0
};
let (tx0, tx1, tz0, tz1) = (x0 >> 3, x1 >> 3, z0 >> 3, z1 >> 3);
let overlapped = (i64::from(tx1 - tx0) + 1) * (i64::from(tz1 - tz0) + 1);
// A square wider than the tiles held (a far reach): go through the tiles instead.
if overlapped > self.0.len() as i64 {
return self.0.iter().any(|(&t, &bits)| hit(t, bits));
}
(tz0..=tz1).any(|tz| {
(tx0..=tx1).any(|tx| {
self.0
.get(&(tx, tz))
.is_some_and(|&bits| hit((tx, tz), bits))
})
/// Whether a forced chunk lies within `reach` of `(x, z)`, or `None` past `REACH`.
pub(super) fn within(&self, x: i32, z: i32, reach: i32) -> Option<bool> {
(reach <= Self::REACH).then(|| {
self.near
.get(&(x, z))
.is_some_and(|&d| i32::from(d) <= reach)
})
}
}
@@ -139,13 +83,8 @@ impl Ranges<'_> {
3 => FORCED_TERRAIN_RING,
_ => margin + 1,
};
self.forced_within(x, z, reach)
}
/// Whether a forced chunk lies within `reach` of `(x, z)` (Chebyshev): from the cover while
/// `update` runs, else by a scan of every forced chunk.
pub(super) fn forced_within(&self, x: i32, z: i32, reach: i32) -> bool {
if let Some(cover) = self.forced_cover {
return cover.within(x, z, reach);
if let Some(hit) = self.forced_cover.and_then(|c| c.within(x, z, reach)) {
return hit;
}
self.forced_chunks()
.any(|f| (x - f.0).abs() <= reach && (z - f.1).abs() <= reach)
@@ -213,194 +152,14 @@ mod tests {
}
}
/// Too many forced chunks for a map: none is made, and the tiles answer.
/// Too many forced chunks for a map: none is made, and the scan answers.
#[test]
fn past_the_most_no_map_is_made() {
let forced: HashSet<(i32, i32)> = (0..=ForcedCover::MOST as i32).map(|x| (x, 0)).collect();
let mut cover = None;
ForcedCover::refresh(&mut cover, &HashSet::new(), &HashSet::from([(0, 0)]));
assert!(cover.as_ref().is_some_and(|c| c.near.is_some()));
assert!(cover.is_some());
ForcedCover::refresh(&mut cover, &forced, &HashSet::new());
let made = cover
.as_ref()
.expect("a cover is made however many are forced");
assert!(made.near.is_none());
assert!(made.within(-3, 3, 3) && !made.within(-3, 4, 3));
}
/// Forced chunks in a disc, in clusters and scattered: `n` of them (the clusters a few more).
fn sets(seed: &mut u64, n: usize) -> [HashSet<(i32, i32)>; 3] {
let r = (n as f64 / std::f64::consts::PI).sqrt().ceil() as i32;
let disc: HashSet<_> = (-r..=r)
.flat_map(|z| (-r..=r).map(move |x| (x, z)))
.filter(|&(x, z)| x * x + z * z <= r * r)
.take(n)
.collect();
let mut clusters = HashSet::new();
while clusters.len() < n {
let (cx, cz) = chunks(seed, 1, 400).into_iter().next().unwrap();
clusters.extend(
chunks(seed, 64, 6)
.into_iter()
.map(|(x, z)| (cx + x, cz + z)),
);
}
let spread = (n as f64).sqrt() as i32 * 6;
let mut scattered = HashSet::new();
while scattered.len() < n {
scattered.extend(chunks(seed, n - scattered.len(), spread));
}
[disc, clusters, scattered]
}
/// Well past `MOST`, and either side of it, the cover answers every reach as the scan of
/// every forced chunk does: around forced chunks, between them, on tile edges and far off,
/// with some held by both a `/forceload` and a mod's ticket.
#[test]
fn past_the_most_the_tiles_answer_as_the_scan() {
let mut seed = 0x9E37_79B9_7F4A_7C15u64;
let m = ForcedCover::MOST;
// Some held both ways past the boundary, none at it (a chunk held both ways counts twice
// towards `MOST`, as `refresh` counts them).
for (n, both) in [(m, false), (m + 1, false), (6000, true), (20_000, true)] {
for (kind, all) in sets(&mut seed, n).into_iter().enumerate() {
// Every third chunk a mod's ticket; with `both`, every fifth held both ways.
let (mut forced, mut mod_forced) = (HashSet::new(), HashSet::new());
for (i, &c) in all.iter().enumerate() {
if i % 3 == 0 || (both && i % 5 == 0) {
mod_forced.insert(c);
}
if i % 3 != 0 {
forced.insert(c);
}
}
let mut cover = None;
ForcedCover::refresh(&mut cover, &forced, &mod_forced);
let made = cover.as_ref().unwrap();
let held = forced.len() + mod_forced.len();
assert_eq!(made.near.is_some(), held <= m);
let ranges = |forced_cover| Ranges {
center: (10_000_000, 10_000_000),
radius: 2,
extra: &[],
forced: &forced,
mod_forced: &mod_forced,
cover: None,
forced_cover,
band: None,
};
let (scan, map) = (ranges(None), ranges(Some(made)));
// The scan goes through every forced chunk: fewer columns for more of them.
let near: Vec<_> = all.iter().step_by(all.len() / 40).copied().collect();
let offsets = chunks(&mut seed, 6, 12);
let far = chunks(&mut seed, 12, 3000);
let columns = near
.iter()
.flat_map(|&(x, z)| offsets.iter().map(move |&(dx, dz)| (x + dx, z + dz)))
.chain(far);
for (x, z) in columns {
for reach in [-1, 0, 1, 2, 3, 4, 5, 6, 8, 11, 40] {
assert_eq!(
map.forced_within(x, z, reach),
scan.forced_within(x, z, reach),
"{n} forced, set {kind}, ({x}, {z}) reach {reach}"
);
}
for margin in 1..=4 {
assert_eq!(
map.in_main_range(x, z, margin),
scan.in_main_range(x, z, margin)
);
}
}
}
}
}
/// Each tile's bits answer for every square that overlaps it in part: corners, edges and
/// across negative coordinates.
#[test]
fn a_tiles_edges_answer_as_the_scan() {
let mut seed = 0xD1B5_4A32_D192_ED03u64;
for _ in 0..200 {
let set = chunks(&mut seed, 3, 9);
let tiles = Tiles::new(set.iter());
for z in -14..=14 {
for x in -14..=14 {
for reach in 0..=9 {
let scan = set
.iter()
.any(|f| (x - f.0).abs() <= reach && (z - f.1).abs() <= reach);
assert_eq!(
tiles.within(x, z, reach),
scan,
"{set:?} ({x}, {z}) {reach}"
);
}
}
}
}
}
/// What a question and the cover cost by how many chunks are forced: run with
/// `cargo test --release -p horizon-client-render forced_cover_cost -- --ignored --nocapture`.
#[test]
#[ignore = "timings; run with --release --ignored --nocapture"]
fn forced_cover_cost() {
let mut seed = 0x2545_F491_4F6C_DD1Du64;
for n in [1000, 4000, 4097, 6000, 20_000] {
for (kind, forced) in sets(&mut seed, n).into_iter().enumerate() {
let none = HashSet::new();
let started = std::time::Instant::now();
let mut cover = None;
ForcedCover::refresh(&mut cover, &forced, &none);
let made_in = started.elapsed();
let made = cover.as_ref().unwrap();
let ranges = |forced_cover| Ranges {
center: (10_000_000, 10_000_000),
radius: 2,
extra: &[],
forced: &forced,
mod_forced: &none,
cover: None,
forced_cover,
band: None,
};
let spread = forced
.iter()
.map(|f| f.0.abs().max(f.1.abs()))
.max()
.unwrap()
+ 20;
let columns = chunks(&mut seed, 200_000, spread);
let time = |r: &Ranges, take: usize| {
let started = std::time::Instant::now();
let mut hits = 0usize;
for &(x, z) in columns.iter().take(take) {
for margin in 1..=4 {
hits += usize::from(r.in_main_range(x, z, margin));
}
}
(
started.elapsed().as_nanos() as f64 / (take * 4) as f64,
hits,
)
};
let (cover_ns, _) = time(&ranges(Some(made)), columns.len());
let (scan_ns, _) = time(&ranges(None), 2000);
let bytes = made.tiles.0.capacity() * (16 + 1)
+ made.near.as_ref().map_or(0, |m| m.capacity() * (12 + 1));
println!(
"{n:>6} forced ({}): cover {cover_ns:6.1} ns a question, scan {scan_ns:8.0} ns; \
made in {made_in:?}, {} tiles, distance map {}, ~{} KiB",
["disc", "clusters", "scattered"][kind],
made.tiles.0.len(),
made.near
.as_ref()
.map_or("none".to_string(), |m| m.len().to_string()),
bytes / 1024
);
}
}
assert!(cover.is_none());
}
}
@@ -11,7 +11,6 @@
//! D-pad, a button, or a look gesture on the world) and keeps it until it
//! lifts, so moving, looking and pressing never take each other's fingers.
pub mod aim;
mod draw;
pub mod layout;
pub use aim::{
attack_indicator, camera_delta, hotbar_slot, item_places_entity_on_tap, item_uses_on_tap,
@@ -82,11 +81,6 @@ pub struct TouchControls {
pub vertical_movement: bool,
pub swimming: bool,
pub mounted: bool,
/// The player is sneaking: the sneak button shows held.
pub sneaking: bool,
/// How far the block under a world hold is broken (0..1), drawn in the
/// touch marker.
pub break_progress: f32,
/// A long hold on the world uses the held item instead of mining. Read when
/// a finger lands, so a change mid-hold (the last apple eaten) can't turn
/// eating into mining.
@@ -1,465 +0,0 @@
// Adapted from Starling (https://github.com/starling-client/starling, `android` branch at
// 150a414b09a1, `crates/horizon-client-render/src/touch.rs`), written by Vasysik and the
// Starling contributors. Copyright (c) 2026 Ludovic Marie and the Horizon contributors, under the
// same MIT license as Horizon (LICENSE at the repository root).
//! Drawing the touch controls on the HUD, in GUI pixels. Buttons use the
//! resource pack's own button sprite (`widget/button`, highlighted while held)
//! with a short label; the joystick, the D-pad and the tap marker are plain
//! shapes. No art of its own ships with the game.
use super::{Control, Mode, Placement, Role, TouchControls, layout};
use crate::gamepad::{Button, PadState};
use crate::hud::{HudAtlas, HudBatch, rgba};
use crate::lang;
const BUTTON: &str = "gui/sprites/widget/button";
const BUTTON_HELD: &str = "gui/sprites/widget/button_highlighted";
impl TouchControls {
/// Draws every visible control, then the tap marker in the tap schemes.
pub fn draw(&self, b: &mut HudBatch, a: &HudAtlas) {
let state = self.state();
for control in Control::ALL {
if !self.visible(control) {
continue;
}
let p = self.placement(control);
let color = rgba(255, 255, 255, alpha(p.opacity));
if control == Control::Move {
self.draw_move(b, a, p, &state, color);
continue;
}
let bounds = square(b, p.center, p.size);
let rect = p.rect(self.aspect());
let pressed = self.held(control, &state)
|| self
.fingers
.values()
.any(|(_, point)| layout::contains(rect, *point));
button(b, a, bounds, &self.label(control), pressed, color);
}
if let Some(point) = self.pointer() {
let center = [point[0] * b.width, point[1] * b.height];
let radius = self.settings.circle_size / 2.0;
ring(b, a, center, radius + 0.7, rgba(0, 0, 0, 110));
ring(b, a, center, radius, rgba(255, 255, 255, 210));
// Mining fills the circle outwards from its centre.
let inner = mining_radius(radius, self.break_progress);
if inner > 0.0 {
disc(b, a, center, inner, rgba(255, 255, 255, 90));
ring(b, a, center, inner, rgba(255, 255, 255, 220));
}
}
}
/// Whether a control shows as held: its button is down, or it latched.
fn held(&self, control: Control, state: &PadState) -> bool {
if control == Control::Sneak && self.sneaking {
return true;
}
Self::button(control).is_some_and(|button| match button {
Button::LeftTrigger => state.triggers[0] > 0.0,
Button::RightTrigger => state.triggers[1] > 0.0,
_ => state.held(button),
})
}
/// The label a control's button shows, in the player's language. Key
/// names and symbols ("F3", "II") read the same in every language.
fn label(&self, control: Control) -> String {
let vertical = self.swimming || self.vertical_movement;
let key = match control {
Control::Move => return String::new(),
Control::Pause => return "II".to_owned(),
Control::Inventory => return "...".to_owned(),
Control::Debug => return "F3".to_owned(),
Control::Perspective => return "F5".to_owned(),
Control::Sprint => "horizon.touch.sprint",
Control::Jump if vertical => "horizon.touch.up",
Control::Jump => "horizon.touch.jump",
Control::Sneak if vertical => "horizon.touch.down",
Control::Sneak if self.mounted => "horizon.touch.dismount",
Control::Sneak => "horizon.touch.sneak",
Control::Attack => "horizon.touch.attack",
Control::Use => "horizon.touch.use",
Control::Chat => "horizon.touch.chat",
Control::Settings => "horizon.touch.settings",
Control::Offhand => "horizon.touch.swap",
Control::Shield => "horizon.touch.shield",
};
lang::get(key)
}
/// The joystick (a rim and a knob) or the D-pad (four arrow buttons).
fn draw_move(
&self,
b: &mut HudBatch,
a: &HudAtlas,
p: Placement,
state: &PadState,
color: u32,
) {
let anchor = self.fingers.values().find_map(|(role, _)| match role {
Role::Move(anchor) => Some(*anchor),
_ => None,
});
let center = match anchor {
Some(anchor) if self.dynamic_joystick() => anchor,
// A dynamic joystick only shows while a finger holds it.
None if self.dynamic_joystick() => return,
_ => p.center,
};
let [x, y, size, _] = square(b, center, p.size);
if self.settings.mode == Mode::Dpad {
let cell = size / 3.0;
for ([dx, dy], label, pressed) in dpad(state.left) {
let bounds = [x + cell * dx, y + cell * dy, cell, cell];
button(b, a, bounds, label, pressed, color);
}
return;
}
let middle = [x + size / 2.0, y + size / 2.0];
let [r, g, blue, opacity] = color.to_le_bytes();
ring(b, a, middle, size / 2.0, color);
disc(b, a, middle, size / 2.0, rgba(0, 0, 0, opacity / 3));
let knob = knob(middle, state.left, size);
disc(b, a, knob, size * 0.17, rgba(r, g, blue, opacity / 2));
ring(b, a, knob, size * 0.17, color);
}
}
/// The D-pad's arrows: each one's cell in a 3x3 grid, its label and whether
/// the stick (`left`, up positive) presses it.
fn dpad(left: [f32; 2]) -> [([f32; 2], &'static str, bool); 4] {
[
([1.0, 0.0], "^", left[1] > 0.2),
([0.0, 1.0], "<", left[0] < -0.2),
([2.0, 1.0], ">", left[0] > 0.2),
([1.0, 2.0], "v", left[1] < -0.2),
]
}
/// Where the joystick's knob sits: the stick is up positive, the screen down.
fn knob(middle: [f32; 2], left: [f32; 2], size: f32) -> [f32; 2] {
[
middle[0] + left[0] * size / 4.0,
middle[1] - left[1] * size / 4.0,
]
}
/// A placement's square in GUI pixels, `[x, y, size, size]`.
fn square(b: &HudBatch, center: [f32; 2], size: f32) -> [f32; 4] {
let size = size * b.height;
[
center[0] * b.width - size / 2.0,
center[1] * b.height - size / 2.0,
size,
size,
]
}
fn alpha(opacity: f32) -> u8 {
(opacity.clamp(0.0, 1.0) * 255.0).round() as u8
}
/// A labelled button: the pack's button sprite, or a plain frame when the
/// pack has none. A held button darkens and its label drops a pixel.
fn button(
b: &mut HudBatch,
a: &HudAtlas,
bounds: [f32; 4],
label: &str,
pressed: bool,
color: u32,
) {
let [x, y, w, h] = bounds;
let [r, g, blue, opacity] = color.to_le_bytes();
if a.sprites.contains_key(BUTTON) {
let sprite = if pressed && a.sprites.contains_key(BUTTON_HELD) {
BUTTON_HELD
} else {
BUTTON
};
crate::ui::nine_slice(b, a, sprite, x, y, w, h, color);
} else {
let fill = if pressed { 150 } else { 90 };
b.fill(
a,
x,
y,
w,
h,
rgba(0, 0, 0, (u16::from(opacity) * fill / 255) as u8),
);
for edge in [
[x, y, w, 1.0],
[x, y + h - 1.0, w, 1.0],
[x, y, 1.0, h],
[x + w - 1.0, y, 1.0, h],
] {
b.fill(a, edge[0], edge[1], edge[2], edge[3], color);
}
}
if label.is_empty() {
return;
}
let text = if pressed {
rgba(r / 2 + 127, g / 2 + 127, blue / 2, opacity)
} else {
color
};
let drop = if pressed { (h / 18.0).min(2.0) } else { 0.0 };
let width = HudBatch::text_width(a, label);
let start = b.vertices.len();
b.text(
a,
label,
x + (w - width) / 2.0,
y + (h - 8.0) / 2.0 + drop,
text,
true,
);
// Shrink a long label to fit, never grow a short one: the width leaves 3
// pixels each side, and the height cap keeps the 8-pixel line inside the
// same margin, never above full size.
let fit_width = (w - 6.0).max(1.0) / width.max(1.0);
let height_cap = ((h - 6.0).max(1.0) / 8.0).min(1.0);
let scale = fit_width.min(height_cap);
b.scale_since(start, x + w / 2.0, y + h / 2.0 + drop, scale, scale);
}
/// How far the mining disc reaches inside a marker of `radius`, by progress.
fn mining_radius(radius: f32, progress: f32) -> f32 {
if progress.is_finite() {
(radius - 1.5).max(0.0) * progress.clamp(0.0, 1.0)
} else {
0.0
}
}
/// 65 points round the unit circle, the last one equal to the first.
fn circle_points() -> &'static [[f32; 2]; 65] {
static POINTS: std::sync::OnceLock<[[f32; 2]; 65]> = std::sync::OnceLock::new();
POINTS.get_or_init(|| {
std::array::from_fn(|i| {
let angle = i as f32 / 64.0 * std::f32::consts::TAU;
[angle.cos(), angle.sin()]
})
})
}
/// A 1.4-pixel circle line, one quad per segment so nothing blends twice.
fn ring(b: &mut HudBatch, a: &HudAtlas, center: [f32; 2], radius: f32, color: u32) {
let at = |p: [f32; 2], r: f32| [center[0] + p[0] * r, center[1] + p[1] * r];
let (outer, inner) = (radius + 0.7, (radius - 0.7).max(0.0));
for s in circle_points().windows(2) {
b.fill_quad(
a,
[
at(s[0], outer),
at(s[1], outer),
at(s[1], inner),
at(s[0], inner),
],
color,
);
}
}
/// A filled circle.
fn disc(b: &mut HudBatch, a: &HudAtlas, center: [f32; 2], radius: f32, color: u32) {
let at = |p: [f32; 2]| [center[0] + p[0] * radius, center[1] + p[1] * radius];
for s in circle_points().windows(2) {
b.fill_quad(a, [center, at(s[0]), at(s[1]), center], color);
}
}
#[cfg(test)]
mod tests {
use super::*;
fn atlas() -> HudAtlas {
HudAtlas::build(std::path::Path::new("/nonexistent/horizon-touch-draw")).unwrap()
}
fn vertices(t: &TouchControls, a: &HudAtlas) -> usize {
let mut b = HudBatch::new([1920, 1080]);
t.draw(&mut b, a);
b.vertices.len()
}
#[test]
fn mining_disc_grows_outwards_within_the_marker() {
assert_eq!(mining_radius(16.0, 0.0), 0.0);
assert_eq!(mining_radius(16.0, 0.5), 7.25);
assert_eq!(mining_radius(16.0, 1.0), 14.5);
assert_eq!(mining_radius(16.0, 2.0), 14.5);
assert_eq!(mining_radius(16.0, -1.0), 0.0);
assert_eq!(mining_radius(16.0, f32::NAN), 0.0);
}
#[test]
fn hidden_controls_draw_nothing() {
let a = atlas();
let mut t = TouchControls::default();
assert!(vertices(&t, &a) > 0);
t.settings.button_visibility = [layout::HIDDEN; layout::CONTROLS];
assert_eq!(vertices(&t, &a), 0);
}
#[test]
fn a_dynamic_joystick_shows_only_while_held() {
let a = atlas();
let mut t = TouchControls::default();
t.settings.dynamic_joystick = true;
let idle = vertices(&t, &a);
t.update(1, [0.1, 0.6], true, false);
assert!(vertices(&t, &a) > idle);
t.update(1, [0.1, 0.6], false, true);
assert_eq!(vertices(&t, &a), idle);
}
#[test]
fn the_marker_shows_in_tap_schemes_and_fills_while_mining() {
let a = atlas();
let mut t = TouchControls::default();
let idle = vertices(&t, &a);
t.update(1, [0.6, 0.4], true, false);
assert_eq!(vertices(&t, &a), idle, "no marker with a crosshair");
t.clear();
t.settings.mode = Mode::Tap;
let idle = vertices(&t, &a);
t.update(1, [0.6, 0.4], true, false);
let marker = vertices(&t, &a);
assert!(marker > idle);
t.break_progress = 0.5;
assert!(vertices(&t, &a) > marker);
}
fn english<R>(f: impl FnOnce() -> R) -> R {
let (result, missed) = lang::scoped(lang::Language::load(&[], "en_us"), f);
assert!(missed.is_empty(), "no English text for {missed:?}");
result
}
#[test]
fn labels_and_held_buttons_follow_the_player() {
let mut t = TouchControls::default();
let all = |t: &TouchControls| english(|| Control::ALL.map(|c| t.label(c)));
assert_eq!(all(&t)[..3], ["", "Sprint", "Jump"]);
assert!(all(&t).iter().all(|l| !l.starts_with("horizon.")));
assert_eq!(t.label(Control::Debug), "F3");
t.swimming = true;
assert_eq!(english(|| t.label(Control::Jump)), "Up");
assert_eq!(english(|| t.label(Control::Sneak)), "Down");
t.swimming = false;
t.mounted = true;
assert_eq!(english(|| t.label(Control::Sneak)), "Dismount");
let state = t.state();
assert!(!t.held(Control::Sneak, &state));
t.sneaking = true;
assert!(t.held(Control::Sneak, &state));
t.update(1, t.placement(Control::Attack).center, true, false);
assert!(t.held(Control::Attack, &t.state()));
assert!(!t.held(Control::Use, &t.state()));
}
#[test]
fn colours_split_into_rgba_in_order() {
let half = rgba(255, 255, 255, alpha(0.5));
assert_eq!(half.to_le_bytes(), [255, 255, 255, 128]);
assert_eq!(rgba(10, 20, 30, 40).to_le_bytes(), [10, 20, 30, 40]);
}
/// One button drawn alone, as `button` draws it in `draw`.
fn one(a: &HudAtlas, bounds: [f32; 4], label: &str, pressed: bool) -> HudBatch {
let mut b = HudBatch::new([1920, 1080]);
button(&mut b, a, bounds, label, pressed, rgba(255, 255, 255, 128));
b
}
#[test]
fn a_held_button_uses_the_packs_highlighted_sprite() {
let mut a = atlas();
let rect = |u0: f32| crate::hud::Rect {
u0,
v0: 0.0,
u1: u0 + 0.1,
v1: 0.1,
w: 200,
h: 20,
};
a.sprites.insert(BUTTON.to_owned(), rect(0.2));
a.sprites.insert(BUTTON_HELD.to_owned(), rect(0.5));
let uses = |b: &HudBatch, u0: f32| {
b.vertices
.iter()
.any(|v| (u0..=u0 + 0.1).contains(&v.uv[0]) && v.uv[1] <= 0.1)
};
let idle = one(&a, [0.0, 0.0, 60.0, 20.0], "", false);
assert!(uses(&idle, 0.2) && !uses(&idle, 0.5));
let held = one(&a, [0.0, 0.0, 60.0, 20.0], "", true);
assert!(uses(&held, 0.5) && !uses(&held, 0.2));
assert!(
held.vertices
.iter()
.all(|v| v.color == rgba(255, 255, 255, 128))
);
}
#[test]
fn without_the_sprite_a_plain_frame_darkens_while_held() {
let a = atlas();
assert!(!a.sprites.contains_key(BUTTON));
let colours = |pressed| {
let b = one(&a, [10.0, 10.0, 60.0, 20.0], "", pressed);
b.vertices.iter().map(|v| v.color).collect::<Vec<_>>()
};
let (idle, held) = (colours(false), colours(true));
let mut fill = HudBatch::new([1920, 1080]);
fill.fill(&a, 0.0, 0.0, 1.0, 1.0, 0);
let quad = fill.vertices.len();
// The backdrop, then the four one-pixel edges in the button's colour.
assert_eq!(idle.len(), 5 * quad);
assert!(idle[..quad].iter().all(|&c| c == rgba(0, 0, 0, 45)));
assert!(held[..quad].iter().all(|&c| c == rgba(0, 0, 0, 75)));
assert!(idle[quad..].iter().all(|&c| c == rgba(255, 255, 255, 128)));
}
#[test]
fn a_long_label_shrinks_to_fit_and_a_short_one_keeps_its_size() {
let a = atlas();
let frame = one(&a, [0.0, 0.0, 40.0, 20.0], "", false).vertices.len();
let span = |label: &str| {
let b = one(&a, [0.0, 0.0, 40.0, 20.0], label, false);
assert!(b.vertices.len() > frame, "{label} drew no text");
let xs = b.vertices[frame..].iter().map(|v| v.pos[0]);
let (lo, hi) = xs.fold((f32::MAX, f32::MIN), |(lo, hi), x| (lo.min(x), hi.max(x)));
(lo, hi)
};
let long = "a label much wider than its button";
assert!(HudBatch::text_width(&a, long) > 40.0);
let (lo, hi) = span(long);
assert!(lo >= 3.0 - 1e-3 && hi <= 37.0 + 1e-3, "{lo}..{hi}");
let width = HudBatch::text_width(&a, "Up");
let (lo, hi) = span("Up");
assert!(hi - lo >= width - 1e-3, "{} < {width}", hi - lo);
}
#[test]
fn the_dpad_and_knob_follow_the_stick_up_positive() {
let only = |left: [f32; 2]| {
let on: Vec<_> = dpad(left).into_iter().filter(|p| p.2).collect();
assert_eq!(on.len(), 1, "{left:?}");
(on[0].0, on[0].1)
};
assert_eq!(only([0.0, 0.5]), ([1.0, 0.0], "^"));
assert_eq!(only([0.0, -0.5]), ([1.0, 2.0], "v"));
assert_eq!(only([-0.5, 0.0]), ([0.0, 1.0], "<"));
assert_eq!(only([0.5, 0.0]), ([2.0, 1.0], ">"));
assert!(dpad([0.1, -0.1]).iter().all(|p| !p.2));
// Stick up draws the knob above the middle, on screen.
assert_eq!(knob([50.0, 50.0], [0.0, 1.0], 40.0), [50.0, 40.0]);
assert_eq!(knob([50.0, 50.0], [1.0, 0.0], 40.0), [60.0, 50.0]);
}
}
@@ -193,8 +193,6 @@ pub struct Settings {
pub dynamic_area_y: f32,
/// Scales every control without changing the saved sizes (0.5-2).
pub button_scale: f32,
/// The touch marker's diameter in GUI pixels (16-64).
pub circle_size: f32,
}
impl Default for Settings {
@@ -241,7 +239,6 @@ impl Default for Settings {
dynamic_area_x: 0.25,
dynamic_area_y: 1.0,
button_scale: 1.0,
circle_size: 32.0,
}
}
}
@@ -285,7 +282,6 @@ impl Settings {
*v = finite_or(*v, 1.0).clamp(0.1, 3.0);
}
self.button_scale = finite_or(self.button_scale, 1.0).clamp(0.5, 2.0);
self.circle_size = finite_or(self.circle_size, 32.0).clamp(16.0, 64.0);
self.dynamic_area_x = finite_or(self.dynamic_area_x, 0.25).clamp(0.0, 1.0);
self.dynamic_area_y = finite_or(self.dynamic_area_y, 1.0).clamp(0.0, 1.0);
}
@@ -478,17 +474,6 @@ mod tests {
assert_eq!(s.button_scale, 2.0);
}
#[test]
fn the_marker_size_defaults_and_stays_in_range() {
let mut s: Settings = serde_json::from_str(r#"{"mode":"tap"}"#).unwrap();
assert_eq!(s.circle_size, 32.0);
for (bad, fixed) in [(f32::NAN, 32.0), (1.0, 16.0), (500.0, 64.0)] {
s.circle_size = bad;
s.sanitize();
assert_eq!(s.circle_size, fixed);
}
}
#[test]
fn left_hands_mirror_and_dpad_can_swap_jump_and_sneak() {
let mut s = Settings::default();
+1 -23
View File
@@ -104,7 +104,7 @@ pub fn read_metadata(root: &Path) -> UiMetadata {
let Ok(text) = horizon_core::prepared_files::read_to_string(&p) else {
continue;
};
let Some(nine_slice) = crate::packs::first_json(text.as_bytes())
let Some(nine_slice) = serde_json::from_str(&text)
.ok()
.as_ref()
.and_then(parse_nine_slice)
@@ -2025,28 +2025,6 @@ impl EditBox {
mod tests {
use super::*;
#[test]
fn notes_after_a_sprites_metadata_keep_its_nine_slice() {
// Gson stops reading after the first value, so vanilla keeps this nine slice
// (CozyUI+'s highlighted button, #3046).
let root = std::env::temp_dir().join(format!("horizon-ui-meta-{}", std::process::id()));
let widget = root.join("assets/minecraft/textures/gui/sprites/widget");
std::fs::create_dir_all(&widget).unwrap();
std::fs::write(
widget.join("button_highlighted.png.mcmeta"),
"{\"gui\": {\"scaling\": {\"type\": \"nine_slice\", \"width\": 80, \"height\": 20,\n\
\"border\": {\"left\": 34, \"top\": 8, \"right\": 34, \"bottom\": 8}}}}\n\n// 0 10\n// 1 8\n",
)
.unwrap();
let metadata = read_metadata(&root);
std::fs::remove_dir_all(&root).unwrap();
let slice = metadata.0["gui/sprites/widget/button_highlighted"];
assert_eq!(
(slice.width, slice.height, slice.border),
(80, 20, [34, 8, 34, 8])
);
}
/// The quads' destination rectangles and their UVs.
fn quads(batch: &HudBatch) -> Vec<([f32; 4], [f32; 4])> {
batch
+1 -10
View File
@@ -9,9 +9,6 @@ use horizon_core::random::{LegacyRandom, LevelRandom};
use horizon_world::registry::BlockStateId;
use std::sync::Arc;
mod pending_entity;
pub use pending_entity::{EntityLoadReason, PendingEntity};
mod modified;
pub use modified::ModifiedChunks;
@@ -84,7 +81,7 @@ pub struct World {
/// incrementally by streaming.
pub light_edits: Vec<((i32, i32, i32), u32, u32)>,
/// Saved entities of chunks that just loaded, spawned by the game.
pub loaded_entities: Vec<((i32, i32), Vec<PendingEntity>)>,
pub loaded_entities: Vec<((i32, i32), Vec<horizon_world::nbt::Tag>)>,
/// Chunks loaded since the level's last pass, their entity sections not
/// ready yet (`PersistentEntitySectionManager`'s PENDING), empty ones too:
/// the pass ends by readying them (`processPendingLoads`).
@@ -218,12 +215,6 @@ impl Weather {
}
}
impl World {
/// Queue ordinary NBT; transient transfer state is never decoded from it.
pub fn queue_entity_nbt(&mut self, key: (i32, i32), tags: Vec<horizon_world::nbt::Tag>) {
self.loaded_entities
.push((key, tags.into_iter().map(PendingEntity::from).collect()));
}
pub fn new(air: BlockStateId, seed: i64) -> Self {
Self {
shape: LevelShape::OVERWORLD,
@@ -1,89 +0,0 @@
//! Pending entity NBT and the runtime context that must not be stored inside it.
use horizon_world::nbt::Tag;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EntityLoadReason {
Ordinary,
TeleportedTnt,
}
#[derive(Clone, Debug)]
pub struct PendingEntity {
tag: Tag,
reason: EntityLoadReason,
}
impl From<Tag> for PendingEntity {
fn from(tag: Tag) -> Self {
Self {
tag,
reason: EntityLoadReason::Ordinary,
}
}
}
impl PendingEntity {
/// Only an in-memory TNT transfer supplies this context, never saved NBT.
pub fn after_tnt_portal(tag: Tag) -> Self {
Self {
tag,
reason: EntityLoadReason::TeleportedTnt,
}
}
pub fn into_parts(self) -> (Tag, EntityLoadReason) {
(self.tag, self.reason)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ordinary_nbt_cannot_request_transient_portal_state() {
for marker in [0, 1] {
let tag = Tag::compound([("horizon:tnt_used_portal", Tag::Byte(marker))]);
let (loaded, reason) = PendingEntity::from(tag.clone()).into_parts();
assert_eq!(loaded, tag);
assert_eq!(reason, EntityLoadReason::Ordinary);
}
}
#[test]
fn queue_swaps_and_appends_keep_each_entitys_context_and_order() {
let ordinary = Tag::compound([("id", Tag::String("ordinary".into()))]);
let transfer = Tag::compound([("id", Tag::String("transfer".into()))]);
let mut batches = vec![(
(1, 2),
vec![
ordinary.clone().into(),
PendingEntity::after_tnt_portal(transfer.clone()),
],
)];
let mut waiting = std::mem::take(&mut batches);
batches.push(((3, 4), vec![ordinary.clone().into()]));
waiting.append(&mut batches);
assert!(batches.is_empty());
let mut batches = waiting.into_iter();
let (key, entities) = batches.next().unwrap();
assert_eq!(key, (1, 2));
let mut entities = entities.into_iter();
assert_eq!(
entities.next().unwrap().into_parts(),
(ordinary.clone(), EntityLoadReason::Ordinary)
);
assert_eq!(
entities.next().unwrap().into_parts(),
(transfer, EntityLoadReason::TeleportedTnt)
);
assert!(entities.next().is_none());
let (key, entities) = batches.next().unwrap();
assert_eq!(key, (3, 4));
assert_eq!(
entities.into_iter().next().unwrap().into_parts(),
(ordinary, EntityLoadReason::Ordinary)
);
assert!(batches.next().is_none());
}
}
+4
View File
@@ -93,6 +93,10 @@ fs4 = { version = "1.1.0", default-features = false, features = ["sync"] }
rustix = { version = "1", default-features = false, features = ["std", "time", "process", "fs"] }
[target.'cfg(windows)'.dependencies]
# Resolve virtualized folders to shell-compatible physical paths.
dunce = "1.0.5"
# Use the registered URI handler without routing links through Explorer/cmd.
open = { version = "5.4.5", features = ["shellexecute-on-windows"] }
# DirectX 12, where Vulkan has no adapter or device, or by choice (`graphicsApi`, graphics.rs).
# Shaders compile with FXC (d3dcompiler_47.dll, part of Windows), or on integrated GPUs with DXC
# (dxcompiler.dll beside the game, gfx/dx12_compiler.rs).
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Growwe verre terrein in plaaslike wêrelde. Geïntegreerde GPU's stop by 128 stukke.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Verminder trek veel terrein growwer: vinniger op hierdie geïntegreerde GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Verminder trek veel terrein growwer, vir GPU's word dit stadiger.",
"Field of view. Wider shows more terrain at once.": "Gesigsveld. Wyer wys meer terrein op een slag.",
"Caps frames per second; a cap saves power and heat.": "Caps rame per sekonde; 'n pet spaar krag en hitte.",
"Waits for the display's refresh: no tearing, a little latency.": "Wag vir die verversing van die skerm: geen skeur nie, 'n bietjie vertraging.",
"Size of menus and the HUD.": "Grootte van spyskaarte en die HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Maak gekartelde rande glad. FXAA: sagter. TAA: gladste, bewegende dinge kan loop.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Maak die wêreld kleiner en herbou dit met TAA. Vinniger, sagter.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Verskerp die opgeskaalde beeld. Hoër: skerper rande, meer flikkering.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-uitset op 'n HDR-skerm: lawa, vuur en sonlig skyn helderder.",
"How frames reach the screen while VSync is off.": "Hoe rame die skerm bereik terwyl VSync af is.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Doeltreffende slaap tot die volgende raam; Presiese draaie, soos vanielje.",
"Fills the screen (borderless).": "Vul die skerm (randloos).",
"Brightens dark places.": "Verhelder donker plekke.",
"Lowers the frame rate when minimised, or idle too.": "Verlaag die raamtempo wanneer dit geminimaliseer word, of ook ledig.",
"Sways the view while walking.": "Swaai die uitsig terwyl jy stap.",
"Fades newly loaded chunks in.": "Vervaag nuutgelaaide stukke in.",
"Darkens the screen's edges.": "Maak die skerm se rande donkerder.",
"Shows when the world saves.": "Wys wanneer die wêreld red.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Hierdie bediener is in aanlynmodus: vanlyn profiele kan nie daarby aansluit nie; elke speler het sy eie Minecraft-rekening nodig.",
"horizon.splitscreen.own_account": "Hierdie bediener vereis elke speler se eie Minecraft-rekening",
"horizon.splitscreen.local_only": "Ander spelers kan slegs met hul eie Minecraft-rekening by hierdie bediener aansluit: vanlyn profiele speel in jou wêreld, op LAN of op 'n bediener op jou plaaslike netwerk.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Versteek modelle agter ondeursigtige blokke. Async kontroleer af-draad; entiteite merk.",
"Block Entities": "Blok Entiteite",
"Shulker Boxes": "Shulkerbokse",
"Reuses settled boxes; lid movement stays animated.": "Hergebruik afgewikkelde bokse; dekselbeweging bly geanimeerd.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Geopen vir hierdie sessie deur die program wat die speletjie begin het.",
"horizon.agent.socket": "Sok: %s (kopieer die besonderhede vir sy volledige pad)",
"horizon.agent.local_only": "Slegs plaaslik: agente op hierdie rekenaar, nooit die netwerk nie.",
"%s nits": "%s nete",
"Auto (%s nits)": "Outo (%s nete)",
"%.2f nits": "%.2f nete",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Versteek modelle agter ondeursigtige blokke. Entiteite-opdatering. Af met pasgemaakte pakke.",
"Entity Culling Precheck": "Entiteit-uitdunning-voorafkontrole",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Voer die skare-AABB-voorafkontrole uit ná hierdie aantal gelaaide skare. Nul skakel dit af.",
"%s mobs": "%s skares",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "التضاريس البعيدة الخشنة في العوالم المحلية. تتوقف وحدات معالجة الرسومات المدمجة عند 128 قطعة.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "تم تقليل الرسم على التضاريس البعيدة: بشكل أسرع على وحدة معالجة الرسومات المدمجة هذه.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "يتم تقليل الرسوم على التضاريس البعيدة بشكل أكثر خشونة، أما بالنسبة لوحدات معالجة الرسومات فإنها تبطئ.",
"Field of view. Wider shows more terrain at once.": "مجال الرؤية. يُظهر العرض الأوسع المزيد من التضاريس في وقت واحد.",
"Caps frames per second; a cap saves power and heat.": "قبعات الإطارات في الثانية الواحدة؛ غطاء يوفر الطاقة والحرارة.",
"Waits for the display's refresh: no tearing, a little latency.": "في انتظار تحديث الشاشة: بدون تمزق، وقليل من زمن الوصول.",
"Size of menus and the HUD.": "حجم القوائم وHUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "ينعم الحواف الخشنة. FXAA: أكثر ليونة. TAA: قد تتبع الأشياء الأكثر سلاسة وتحريكًا.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "يجعل العالم أصغر حجمًا ويعيد بنائه باستخدام TAA. أسرع وأكثر ليونة.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "يزيد حدة الصورة المرتقاة. أعلى: حواف أوضح ووميض أكثر.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "إخراج HDR على شاشة HDR: تتألق الحمم البركانية والنار وأشعة الشمس بشكل أكثر سطوعًا.",
"How frames reach the screen while VSync is off.": "كيفية وصول الإطارات إلى الشاشة أثناء إيقاف تشغيل VSync.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "ينام بكفاءة حتى الإطار التالي؛ يدور بدقة، مثل الفانيليا.",
"Fills the screen (borderless).": "يملأ الشاشة (بلا حدود).",
"Brightens dark places.": "يضيء الأماكن الداكنة.",
"Lowers the frame rate when minimised, or idle too.": "يخفض معدل الإطارات عند تصغيره أو في وضع الخمول أيضًا.",
"Sways the view while walking.": "يتأرجح المنظر أثناء المشي.",
"Fades newly loaded chunks in.": "يتلاشى القطع المحملة حديثًا.",
"Darkens the screen's edges.": "لتغميق حواف الشاشة.",
"Shows when the world saves.": "يظهر عندما ينقذ العالم.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "هذا الخادم في وضع الاتصال: لا يمكن للملفات الشخصية غير المتصلة الانضمام إليه، وكل لاعب يحتاج حساب Minecraft خاصًا به.",
"horizon.splitscreen.own_account": "يحتاج هذا الخادم حساب Minecraft خاصًا بكل لاعب",
"horizon.splitscreen.local_only": "يمكن للاعبين الآخرين الانضمام إلى هذا الخادم فقط بحساب Minecraft خاص بهم: أما الملفات الشخصية غير المتصلة فتلعب في عالمك، على LAN أو على خادم في شبكتك المحلية.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "يخفي النماذج خلف الكتل المعتمة. غير متزامن يتحقق من خارج الموضوع؛ علامة الكيانات.",
"Block Entities": "حظر الكيانات",
"Shulker Boxes": "صناديق شوكر",
"Reuses settled boxes; lid movement stays animated.": "إعادة استخدام الصناديق المستقرة؛ تبقى حركة الغطاء متحركة.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "تم فتحه لهذه الجلسة بواسطة البرنامج الذي بدأ اللعبة.",
"horizon.agent.socket": "المقبس: %s (انسخ التفاصيل لمساره الكامل)",
"horizon.agent.local_only": "محلي فقط: الوكلاء على هذا الكمبيوتر، وليس الشبكة أبدًا.",
"%s nits": "%s القمل",
"Auto (%s nits)": "تلقائي (%s شمعة في المتر المربع)",
"%.2f nits": "%.2f القمل",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "يخفي النماذج خلف الكتل المعتمة. تحديث الكيانات مع حزم مخصصة.",
"Entity Culling Precheck": "فحص استبعاد الكيانات المسبق",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "يشغّل فحص AABB للغوغاء بعد هذا العدد من الغوغاء المحمّلين. صفر يعطّله.",
"%s mobs": "%s غوغاء",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Yerli dünyalarda kobud uzaq ərazi. İnteqrasiya edilmiş GPU-lar 128 hissədə dayanır.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Azaldılmış ərazini daha qaba çəkir: bu inteqrasiya olunmuş GPU-da daha sürətli.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Azaldılmış ərazini daha qaba çəkir, GPU-lar üçün isə yavaşlayır.",
"Field of view. Wider shows more terrain at once.": "Baxış sahəsi. Daha geniş bir anda daha çox ərazini göstərir.",
"Caps frames per second; a cap saves power and heat.": "Saniyədə kadrların sayı; qapaq enerjiyə və istiliyə qənaət edir.",
"Waits for the display's refresh: no tearing, a little latency.": "Ekranın təzələnməsini gözləyir: cırılma, bir az gecikmə.",
"Size of menus and the HUD.": "Menyuların ölçüsü və HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Kəsik kənarları hamarlayır. FXAA: daha yumşaq. TAA: ən hamar, hərəkətli şeylər cığır çəkə bilər.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Dünyanı daha kiçik edir və TAA ilə yenidən qurur. Daha sürətli, daha yumşaq.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Böyüdülmüş təsviri kəskinləşdirir. Daha yüksək: daha aydın kənarlar, daha çox parıltı.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR displeydə HDR çıxışı: lava, yanğın və günəş işığı daha parlaq parlayır.",
"How frames reach the screen while VSync is off.": "VSync söndürüldükdə çərçivələr ekrana necə çatır.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Növbəti kadra qədər səmərəli yuxular; Vanil kimi dəqiq spinlər.",
"Fills the screen (borderless).": "Ekranı doldurur (sərhədsiz).",
"Brightens dark places.": "Qaranlıq yerləri işıqlandırır.",
"Lowers the frame rate when minimised, or idle too.": "Minimumlaşdırıldıqda və ya boş olduqda kadr sürətini azaldır.",
"Sways the view while walking.": "Gəzərkən mənzərəni yelləyir.",
"Fades newly loaded chunks in.": "Yeni yüklənmiş parçaları sönür.",
"Darkens the screen's edges.": "Ekranın kənarlarını qaraldır.",
"Shows when the world saves.": "Dünyanın nə vaxt xilas etdiyini göstərir.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Bu server onlayn rejimdədir: oflayn profillər ona qoşula bilməz, hər oyunçunun öz Minecraft hesabı lazımdır.",
"horizon.splitscreen.own_account": "Bu server hər oyunçunun öz Minecraft hesabını tələb edir",
"horizon.splitscreen.local_only": "Digər oyunçular bu serverə yalnız öz Minecraft hesabları ilə qoşula bilər: oflayn profillər sizin dünyanızda, LAN-da və ya yerli şəbəkənizdəki serverdə oynayır.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Modelləri qeyri-şəffaf blokların arxasında gizlədir. Async-dən kənar yoxlayır; qurumlar işarələyir.",
"Block Entities": "Blok obyektləri",
"Shulker Boxes": "Shulker qutuları",
"Reuses settled boxes; lid movement stays animated.": "Yerləşmiş qutuları təkrar istifadə edir; qapaq hərəkəti canlı qalır.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Oyuna başlayan proqram tərəfindən bu sessiya üçün açıldı.",
"horizon.agent.socket": "Soket: %s (tam yolu üçün təfərrüatları kopyalayın)",
"horizon.agent.local_only": "Yalnız yerli: bu kompüterdəki agentlər, heç vaxt şəbəkə.",
"%s nits": "%s nit",
"Auto (%s nits)": "Avtomatik (%s nits)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Modelləri qeyri-şəffaf blokların arxasında gizlədir. Müəssisələrin yenilənməsi. Fərdi paketlərlə endirim.",
"Entity Culling Precheck": "Obyekt kəsmə ön yoxlaması",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Yüklənmiş mob sayı bu həddə çatanda mob AABB ön yoxlamasını işlədir. Sıfır onu söndürür.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Урындағы донъяларҙа ҡырыҫ алыҫ ерҙәр. Интеграцияланған график процессорҙар 128 өлөштә туҡтай.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Ҡыҫҡартылған тарта алыҫ ер ҡырыҫ: тиҙерәк был интеграцияланған GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Кәметелгән тарта алыҫ ер ҡырыҫыраҡ, GPUs өсөн ул яйлатып.",
"Field of view. Wider shows more terrain at once.": "Күренеш өлкәһе. Киңерәк бер юлы күберәк ерҙе күрһәтә.",
"Caps frames per second; a cap saves power and heat.": "Ҡапҡастар кадрҙар секундына; ҡапҡас энергияны һәм йылылыҡты һаҡлай.",
"Waits for the display's refresh: no tearing, a little latency.": "Дисплейҙы яңыртыуҙы көтә: йыртыу юҡ, бер аҙ тотҡарлыҡ.",
"Size of menus and the HUD.": "Размер меню һәм HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Тешле ситтәрен тигеҙләй. ФХАА: йомшағыраҡ. ТАА: иң шыма, хәрәкәт итеүсе әйберҙәр эҙҙәре булыуы мөмкин.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Донъяны бәләкәйерәк итә һәм уны ТАА менән яңынан төҙөй. Тиҙерәк, йомшағыраҡ.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Масштабланған һүрәтте үткерләндерә. Юғарыраҡ: ситтәр асығыраҡ, ялтырау күберәк.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR дисплейында HDR сығышы: лава, ут һәм ҡояш нурҙары сағыуыраҡ балҡый.",
"How frames reach the screen while VSync is off.": "Нисек кадрҙар экранға етә, ә VSync өҙөлгән.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Һөҙөмтәле йоҡлай сираттағы кадрға тиклем; Теүәл әйләнештәр, ваниль кеүек.",
"Fills the screen (borderless).": "Экранды тултыра (сикһеҙ).",
"Brightens dark places.": "Ҡараңғы урындарҙы яҡтырта.",
"Lowers the frame rate when minimised, or idle too.": "Кадрҙар йышлығын түбәнәйтә, ҡасан минималь, йәки буш ла.",
"Sways the view while walking.": "Йөрөгәндә ҡарашты һелкетә.",
"Fades newly loaded chunks in.": "Яңы тейәлгән өлөштәрҙе һүнә.",
"Darkens the screen's edges.": "Экрандың ситтәрен ҡарайта.",
"Shows when the world saves.": "Донъя ҡотҡарғанда күрһәтә.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Был сервер онлайн режимда: офлайн профилдәр уға ҡушыла алмай, һәр уйынсыға үҙ Minecraft иҫәбе кәрәк.",
"horizon.splitscreen.own_account": "Был серверға һәр уйынсының үҙ Minecraft иҫәбе кәрәк",
"horizon.splitscreen.local_only": "Башҡа уйынсылар был серверға үҙҙәренең Minecraft иҫәбенә генә ҡушыла ала: офлайн профилдәр һеҙҙең донъяла, LAN йәки һеҙҙең урындағы селтәрҙәге серверҙа уйнай.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Моделдәрҙе асыҡ булмаған блоктар артында йәшерә. Ассинхрон тикшерә тышҡы еп; субъекттар галочкой.",
"Block Entities": "Блок субъекттары",
"Shulker Boxes": "Шулкер йәшниктәре",
"Reuses settled boxes; lid movement stays animated.": "Ҡабаттан ҡуллана урынлаштырылған йәшниктәр; ҡапҡас хәрәкәте йәнле ҡала.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Был сессия өсөн уйынды башлаған программа асты.",
"horizon.agent.socket": "Розетка: %s (уның тулы юлы өсөн реквизиттарҙы күсерергә)",
"horizon.agent.local_only": "Урындағы ғына: был компьютерҙа агенттар, бер ҡасан да селтәр.",
"%s nits": "%s нит",
"Auto (%s nits)": "Авто (%s нит)",
"%.2f nits": "%.2f нит",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Моделдәрҙе асыҡ булмаған блоктар артында йәшерә. Яңыртыу субъекттары. Ҡулланыусылар пакеттары менән өҙөлгән.",
"Entity Culling Precheck": "Субъекттарҙы ҡырҡыуҙы алдан тикшереү",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Моб AABB алдан тикшереүен был һандағы тейәлгән мобтан һуң башҡара. Ноль уны һүндерә.",
"%s mobs": "%s моб",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Грубая аддаленая мясцовасць у лакальных мірах. Убудаваныя графічныя працэсары спыняюцца на 128 кавалках.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Паменшанае малюнак больш грубай мясцовасці: хутчэй на гэтым убудаваным графічным працэсары.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Зніжэнне малюе больш грубую мясцовасць, для графічных працэсараў гэта запавольваецца.",
"Field of view. Wider shows more terrain at once.": "Поле зроку. Шырэй паказвае адразу больш мясцовасці.",
"Caps frames per second; a cap saves power and heat.": "Колькасць кадраў у секунду; шапка эканоміць энергію і цяпло.",
"Waits for the display's refresh: no tearing, a little latency.": "Чакае абнаўлення дысплея: без разрыву, з невялікай затрымкай.",
"Size of menus and the HUD.": "Памер меню і HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Згладжвае няроўныя краю. FXAA: мякчэй. TAA: самыя гладкія рэчы, якія рухаюцца, могуць цягнуцца.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Памяншае свет і перабудоўвае яго з TAA. Хутчэй, мякчэй.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Павялічвае рэзкасць павялічанай выявы. Вышэй: больш рэзкія краі, больш мігацення.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Вывад HDR на дысплеі HDR: лава, агонь і сонечнае святло ззяюць ярчэй.",
"How frames reach the screen while VSync is off.": "Як кадры трапляюць на экран, калі VSync выключаны.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Эфектыўнае спіць да наступнага кадра; Дакладныя спіны, як ваніль.",
"Fills the screen (borderless).": "Запаўняе экран (без палёў).",
"Brightens dark places.": "Асвятляе цёмныя месцы.",
"Lowers the frame rate when minimised, or idle too.": "Зніжае частату кадраў пры згортванні або ў рэжыме чакання.",
"Sways the view while walking.": "Качае погляд падчас хады.",
"Fades newly loaded chunks in.": "Змяншае толькі што загружаныя кавалкі.",
"Darkens the screen's edges.": "Зацямняе краю экрана.",
"Shows when the world saves.": "Паказвае, калі свет ратуе.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Гэты сервер у анлайн-рэжыме: афлайн-профілі не могуць далучыцца, кожнаму гульцу патрэбны ўласны ўліковы запіс Minecraft.",
"horizon.splitscreen.own_account": "Гэтаму серверу патрэбны ўласны ўліковы запіс Minecraft для кожнага гульца",
"horizon.splitscreen.local_only": "Іншыя гульцы могуць далучыцца да гэтага сервера толькі са сваім уліковым запісам Minecraft: афлайн-профілі гуляюць у вашым свеце, па LAN або на серверы ў вашай лакальнай сетцы.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Хавае мадэлі за непразрыстымі блокамі. Async правярае па-за патокам; суб'ектаў цік.",
"Block Entities": "Блокавыя аб'екты",
"Shulker Boxes": "Скрынкі Шулкера",
"Reuses settled boxes; lid movement stays animated.": "Паўторна выкарыстоўвае адстойнікі; рух вечка застаецца ажыўленым.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Адкрыты для гэтай сесіі праграмай, якая запусціла гульню.",
"horizon.agent.socket": "Сокет: %s (скапіруйце дэталі для поўнага шляху)",
"horizon.agent.local_only": "Толькі лакальна: агенты на гэтым кампутары, ніколі ў сетцы.",
"%s nits": "%s ніт",
"Auto (%s nits)": "Аўта (%s ніт)",
"%.2f nits": "%.2f ніт",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Хавае мадэлі за непразрыстымі блокамі. Абнаўленне суб'ектаў. Выключыце спецыяльныя пакеты.",
"Entity Culling Precheck": "Папярэдняя праверка адсячэння сутнасцей",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Выконвае папярэднюю праверку AABB мабаў пасля гэтай колькасці загружаных мабаў. Нуль адключае яе.",
"%s mobs": "%s мабаў",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Груб далечен терен в местните светове. Интегрираните графични процесори спират на 128 парчета.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Намалено чертане на по-груб терен: по-бързо с този интегриран GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Намалено рисува далеч по-груб терен, за GPU се забавя.",
"Field of view. Wider shows more terrain at once.": "Зрително поле. По-широко показва повече терен наведнъж.",
"Caps frames per second; a cap saves power and heat.": "Максимални кадри в секунда; капачката спестява енергия и топлина.",
"Waits for the display's refresh: no tearing, a little latency.": "Изчаква опресняване на дисплея: без разкъсване, малко забавяне.",
"Size of menus and the HUD.": "Размер на менютата и HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Изглажда назъбените ръбове. FXAA: по-мек. TAA: най-плавните, движещи се неща могат да се проточат.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Прави света по-малък и го възстановява с TAA. По-бързо, по-меко.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Изостря премащабираната картина. По-високо: по-ясни ръбове, повече трептене.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR изход на HDR дисплей: лава, огън и слънчева светлина блестят по-ярко.",
"How frames reach the screen while VSync is off.": "Как кадрите достигат до екрана, докато VSync е изключен.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Ефективно заспиване до следващия кадър; Прецизни завъртания, като ванилия.",
"Fills the screen (borderless).": "Запълва екрана (без граници).",
"Brightens dark places.": "Осветява тъмните места.",
"Lowers the frame rate when minimised, or idle too.": "Намалява честотата на кадрите, когато е минимизирана или неактивна.",
"Sways the view while walking.": "Люлее гледката по време на ходене.",
"Fades newly loaded chunks in.": "Избледнява новозаредените парчета.",
"Darkens the screen's edges.": "Затъмнява ръбовете на екрана.",
"Shows when the world saves.": "Показва кога светът спасява.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Този сървър е в онлайн режим: офлайн профилите не могат да се присъединят, всеки играч се нуждае от собствен акаунт в Minecraft.",
"horizon.splitscreen.own_account": "Този сървър изисква собствен акаунт в Minecraft за всеки играч",
"horizon.splitscreen.local_only": "Другите играчи могат да се присъединят към този сървър само със свой акаунт в Minecraft: офлайн профилите играят във вашия свят, в LAN или на сървър в локалната ви мрежа.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Скрива модели зад непрозрачни блокове. Async проверява извън нишката; субекти отметка.",
"Block Entities": "Блокиране на обекти",
"Shulker Boxes": "Кутии Шулкер",
"Reuses settled boxes; lid movement stays animated.": "Повторно използване на утаени кутии; движението на капака остава анимирано.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Отворено за тази сесия от програмата, която стартира играта.",
"horizon.agent.socket": "Сокет: %s (копирайте подробностите за пълния му път)",
"horizon.agent.local_only": "Само локално: агенти на този компютър, никога в мрежата.",
"%s nits": "%s нита",
"Auto (%s nits)": "Автоматично (%s нита)",
"%.2f nits": "%.2f нита",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Скрива модели зад непрозрачни блокове. Актуализация на обекти. Изключване с персонализирани пакети.",
"Entity Culling Precheck": "Предварителна проверка на отстраняването",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Изпълнява предварителната проверка на AABB за тълпите след толкова заредени тълпи. Нула я изключва.",
"%s mobs": "%s тълпи",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Douaroù pell gros e bedoù lec'hel. Paouez a ra ar GPUoù kevredet da 128 tamm.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Digreskiñ a ra an douaroù kalz grosoc'h : buanoc'h war ar GPU kevredet-mañ.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Ar reduset a denn an douaroù kalz grosoc'h, evit ar GPUoù e vez gorrekaet.",
"Field of view. Wider shows more terrain at once.": "Tachenn gwel. Ledanoc'h a ziskouez muioc'h a zouaroù war un dro.",
"Caps frames per second; a cap saves power and heat.": "Bep frammoù dre eilenn; ur c'hasketenn a espern energiezh ha tommder.",
"Waits for the display's refresh: no tearing, a little latency.": "Gortoz a ra freskaat ar skramm : tamm torr ebet, un tamm dale.",
"Size of menus and the HUD.": "Ment ar mennozhioù hag an HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Eeunaat a ra ar c'hornioù ruz. FXAA: dousoc'h. TAA: an traoù eeunañ, o fiñval a c'hell heuliañ.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Bihanaat a ra ar bed hag adsevel anezhañ gant TAA. Buanoc'h, dousoc'h.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Lemmaat a ra ar skeudenn gresket. Uheloc'h : bordoù lemmoc'h, muioc'h a sked.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Disoc'h HDR war ur skramm HDR : lava, tan ha gouloù an heol a lugern muioc'h.",
"How frames reach the screen while VSync is off.": "Penaos e tistro ar frammoù war ar skramm pa vez diweredekaet VSync.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Kousket a ra efedus betek ar framm da heul; Troioù resis, evel ar vanilha.",
"Fills the screen (borderless).": "Leuniañ ar skramm (hep bevennoù).",
"Brightens dark places.": "Sklaeraat a ra al lec'hioù teñval.",
"Lowers the frame rate when minimised, or idle too.": "Digreskiñ a ra ar feur framm pa vez bihanaet, pe pa vez didalvoud ivez.",
"Sways the view while walking.": "Heñchañ a ra ar gwel e-pad ma kerzher.",
"Fades newly loaded chunks in.": "Diverkañ a ra an tammoù nevez karget.",
"Darkens the screen's edges.": "Teñvalaat a ra ribloù ar skramm.",
"Shows when the world saves.": "Diskouez a ra pa savete ar bed.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "E mod enlinenn emañ ar servijer-mañ : n'hall ket ar profiloù ezlinenn mont e-barzh, pep c'hoarier en deus ezhomm eus e gont Minecraft.",
"horizon.splitscreen.own_account": "Ezhomm en deus ar servijer-mañ eus ur gont Minecraft evit pep c'hoarier",
"horizon.splitscreen.local_only": "Ar c'hoarierien all ne c'hallont mont e-barzh ar servijer-mañ nemet gant o c'hont Minecraft o-unan : ar profiloù ezlinenn a c'hoari en ho bed, war LAN pe war ur servijer war ho rouedad lec'hel.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Kuzhat a ra ar patromoù a-dreñv bloc'hoù dister. Gwiriañ a ra an async e-maez an neudennad; tik an entiteoù.",
"Block Entities": "Entiteoù stankañ",
"Shulker Boxes": "Boestoù Shulker",
"Reuses settled boxes; lid movement stays animated.": "Adimplij a ra ar voestoù staliet; fiñv ar golo a chom bev.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Digoret evit ar prantad-mañ gant ar programm en deus kroget ar c'hoari.",
"horizon.agent.socket": "Socket: %s (eilañ ar munudoù evit e hent klok)",
"horizon.agent.local_only": "Lec'hel hepken : an ajañsoù war an urzhiataer-mañ, biskoazh ar rouedad.",
"%s nits": "%s nits",
"Auto (%s nits)": "Emgefre (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Kuzhat a ra ar patromoù a-dreñv bloc'hoù dister. Hizivaat an ensavadurioù. Dilezet gant pakadoù personelaet.",
"Entity Culling Precheck": "Rakwiriañ distruj an entiteoù",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Kas a ra rakwiriad AABB ar moboù goude kement-mañ a voboù karget. Zero a ziweredeka anezhañ.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grubi udaljeni teren u lokalnim svjetovima. Integrisani GPU-ovi se zaustavljaju na 128 komada.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Smanjeno crtanje dalekog terena grublje: brže na ovom integrisanom GPU-u.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Smanjeno crtanje dalekog terena je grublje, za GPU-ove usporava.",
"Field of view. Wider shows more terrain at once.": "Vidno polje. Šire prikazuje više terena odjednom.",
"Caps frames per second; a cap saves power and heat.": "Caps okvira u sekundi; kapa štedi energiju i toplotu.",
"Waits for the display's refresh: no tearing, a little latency.": "Čeka osvježavanje ekrana: nema kidanja, malo kašnjenja.",
"Size of menus and the HUD.": "Veličina menija i HUD-a.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Zaglađuje nazubljene ivice. FXAA: mekše. TAA: najglađe, pokretne stvari mogu zaostajati.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Čini svijet manjim i obnavlja ga pomoću TAA. Brže, mekše.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Izoštrava uvećanu sliku. Više: oštrije ivice, više treperenja.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR izlaz na HDR displeju: lava, vatra i sunčeva svetlost sijaju jače.",
"How frames reach the screen while VSync is off.": "Kako okviri dolaze do ekrana dok je VSync isključen.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efikasno spavanje do sljedećeg kadra; Precizno okretanje, poput vanile.",
"Fills the screen (borderless).": "Ispunjava ekran (bez ivica).",
"Brightens dark places.": "Osvjetljava tamna mjesta.",
"Lowers the frame rate when minimised, or idle too.": "Smanjuje brzinu kadrova kada je minimizirana ili u stanju mirovanja.",
"Sways the view while walking.": "Ljulja pogled dok hodate.",
"Fades newly loaded chunks in.": "Uklanja novoučitane komade.",
"Darkens the screen's edges.": "Zatamnjuje ivice ekrana.",
"Shows when the world saves.": "Prikazuje kada svijet spašava.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Ovaj server je u online modu: offline profili mu se ne mogu pridružiti, svaki igrač treba vlastiti Minecraft nalog.",
"horizon.splitscreen.own_account": "Ovaj server zahtijeva vlastiti Minecraft nalog za svakog igrača",
"horizon.splitscreen.local_only": "Drugi igrači se mogu pridružiti ovom serveru samo sa svojim Minecraft nalogom: offline profili igraju u vašem svijetu, na LAN-u ili na serveru na vašoj lokalnoj mreži.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Skriva modele iza neprozirnih blokova. Async provjerava off-thread; entiteti otkucaju.",
"Block Entities": "Blokirajte entitete",
"Shulker Boxes": "Kutije za šulkere",
"Reuses settled boxes; lid movement stays animated.": "Ponovno koristi postavljene kutije; pokreti poklopca ostaju animirani.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Otvoreno za ovu sesiju od strane programa koji je pokrenuo igru.",
"horizon.agent.socket": "Socket: %s (kopirajte detalje za njegovu punu putanju)",
"horizon.agent.local_only": "Samo lokalno: agenti na ovom računaru, nikada mreža.",
"%s nits": "%s gnjida",
"Auto (%s nits)": "automatski (%s gnjida)",
"%.2f nits": "%.2f gnjida",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Skriva modele iza neprozirnih blokova. Ažuriranje entiteta. Isključeno sa prilagođenim paketima.",
"Entity Culling Precheck": "Prethodna provjera odbijanja entiteta",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Pokreće AABB prethodnu provjeru mobova nakon ovoliko učitanih mobova. Nula je isključuje.",
"%s mobs": "%s mobova",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terreny llunyà gruixut en mons locals. Les GPU integrades s'aturen a 128 fragments.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Dibuixos reduïts molt llunyans més gruixuts: més ràpid en aquesta GPU integrada.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Els dibuixos reduïts són molt més gruixuts, per a les GPU s'alenteix.",
"Field of view. Wider shows more terrain at once.": "Camp de visió. Més ample mostra més terreny alhora.",
"Caps frames per second; a cap saves power and heat.": "Caps fotogrames per segon; una tapa estalvia energia i calor.",
"Waits for the display's refresh: no tearing, a little latency.": "Espera que la pantalla s'actualitzi: sense trencament, una mica de latència.",
"Size of menus and the HUD.": "Mida dels menús i l'HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Allisa les vores dentades. FXAA: més suau. TAA: més suau, les coses en moviment poden seguir.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Redueix el món i el reconstrueix amb TAA. Més ràpid, més suau.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Fa més nítida la imatge ampliada. Més alt: vores més nítides, més tremolor.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Sortida HDR en una pantalla HDR: la lava, el foc i la llum del sol brillen més.",
"How frames reach the screen while VSync is off.": "Com arriben els fotogrames a la pantalla mentre VSync està desactivat.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Dors eficients fins al següent fotograma; Girades precises, com la vainilla.",
"Fills the screen (borderless).": "Omple la pantalla (sense vores).",
"Brightens dark places.": "Il·lumina els llocs foscos.",
"Lowers the frame rate when minimised, or idle too.": "Redueix la velocitat de fotogrames quan es minimitza o també està inactiva.",
"Sways the view while walking.": "Oblida la vista mentre camina.",
"Fades newly loaded chunks in.": "Esvaeix els fragments que s'han carregat recentment.",
"Darkens the screen's edges.": "Enfosqueix les vores de la pantalla.",
"Shows when the world saves.": "Mostra quan el món salva.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Aquest servidor està en mode en línia: els perfils fora de línia no s'hi poden unir, cada jugador necessita el seu propi compte de Minecraft.",
"horizon.splitscreen.own_account": "Aquest servidor necessita el compte de Minecraft propi de cada jugador",
"horizon.splitscreen.local_only": "Els altres jugadors només s'hi poden unir amb el seu propi compte de Minecraft: els perfils fora de línia juguen al teu món, a la LAN o en un servidor de la teva xarxa local.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Amaga models darrere de blocs opacs. Async comprova fora de fil; les entitats marquen.",
"Block Entities": "Bloquejar entitats",
"Shulker Boxes": "Caixes Shulker",
"Reuses settled boxes; lid movement stays animated.": "Reutilitza caixes assentades; el moviment de la tapa es manté animat.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Obert per a aquesta sessió pel programa que va iniciar el joc.",
"horizon.agent.socket": "Socket: %s (copieu els detalls del camí complet)",
"horizon.agent.local_only": "Només local: agents en aquest ordinador, mai la xarxa.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automàtic (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Amaga models darrere de blocs opacs. Actualització d'entitats. Apaga amb paquets personalitzats.",
"Entity Culling Precheck": "Comprovació prèvia del culling d'entitats",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Executa la comprovació prèvia d'AABB dels mobs després d'aquest nombre de mobs carregats. Zero la desactiva.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Hrubý vzdálený terén v místních světech. Integrované GPU se zastaví na 128 blocích.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Snížené vykreslování daleko hrubšího terénu: rychlejší na tomto integrovaném GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Snížené vykresluje daleko hrubší terén, u GPU se zpomaluje.",
"Field of view. Wider shows more terrain at once.": "Zorné pole. Širší zobrazuje více terénu najednou.",
"Caps frames per second; a cap saves power and heat.": "Počet snímků za sekundu; čepice šetří energii a teplo.",
"Waits for the display's refresh: no tearing, a little latency.": "Čeká na obnovení displeje: žádné trhání, malá latence.",
"Size of menus and the HUD.": "Velikost menu a HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Vyhlazuje zubaté okraje. FXAA: měkčí. TAA: nejhladší, pohyblivé věci se mohou táhnout.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Zmenší svět a přestaví ho pomocí TAA. Rychlejší, měkčí.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Zaostří zvětšený obraz. Vyšší: ostřejší hrany, více třpytu.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Výstup HDR na displeji HDR: láva, oheň a sluneční světlo září jasněji.",
"How frames reach the screen while VSync is off.": "Jak se snímky dostanou na obrazovku, když je VSync vypnutá.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efektivní režim spánku až do dalšího snímku; Přesná rotace, jako vanilka.",
"Fills the screen (borderless).": "Vyplní obrazovku (bez okrajů).",
"Brightens dark places.": "Rozjasňuje tmavá místa.",
"Lowers the frame rate when minimised, or idle too.": "Při minimalizaci nebo nečinnosti sníží snímkovou frekvenci.",
"Sways the view while walking.": "Při chůzi kývá výhled.",
"Fades newly loaded chunks in.": "Nově načtené kousky zmizí.",
"Darkens the screen's edges.": "Ztmaví okraje obrazovky.",
"Shows when the world saves.": "Ukazuje, kdy svět zachraňuje.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Tento server je v online režimu: offline profily se k němu nemohou připojit, každý hráč potřebuje vlastní účet Minecraft.",
"horizon.splitscreen.own_account": "Tento server vyžaduje vlastní účet Minecraft pro každého hráče",
"horizon.splitscreen.local_only": "Ostatní hráči se k tomuto serveru mohou připojit jen s vlastním účtem Minecraft: offline profily hrají ve vašem světě, na LAN nebo na serveru ve vaší místní síti.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Skryje modely za neprůhledné bloky. Async kontroluje off-thread; entity klíštěte.",
"Block Entities": "Blokovat entity",
"Shulker Boxes": "Krabice Shulker",
"Reuses settled boxes; lid movement stays animated.": "Znovu používá usazené krabice; pohyb víka zůstává animovaný.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Otevřeno pro tuto relaci programem, který spustil hru.",
"horizon.agent.socket": "Socket: %s (zkopírujte podrobnosti pro jeho úplnou cestu)",
"horizon.agent.local_only": "Pouze místní: agenti na tomto počítači, nikdy v síti.",
"%s nits": "%s hnid",
"Auto (%s nits)": "Auto (%s nitů)",
"%.2f nits": "%.2f hnid",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Skryje modely za neprůhledné bloky. Aktualizace entit. Vypnuto s vlastními balíčky.",
"Entity Culling Precheck": "Předkontrola vyřazování entit",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Spustí předkontrolu AABB mobů po tomto počtu načtených mobů. Nula ji vypne.",
"%s mobs": "%s mobů",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Вырӑнти тӗнчери инҫетри ҫӗр лаптӑкӗ. Пӗрлештернӗ GPU-сем 128 татӑк ҫинче чарӑнаҫҫӗ.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Ҫак пӗрлештернӗ GPU-ра пӗчӗклетни ҫӗре чылай хытӑрах туртать: хӑвӑртрах.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Пӗчӗклетни ҫӗре чылай хытӑрах туртать, GPU-семшӗн вӑл ерипенлетет.",
"Field of view. Wider shows more terrain at once.": "Курӑну уйӗ. Сарлакараххи пӗр харӑсах ытларах ҫӗре кӑтартать.",
"Caps frames per second; a cap saves power and heat.": "Ҫеккунтра кадрсене чакарать; ҫӗлӗк энергипе ӑшша перекетлет.",
"Waits for the display's refresh: no tearing, a little latency.": "Дисплей ҫӗнелессине кӗтет: ҫурӑлмасть, кӑштах кая юлать.",
"Size of menus and the HUD.": "Менюсен калӑпӑшӗ тата HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Шӑллӑ хӗррисене тикӗслетет. FXAA: ҫемҫерех. ТАА: чи тикӗс, куҫакан япаласем йӗрлеме пултараҫҫӗ.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Тӗнчене пӗчӗклетет те ӑна TAA-па ҫӗнӗрен тӑвать. Хӑвӑртрах, ҫемҫерех.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Ӳстернӗ сӑнӑн ҫивӗчӗшӗн. Пысӑкрах: хӗррисем ҫивӗчрех, йӑлтӑркка ытларах.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR дисплей ҫинче HDR тухӑҫӗ: лава, вут тата хӗвел ҫути ҫутӑрах ҫутатаҫҫӗ.",
"How frames reach the screen while VSync is off.": "VSync ӗҫлемен чухне кадрсем экран ҫине мӗнле ҫитеҫҫӗ.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Тепӗр кадрчченех лайӑх ҫывӑрать; Тӗрӗс ҫаврӑнусем, ваниль пек.",
"Fills the screen (borderless).": "Экрана тултарать (чикӗсӗр).",
"Brightens dark places.": "Тӗттӗм вырӑнсене ҫутатать.",
"Lowers the frame rate when minimised, or idle too.": "Кадрсен хӑвӑртлӑхне пӗчӗклетнӗ чухне е ӗҫлемен чухне те чакарать.",
"Sways the view while walking.": "Утнӑ чухне курӑнӑва суллантарать.",
"Fades newly loaded chunks in.": "Ҫӗнӗрен ҫӗкленӗ татӑксене ҫухатать.",
"Darkens the screen's edges.": "Экран хӗррисене тӗксӗмлетет.",
"Shows when the world saves.": "Тӗнче хӑҫан ҫӑлӑннине кӑтартать.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Ку сервер онлайн режимра: офлайн профильсем унта кӗреймеҫҫӗ, кашни выляканӑн хӑйӗн Minecraft аккаунчӗ кирлӗ.",
"horizon.splitscreen.own_account": "Ку сервера кашни выляканӑн хӑйӗн Minecraft аккаунчӗ кирлӗ",
"horizon.splitscreen.local_only": "Ытти вылякансем ҫак сервера хӑйсен Minecraft аккаунчӗпе кӑна кӗме пултараҫҫӗ: офлайн профильсем сирӗн тӗнчере, LAN-ра е сирӗн вырӑнти сетьри серверта выляҫҫӗ.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Модельсене тӗксӗм блоксем хыҫне пытарать. Асинхронлӑ ҫипрен тухнине тӗрӗслет; субъектсем тик.",
"Block Entities": "Блок субъекчӗсем",
"Shulker Boxes": "Шулькер ещӗкӗсем",
"Reuses settled boxes; lid movement stays animated.": "Ҫирӗплетнӗ ещӗксемпе тепӗр хут усӑ курать; хупӑлча хусканӑвӗ чӗрӗ юлать.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Ку сеанс валли вӑййа пуҫарса янӑ программа уҫнӑ.",
"horizon.agent.socket": "Сокет: %s (унӑн тулли ҫулӗ валли детальсене копиле)",
"horizon.agent.local_only": "Вырӑнти кӑна: ку компьютер ҫинчи агентсем, нихӑҫан та сеть мар.",
"%s nits": "%s нитс",
"Auto (%s nits)": "Авто (%s нит)",
"%.2f nits": "%.2f нитс",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Модельсене тӗксӗм блоксем хыҫне пытарать. Субъектсем ҫӗнелеҫҫӗ. Ятарлӑ пакетсемпе тухӑр.",
"Entity Culling Precheck": "Объектсен кульлингӗн умлӑ тӗрӗслевӗ",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Мобсен AABB умлӑ тӗрӗслевне ҫакӑн чухлӗ моб тиеннӗ хыҫҫӑн пурнӑҫлать. Ноль сӳнтерет.",
"%s mobs": "%s моб",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Tir garw pell yn y bydoedd lleol. Mae GPUs integredig yn stopio ar 128 talpiau.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Llai yn tynnu tir llawer mwy bras: yn gyflymach ar y GPU integredig hwn.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Mae llai yn tynnu tir llawer mwy bras, ar gyfer GPUs mae'n arafu.",
"Field of view. Wider shows more terrain at once.": "Maes golygfa. Yn ehangach yn dangos mwy o dir ar unwaith.",
"Caps frames per second; a cap saves power and heat.": "Fframiau capiau yr eiliad; mae cap yn arbed pŵer a gwres.",
"Waits for the display's refresh: no tearing, a little latency.": "Aros am adnewyddu'r arddangosfa: dim rhwygo, ychydig o hwyrni.",
"Size of menus and the HUD.": "Maint y bwydlenni a'r HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Llyfn ymylon miniog. FXAA: meddalach. TAA: mae'n bosibl y bydd pethau llyfn, symudol yn dilyn.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Yn gwneud y byd yn llai ac yn ei ailadeiladu gyda TAA. Cyflymach, meddalach.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Yn miniogi'r darlun a uwch-raddiwyd. Uwch: ymylon cliriach, mwy o ddisgleirdeb symudol.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Allbwn HDR ar arddangosfa HDR: lafa, tân a golau haul yn disgleirio'n fwy disglair.",
"How frames reach the screen while VSync is off.": "Sut mae fframiau'n cyrraedd y sgrin tra bod VSync i ffwrdd.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Cysgu'n effeithlon tan y ffrâm nesaf; Troelli manwl gywir, fel fanila.",
"Fills the screen (borderless).": "Yn llenwi'r sgrin (heb ffiniau).",
"Brightens dark places.": "Yn goleuo lleoedd tywyll.",
"Lowers the frame rate when minimised, or idle too.": "Yn gostwng y gyfradd ffrâm pan gaiff ei lleihau, neu'n segur hefyd.",
"Sways the view while walking.": "Troi'r olygfa wrth gerdded.",
"Fades newly loaded chunks in.": "Yn pylu darnau newydd eu llwytho i mewn.",
"Darkens the screen's edges.": "Tywyllu ymylon y sgrin.",
"Shows when the world saves.": "Yn dangos pan fydd y byd yn arbed.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Mae'r gweinydd hwn mewn modd ar-lein: ni all proffiliau all-lein ymuno ag ef, mae angen cyfrif Minecraft ei hun ar bob chwaraewr.",
"horizon.splitscreen.own_account": "Mae'r gweinydd hwn angen cyfrif Minecraft ei hun ar bob chwaraewr",
"horizon.splitscreen.local_only": "Ni all chwaraewyr eraill ymuno â'r gweinydd hwn ond gyda'u cyfrif Minecraft eu hunain: mae proffiliau all-lein yn chwarae yn eich byd, ar LAN neu ar weinydd ar eich rhwydwaith lleol.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Yn cuddio modelau y tu ôl i flociau afloyw. Mae Async yn gwirio oddi ar yr edau; endidau tic.",
"Block Entities": "Endidau Bloc",
"Shulker Boxes": "Blychau Shulker",
"Reuses settled boxes; lid movement stays animated.": "Yn ailddefnyddio blychau sefydlog; symudiad caead yn aros yn animeiddiedig.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Agorwyd ar gyfer y sesiwn hon gan y rhaglen a ddechreuodd y gêm.",
"horizon.agent.socket": "Soced: %s (copïwch y manylion ar gyfer ei lwybr llawn)",
"horizon.agent.local_only": "Lleol yn unig: asiantau ar y cyfrifiadur hwn, byth y rhwydwaith.",
"%s nits": "%s nit",
"Auto (%s nits)": "Awtomatig (%s nit)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Yn cuddio modelau y tu ôl i flociau afloyw. Diweddariad endidau. I ffwrdd â phecynnau arferol.",
"Entity Culling Precheck": "Rhagwiriad Difa Endidau",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Yn rhedeg rhagwiriad AABB y mobs ar ôl hyn o fobs wedi'u llwytho. Mae sero yn ei analluogi.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Groft fjernt terræn i lokale verdener. Integrerede GPU'er stopper ved 128 bidder.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reduceret trækker langt grovere terræn: hurtigere på denne integrerede GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduceret trækker terrænet langt grovere, for GPU'er bliver det langsommere.",
"Field of view. Wider shows more terrain at once.": "Synsfelt. Bredere viser mere terræn på én gang.",
"Caps frames per second; a cap saves power and heat.": "Caps billeder per sekund; en hætte sparer strøm og varme.",
"Waits for the display's refresh: no tearing, a little latency.": "Venter på skærmens opdatering: ingen rivning, lidt forsinkelse.",
"Size of menus and the HUD.": "Størrelse på menuer og HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Udglatter takkede kanter. FXAA: blødere. TAA: de glatteste ting i bevægelse kan spore.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Gør verden mindre og genopbygger den med TAA. Hurtigere, blødere.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Gør det opskalerede billede skarpere. Højere: skarpere kanter, mere flimmer.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-output på en HDR-skærm: lava, ild og sollys skinner kraftigere.",
"How frames reach the screen while VSync is off.": "Hvordan rammer når skærmen, mens VSync er slukket.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Effektiv sover indtil næste billede; Præcise spins, som vanilje.",
"Fills the screen (borderless).": "Fylder skærmen (uden kant).",
"Brightens dark places.": "Lysner mørke steder.",
"Lowers the frame rate when minimised, or idle too.": "Sænker billedhastigheden, når den minimeres, eller også inaktiv.",
"Sways the view while walking.": "Svinger udsigten, mens du går.",
"Fades newly loaded chunks in.": "Fader nyindlæste bidder ind.",
"Darkens the screen's edges.": "Gør skærmens kanter mørkere.",
"Shows when the world saves.": "Viser, når verden redder.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Denne server er i onlinetilstand: offline-profiler kan ikke deltage, og hver spiller skal have sin egen Minecraft-konto.",
"horizon.splitscreen.own_account": "Denne server kræver, at hver spiller har sin egen Minecraft-konto",
"horizon.splitscreen.local_only": "Andre spillere kan kun deltage på denne server med deres egen Minecraft-konto: offline-profiler spiller i din verden, på LAN eller på en server på dit lokale netværk.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Gemmer modeller bag uigennemsigtige blokke. Asynkron checker off-thread; enheder krydser af.",
"Block Entities": "Bloker enheder",
"Shulker Boxes": "Shulker kasser",
"Reuses settled boxes; lid movement stays animated.": "Genbruger aflejrede kasser; lågets bevægelse forbliver animeret.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Åbnet til denne session af programmet, der startede spillet.",
"horizon.agent.socket": "Socket: %s (kopier detaljerne for dens fulde sti)",
"horizon.agent.local_only": "Kun lokalt: agenter på denne computer, aldrig netværket.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Gemmer modeller bag uigennemsigtige blokke. Enheder opdatering. Afsted med brugerdefinerede pakker.",
"Entity Culling Precheck": "Forudkontrol af entitetsnedskæring",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Kører AABB-forudkontrollen for mobs efter så mange indlæste mobs. Nul slår den fra.",
"%s mobs": "%s mobs",
@@ -415,6 +415,10 @@
"How far around you BlueMap tiles are downloaded. Next join.": "Wie weit um dich herum BlueMap-Kacheln heruntergeladen werden. Nächster Beitritt.",
"Hidden Faces": "Versteckte Flächen",
"Drops leaf faces behind two leaf layers: faster, same crowns.": "Lässt Blattflächen hinter zwei Laubschichten weg: schneller, gleiche Kronen.",
"%s nits": "%s Nits",
"Auto (%s nits)": "Auto (%s Nits)",
"%.2f nits": "%.2f Nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Versteckt Modelle hinter undurchsichtigen Blöcken. Entitäten aktualisieren sich. Aus bei benutzerdefinierten Paketen.",
"Entity Culling Precheck": "Objekt-Culling-Vorprüfung",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Führt die AABB-Vorprüfung für Kreaturen nach dieser Anzahl geladener Kreaturen aus. Null deaktiviert sie.",
"%s mobs": "%s Kreaturen",
@@ -428,6 +432,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grobes fernes Gelände in lokalen Welten. Integrierte GPUs: max. 128.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reduziert: fernes Gelände gröber, schneller auf dieser GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduziert: fernes Gelände gröber, für GPUs, die sonst bremsen.",
"Field of view. Wider shows more terrain at once.": "Sichtfeld. Ein größeres zeigt mehr Gelände auf einmal.",
"Caps frames per second; a cap saves power and heat.": "Begrenzt die Bilder pro Sekunde; spart Strom und Wärme.",
"Waits for the display's refresh: no tearing, a little latency.": "Wartet auf den Bildaufbau: kein Tearing, etwas Latenz.",
"Size of menus and the HUD.": "Größe der Menüs und des HUDs.",
@@ -461,11 +466,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Glättet Kanten. FXAA: weicher. TAA: am glattesten, evtl. Schlieren.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Rendert die Welt kleiner und baut sie mit TAA wieder auf. Schneller, weicher.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Schärft das hochskalierte Bild. Höher: schärfere Kanten, mehr Flimmern.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-Ausgabe auf HDR-Bildschirm: Lava, Feuer, Sonne heller.",
"How frames reach the screen while VSync is off.": "Wie Bilder auf den Bildschirm gelangen, wenn VSync aus ist.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Sparsam schläft bis zum nächsten Bild; Präzise wartet aktiv, wie in Vanilla.",
"Fills the screen (borderless).": "Füllt den Bildschirm (randlos).",
"Brightens dark places.": "Hellt dunkle Orte auf.",
"Lowers the frame rate when minimised, or idle too.": "Senkt die Bildrate bei Minimierung oder auch bei Inaktivität.",
"Sways the view while walking.": "Lässt die Ansicht beim Gehen schwanken.",
"Fades newly loaded chunks in.": "Blendet neu geladene Chunks ein.",
"Darkens the screen's edges.": "Dunkelt die Bildschirmränder ab.",
"Shows when the world saves.": "Zeigt an, wann die Welt gespeichert wird.",
@@ -563,6 +570,7 @@
"horizon.multiplayer.connected_friend_direct": "Direkt mit deinem Freund verbunden …",
"horizon.multiplayer.connected_friend_relay": "Über das Relay mit deinem Freund verbunden …",
"Culling": "Culling",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Versteckt Modelle hinter Blöcken. Prüfung im Hintergrund; Objekte laufen weiter.",
"Leaf Culling": "Laub-Culling",
"Every leaf face. Vanilla's fancy leaves.": "Jede Blattfläche, wie Minecraft sie bei schönen Blättern zeichnet.",
"Distant Plant Dither": "Pflanzen-Dithering",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Χοντρό μακρινό έδαφος σε τοπικούς κόσμους. Οι ενσωματωμένες GPU σταματούν στα 128 κομμάτια.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Μειωμένες έλξεις πολύ πιο χοντρό έδαφος: πιο γρήγορα σε αυτήν την ενσωματωμένη GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Οι μειωμένες έλξεις πολύ πιο τραχύ εδάφους, για τις GPU επιβραδύνουν.",
"Field of view. Wider shows more terrain at once.": "Οπτικό πεδίο. Το ευρύτερο δείχνει περισσότερο έδαφος ταυτόχρονα.",
"Caps frames per second; a cap saves power and heat.": "Καπάκια καρέ ανά δευτερόλεπτο. ένα καπάκι εξοικονομεί ενέργεια και θερμότητα.",
"Waits for the display's refresh: no tearing, a little latency.": "Περιμένει για την ανανέωση της οθόνης: χωρίς σκίσιμο, λίγο λανθάνουσα κατάσταση.",
"Size of menus and the HUD.": "Το μέγεθος των μενού και το HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Λειαίνει τις οδοντωτές άκρες. FXAA: πιο μαλακό. ΤΑΑ: τα πιο ομαλά, κινούμενα πράγματα μπορεί να ακολουθούν.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Καθιστά τον κόσμο μικρότερο και τον ξαναχτίζει με ΤΑΑ. Πιο γρήγορα, πιο μαλακά.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Κάνει πιο ευκρινή την αναβαθμισμένη εικόνα. Υψηλότερο: πιο καθαρές άκρες, περισσότερο τρεμόπαιγμα.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Έξοδος HDR σε οθόνη HDR: η λάβα, η φωτιά και το φως του ήλιου λάμπουν πιο έντονα.",
"How frames reach the screen while VSync is off.": "Πώς τα καρέ φτάνουν στην οθόνη ενώ το VSync είναι απενεργοποιημένο.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Αποτελεσματικοί ύπνοι μέχρι το επόμενο καρέ. Ακριβές περιστροφές, όπως η βανίλια.",
"Fills the screen (borderless).": "Γεμίζει την οθόνη (χωρίς περιθώρια).",
"Brightens dark places.": "Φωτίζει τα σκοτεινά μέρη.",
"Lowers the frame rate when minimised, or idle too.": "Μειώνει τον ρυθμό καρέ όταν είναι ελαχιστοποιημένος ή και σε αδράνεια.",
"Sways the view while walking.": "Κουνάει τη θέα ενώ περπατάτε.",
"Fades newly loaded chunks in.": "Ξεθωριάζει τα πρόσφατα φορτωμένα κομμάτια.",
"Darkens the screen's edges.": "Σκουραίνει τα άκρα της οθόνης.",
"Shows when the world saves.": "Δείχνει όταν ο κόσμος σώζει.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Αυτός ο διακομιστής είναι σε λειτουργία online: τα προφίλ εκτός σύνδεσης δεν μπορούν να συνδεθούν, κάθε παίκτης χρειάζεται τον δικό του λογαριασμό Minecraft.",
"horizon.splitscreen.own_account": "Αυτός ο διακομιστής χρειάζεται τον λογαριασμό Minecraft κάθε παίκτη",
"horizon.splitscreen.local_only": "Άλλοι παίκτες μπορούν να συνδεθούν σε αυτόν τον διακομιστή μόνο με τον δικό τους λογαριασμό Minecraft: τα προφίλ εκτός σύνδεσης παίζουν στον κόσμο σας, σε LAN ή σε διακομιστή στο τοπικό σας δίκτυο.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Κρύβει μοντέλα πίσω από αδιαφανή μπλοκ. Ασύγχρονοι έλεγχοι εκτός νήματος. οντότητες τικ.",
"Block Entities": "Αποκλεισμός οντοτήτων",
"Shulker Boxes": "Κουτιά Shulker",
"Reuses settled boxes; lid movement stays animated.": "Επαναχρησιμοποιεί τα καθιζημένα κουτιά. Η κίνηση του καπακιού παραμένει κινούμενη.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Άνοιξε για αυτήν την περίοδο λειτουργίας από το πρόγραμμα που ξεκίνησε το παιχνίδι.",
"horizon.agent.socket": "Υποδοχή: %s (αντιγράψτε τα στοιχεία για την πλήρη διαδρομή του)",
"horizon.agent.local_only": "Μόνο τοπικά: πράκτορες σε αυτόν τον υπολογιστή, ποτέ στο δίκτυο.",
"%s nits": "%s κόνιδες",
"Auto (%s nits)": "Αυτόματο (%s nits)",
"%.2f nits": "%.2f κόνιδες",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Κρύβει μοντέλα πίσω από αδιαφανή μπλοκ. Ενημέρωση οντοτήτων. Εκτός με προσαρμοσμένα πακέτα.",
"Entity Culling Precheck": "Προέλεγχος σφαγής οντοτήτων",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Εκτελεί τον προέλεγχο AABB όχλων μετά από τόσους φορτωμένους όχλους. Το μηδέν το απενεργοποιεί.",
"%s mobs": "%s όχλοι",
@@ -80,18 +80,6 @@
"horizon.controller.guide.pages": "Pages",
"horizon.controller.guide.categories": "Categories",
"horizon.controller.guide.tabs": "Tabs",
"horizon.touch.sprint": "Sprint",
"horizon.touch.jump": "Jump",
"horizon.touch.up": "Up",
"horizon.touch.down": "Down",
"horizon.touch.sneak": "Sneak",
"horizon.touch.dismount": "Dismount",
"horizon.touch.attack": "Attack",
"horizon.touch.use": "Use",
"horizon.touch.chat": "Chat",
"horizon.touch.settings": "Touch",
"horizon.touch.swap": "Swap",
"horizon.touch.shield": "Shield",
"horizon.options.lightbar": "Lightbar",
"horizon.options.look_sensitivity": "Look Sensitivity",
"horizon.options.invert_x": "Invert Look X",
@@ -328,7 +316,6 @@
"horizon.multiplayer.invite_code": "Invite Code",
"horizon.multiplayer.relay": "Relay (optional)",
"Preset": "Preset",
"Horizon Preset": "Horizon Preset",
"LOD Distance": "LOD Distance",
"Far Detail": "Far Detail",
"Cave Culling": "Cave Culling",
@@ -367,7 +354,6 @@
"Unlimited": "Unlimited",
"Auto": "Auto",
"Custom": "Custom",
"Full Performance": "Full Performance",
"Performance": "Performance",
"Balanced": "Balanced",
"Quality": "Quality",
@@ -415,6 +401,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reduced draws far terrain coarser: faster on this integrated GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduced draws far terrain coarser, for GPUs it slows down.",
"Field of view. Wider shows more terrain at once.": "Field of view. Wider shows more terrain at once.",
"Caps frames per second; a cap saves power and heat.": "Caps frames per second; a cap saves power and heat.",
"Waits for the display's refresh: no tearing, a little latency.": "Waits for the display's refresh: no tearing, a little latency.",
"Size of menus and the HUD.": "Size of menus and the HUD.",
@@ -455,11 +442,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Renders the world smaller and rebuilds it with TAA. Faster, softer.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Sharpens the upscaled picture. Higher: crisper edges, more shimmer.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR output on an HDR display: lava, fire and sunlight shine brighter.",
"How frames reach the screen while VSync is off.": "How frames reach the screen while VSync is off.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efficient sleeps until the next frame; Precise spins, like vanilla.",
"Fills the screen (borderless).": "Fills the screen (borderless).",
"Brightens dark places.": "Brightens dark places.",
"Lowers the frame rate when minimised, or idle too.": "Lowers the frame rate when minimised, or idle too.",
"Sways the view while walking.": "Sways the view while walking.",
"Fades newly loaded chunks in.": "Fades newly loaded chunks in.",
"Darkens the screen's edges.": "Darkens the screen's edges.",
"Shows when the world saves.": "Shows when the world saves.",
@@ -674,6 +663,7 @@
"horizon.splitscreen.online_only": "This server is in online mode: offline profiles can't join it, each player needs its own Minecraft account.",
"horizon.splitscreen.own_account": "This server needs each player's own Minecraft account",
"horizon.splitscreen.local_only": "Other players can join this server only with their own Minecraft account: offline profiles play in your world, on LAN or on a server on your local network.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Hides models behind opaque blocks. Async checks off-thread; entities tick.",
"Block Entities": "Block Entities",
"Shulker Boxes": "Shulker Boxes",
"Reuses settled boxes; lid movement stays animated.": "Reuses settled boxes; lid movement stays animated.",
@@ -691,8 +681,6 @@
"Reuses statue geometry until its block state changes.": "Reuses statue geometry until its block state changes.",
"Leaf Culling": "Leaf Culling",
"Every leaf face. Vanilla's fancy leaves.": "Every leaf face. Vanilla's fancy leaves.",
"Parallel Tick": "Parallel Tick",
"Shares your world's tick among threads. Auto: only while that is faster.": "Shares your world's tick among threads. Auto: only while that is faster.",
"Opaque Ice": "Opaque Ice",
"Draws ice in the solid pass, without its see-through texture.": "Draws ice in the solid pass, without its see-through texture.",
"Distant Plant Dither": "Distant Plant Dither",
@@ -719,9 +707,6 @@
"Pick a shader pack. Picking the one in use turns shaders off.": "Pick a shader pack. Picking the one in use turns shaders off.",
"Changed options apply with Apply, or when you leave.": "Changed options apply with Apply, or when you leave.",
"Pack settings": "Pack settings",
"Whole pack": "Whole pack",
"Reset all": "Reset all",
"Every option is at its default already.": "Every option is at its default already.",
"Built-in settings": "Built-in settings",
"%s settings": "%s settings",
"Settings made by the pack's author: they change only this pack.": "Settings made by the pack's author: they change only this pack.",
@@ -760,6 +745,10 @@
"horizon.agent.session_opened": "Opened for this session by the program that started the game.",
"horizon.agent.socket": "Socket: %s (copy the details for its full path)",
"horizon.agent.local_only": "Local only: agents on this computer, never the network.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Hides models behind opaque blocks. Entities update. Off with custom packs.",
"Entity Culling Precheck": "Entity Culling Precheck",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Runs the mob AABB precheck after this many loaded mobs. Zero disables it.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Kruda malproksima tereno en lokaj mondoj. Integritaj GPUoj ĉesas ĉe 128 pecoj.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reduktitaj tiradoj multe pli krudaj: pli rapide sur ĉi tiu integra GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduktita tirado multe pli kruda, por GPU-oj ĝi malrapidiĝas.",
"Field of view. Wider shows more terrain at once.": "Vidkampo. Pli larĝa montras pli da tereno samtempe.",
"Caps frames per second; a cap saves power and heat.": "Ĉapaj kadroj por sekundo; ĉapo ŝparas potencon kaj varmon.",
"Waits for the display's refresh: no tearing, a little latency.": "Atendas la refreŝigon de la ekrano: neniu ŝirado, iom da latenco.",
"Size of menus and the HUD.": "Grandeco de menuoj kaj la HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Glatigas dentitajn randojn. FXAA: pli mola. TAA: plej glate, moviĝantaj aferoj povas spuri.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Malgrandigas la mondon kaj rekonstruas ĝin per TAA. Faster, pli mola.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Akutigas la altskaligitan bildon. Pli alta: pli klaraj randoj, pli da trembrilo.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-eligo sur HDR-ekrano: lafo, fajro kaj sunlumo brilas pli hele.",
"How frames reach the screen while VSync is off.": "Kiel kadroj atingas la ekranon dum VSync estas malŝaltita.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efika dormas ĝis la sekva kadro; Precizaj turnoj, kiel vanilo.",
"Fills the screen (borderless).": "Plenigas la ekranon (senborda).",
"Brightens dark places.": "Heligas malhelajn lokojn.",
"Lowers the frame rate when minimised, or idle too.": "Malaltigas la framfrekvencon kiam minimumigita, aŭ neaktiva ankaŭ.",
"Sways the view while walking.": "Ŝancelas la vidon dum marŝado.",
"Fades newly loaded chunks in.": "Fadas lastatempe ŝarĝitajn pecojn.",
"Darkens the screen's edges.": "Malheligas la randojn de la ekrano.",
"Shows when the world saves.": "Montras kiam la mondo savas.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Ĉi tiu servilo estas en reta reĝimo: eksterretaj profiloj ne povas aliĝi, ĉiu ludanto bezonas sian propran Minecraft-konton.",
"horizon.splitscreen.own_account": "Ĉi tiu servilo bezonas la propran Minecraft-konton de ĉiu ludanto",
"horizon.splitscreen.local_only": "Aliaj ludantoj povas aliĝi al ĉi tiu servilo nur per sia propra Minecraft-konto: eksterretaj profiloj ludas en via mondo, en LAN aŭ en servilo en via loka reto.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Kaŝas modelojn malantaŭ maldiafanaj blokoj. Async kontrolas eksterfadenon; entoj tiktas.",
"Block Entities": "Blokaj Entoj",
"Shulker Boxes": "Ŝulkeraj Kestoj",
"Reuses settled boxes; lid movement stays animated.": "Reuzas fiksitajn skatolojn; klapomovo restas vigla.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Malfermita por ĉi tiu sesio de la programo kiu komencis la ludon.",
"horizon.agent.socket": "Ingo: %s (kopiu la detalojn por ĝia plena vojo)",
"horizon.agent.local_only": "Loka nur: agentoj sur ĉi tiu komputilo, neniam la reto.",
"%s nits": "%s nitoj",
"Auto (%s nits)": "Aŭtomata (%s nits)",
"%.2f nits": "%.2f nitoj",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Kaŝas modelojn malantaŭ maldiafanaj blokoj. Entoj ĝisdatigas. For per kutimaj pakoj.",
"Entity Culling Precheck": "Antaŭkontrolo de enta kaŝado",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Plenumas la antaŭkontrolon AABB de monstroj post tiom da ŝargitaj monstroj. Nulo malŝaltas ĝin.",
"%s mobs": "%s monstroj",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terreno lejano de baja resolución en mundos locales. Las GPU integradas se limitan a 128 chunks.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reducido dibuja el terreno lejano con menos detalle: más rápido en esta GPU integrada.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reducido dibuja el terreno lejano con menos detalle, para GPU a las que ralentiza.",
"Field of view. Wider shows more terrain at once.": "Campo de visión. Más amplio muestra más terreno a la vez.",
"Caps frames per second; a cap saves power and heat.": "Limita los fotogramas por segundo; un límite ahorra energía y calor.",
"Waits for the display's refresh: no tearing, a little latency.": "Espera al refresco de la pantalla: sin desgarro, algo de latencia.",
"Size of menus and the HUD.": "Tamaño de los menús y del HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Suaviza los bordes dentados. FXAA: más suave. TAA: el más suave, lo que se mueve puede dejar estela.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Renderiza el mundo más pequeño y lo reconstruye con TAA. Más rápido y más suave.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Aumenta la nitidez de la imagen reescalada. Más alto: bordes más nítidos y más parpadeo.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Salida HDR en una pantalla HDR: la lava, el fuego y la luz del sol brillan más.",
"How frames reach the screen while VSync is off.": "Cómo llegan los fotogramas a la pantalla con VSync desactivado.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Eficiente duerme hasta el siguiente fotograma; Preciso gira, como en vanilla.",
"Fills the screen (borderless).": "Llena la pantalla (sin bordes).",
"Brightens dark places.": "Ilumina los lugares oscuros.",
"Lowers the frame rate when minimised, or idle too.": "Reduce los fotogramas por segundo al minimizar o al estar inactivo.",
"Sways the view while walking.": "Balancea la vista al caminar.",
"Fades newly loaded chunks in.": "Hace aparecer gradualmente los chunks recién cargados.",
"Darkens the screen's edges.": "Oscurece los bordes de la pantalla.",
"Shows when the world saves.": "Muestra cuándo se guarda el mundo.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Este servidor está en modo en línea: los perfiles sin conexión no pueden unirse; cada jugador necesita su propia cuenta de Minecraft.",
"horizon.splitscreen.own_account": "Este servidor requiere la cuenta de Minecraft de cada jugador",
"horizon.splitscreen.local_only": "Otros jugadores solo pueden unirse a este servidor con su propia cuenta de Minecraft: los perfiles sin conexión juegan en tu mundo, en LAN o en un servidor de tu red local.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Oculta modelos tras bloques opacos. Asíncrono comprueba fuera del hilo; las entidades se actualizan.",
"Block Entities": "Entidades de bloque",
"Shulker Boxes": "Cajas de shulker",
"Reuses settled boxes; lid movement stays animated.": "Reutiliza las cajas quietas; el movimiento de la tapa sigue animado.",
@@ -634,6 +638,10 @@
"horizon.agent.session_opened": "Abierto para esta sesión por el programa que inició el juego.",
"horizon.agent.socket": "Socket: %s (copia los datos para ver su ruta completa)",
"horizon.agent.local_only": "Solo local: agentes en este equipo, nunca la red.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automático (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Oculta modelos tras bloques opacos. Las entidades se actualizan. Desactivado con paquetes personalizados.",
"Entity Culling Precheck": "Comprobación previa de oclusión de entidades",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Ejecuta la comprobación previa del AABB de los mobs tras esta cantidad de mobs cargados. Cero la desactiva.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Jäme kauge maastik kohalikes maailmades. Integreeritud GPU-de arv on 128 tükki.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Vähendatud joonistab maastikul jämedam: kiirem selle integreeritud GPU-ga.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Vähendatud tõmbab maastikku jämedamalt, GPU-de puhul aeglustab.",
"Field of view. Wider shows more terrain at once.": "Vaateväli. Laiem näitab korraga rohkem maastikku.",
"Caps frames per second; a cap saves power and heat.": "Caps kaadrit sekundis; kork säästab elektrit ja soojust.",
"Waits for the display's refresh: no tearing, a little latency.": "Ootab ekraani värskendust: ei rebene, väike latentsus.",
"Size of menus and the HUD.": "Menüüde suurus ja HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Silustab sakilised servad. FXAA: pehmem. TAA: kõige sujuvamad, liikuvad asjad võivad järele jääda.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Muudab maailma väiksemaks ja ehitab selle TAA abil uuesti üles. Kiirem, pehmem.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Teravdab suurendatud pilti. Kõrgem: selgemad servad, rohkem virvendust.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-väljund HDR-ekraanil: laava, tuli ja päikesevalgus säravad eredamalt.",
"How frames reach the screen while VSync is off.": "Kuidas raamid ekraanile jõuavad, kui VSync on välja lülitatud.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Tõhusad magamised kuni järgmise kaadrini; Täpsed keerutused, nagu vanilje.",
"Fills the screen (borderless).": "Täidab ekraani (ääristeta).",
"Brightens dark places.": "Teeb tumedad kohad heledamaks.",
"Lowers the frame rate when minimised, or idle too.": "Vähendab kaadrisagedust, kui see on minimeeritud või ka tühikäigul.",
"Sways the view while walking.": "Kõndib kõndides vaadet.",
"Fades newly loaded chunks in.": "Peidab äsja laaditud tükid sisse.",
"Darkens the screen's edges.": "Tumendab ekraani servi.",
"Shows when the world saves.": "Näitab, millal maailm päästab.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "See server on võrgurežiimis: võrguühenduseta profiilid ei saa sellega liituda, iga mängija vajab oma Minecrafti kontot.",
"horizon.splitscreen.own_account": "See server vajab iga mängija oma Minecrafti kontot",
"horizon.splitscreen.local_only": "Teised mängijad saavad selle serveriga liituda ainult oma Minecrafti kontoga: võrguühenduseta profiilid mängivad sinu maailmas, LAN-is või sinu kohaliku võrgu serveris.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Peidab mudelid läbipaistmatute plokkide taha. Async kontrollib lõimevälist; olemid tiksuvad.",
"Block Entities": "Blokeeri üksused",
"Shulker Boxes": "Shulkeri karbid",
"Reuses settled boxes; lid movement stays animated.": "Taaskasutab settinud kaste; kaane liikumine jääb animeeritud.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Selle seansi jaoks avas mängu käivitanud programm.",
"horizon.agent.socket": "Pistikupesa: %s (kopeerige selle täieliku tee üksikasjad)",
"horizon.agent.local_only": "Ainult kohalik: selles arvutis olevad agendid, mitte kunagi võrk.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automaatne (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Peidab mudelid läbipaistmatute plokkide taha. Olemite värskendamine. Väljas kohandatud pakkidega.",
"Entity Culling Precheck": "Üksuste kärpimise eelkontroll",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Käivitab mobide AABB eelkontrolli pärast nii paljude mobide laadimist. Null lülitab selle välja.",
"%s mobs": "%s mobi",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Urruneko lur lodia tokiko munduetan. GPU integratuak 128 zatitan gelditzen dira.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Marrazki murrizketak lur urrunago lodiagoak: azkarrago GPU integratu honetan.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Marrazki murriztuak lur urrunago lodiagoak dira, GPUentzat moteldu egiten da.",
"Field of view. Wider shows more terrain at once.": "Ikus-eremua. Zabalerak lur gehiago erakusten du aldi berean.",
"Caps frames per second; a cap saves power and heat.": "Maiuskulak segundoko fotogramak; txano batek energia eta beroa aurrezten ditu.",
"Waits for the display's refresh: no tearing, a little latency.": "Pantaila freskatzeko zain dago: urratu gabe, latentzia pixka bat.",
"Size of menus and the HUD.": "Menuen tamaina eta HUD-a.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Ertz bitxiak leuntzen ditu. FXAA: bigunagoa. TAA: leunena, mugitzen diren gauzak atzetik joan daitezke.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Mundua txikiagotzen du eta TAArekin berreraikitzen du. Azkarrago, leunagoa.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Handitutako irudia zorrozten du. Handiagoa: ertz zorrotzagoak, dirdira gehiago.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR irteera HDR pantaila batean: labak, sua eta eguzki-argiak distiratsuagoak dira.",
"How frames reach the screen while VSync is off.": "Nola iristen diren fotogramak pantailara VSync itzalita dagoen bitartean.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Lo eraginkorra hurrengo fotograma arte; Bira zehatzak, bainila bezala.",
"Fills the screen (borderless).": "Pantaila betetzen du (ertzak gabe).",
"Brightens dark places.": "Leku ilunak argitzen ditu.",
"Lowers the frame rate when minimised, or idle too.": "Fotograma-abiadura murrizten du minimizatzen denean, edo inaktibo ere.",
"Sways the view while walking.": "Ikuspegia aldarazi egiten du oinez ibiltzean.",
"Fades newly loaded chunks in.": "Kargatutako zati berriak lausotzen ditu.",
"Darkens the screen's edges.": "Pantailaren ertzak iluntzen ditu.",
"Shows when the world saves.": "Munduak salbatzen duenean erakusten du.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Zerbitzari hau lineako moduan dago: lineaz kanpoko profilek ezin dute sartu, jokalari bakoitzak bere Minecraft kontua behar du.",
"horizon.splitscreen.own_account": "Zerbitzari honek jokalari bakoitzaren Minecraft kontua behar du",
"horizon.splitscreen.local_only": "Beste jokalariek beren Minecraft kontuarekin soilik sar daitezke zerbitzari honetan: lineaz kanpoko profilek zure munduan jokatzen dute, LANean edo zure tokiko sareko zerbitzari batean.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Bloke opakuen atzean ereduak ezkutatzen ditu. Async egiaztapenak off-thread; entitateak markatuta.",
"Block Entities": "Blokeatu Entitateak",
"Shulker Boxes": "Shulker Kutxak",
"Reuses settled boxes; lid movement stays animated.": "Kutxa finkatuak berrerabili; estalkien mugimendua animatuta geratzen da.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Saio honetarako irekia jokoa hasi zuen programak.",
"horizon.agent.socket": "Socketa: %s (kopiatu bere bide osoaren xehetasunak)",
"horizon.agent.local_only": "Tokiko soilik: ordenagailu honetako agenteak, inoiz ez sarekoak.",
"%s nits": "%s nit",
"Auto (%s nits)": "Autoa (%s nit)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Bloke opakuen atzean ereduak ezkutatzen ditu. Entitateak eguneratzea. Off pakete pertsonalizatuekin.",
"Entity Culling Precheck": "Entitate-mozketaren aurre-egiaztapena",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Mob AABB aurre-egiaztapena kargatutako mob kopuru honen ondoren exekutatzen du. Zeroak desaktibatzen du.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "زمین های درشت دور در جهان های محلی. پردازنده های گرافیکی مجتمع در 128 تکه متوقف می شوند.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "کشش های کمتر در زمین های دور درشت تر: در این GPU یکپارچه سریع تر.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "کشش های کمتر در زمین های دور درشت تر است، برای پردازنده های گرافیکی سرعت آن کاهش می یابد.",
"Field of view. Wider shows more terrain at once.": "میدان دید. عریض تر، زمین های بیشتری را به یکباره نشان می دهد.",
"Caps frames per second; a cap saves power and heat.": "فریم بر ثانیه یک کلاه باعث صرفه جویی در انرژی و گرما می شود.",
"Waits for the display's refresh: no tearing, a little latency.": "منتظر تازه شدن نمایشگر است: بدون پارگی، کمی تأخیر.",
"Size of menus and the HUD.": "اندازه منوها و HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "لبه های دندانه دار را صاف می کند. FXAA: نرم تر. TAA: نرم ترین و متحرک ترین چیزها ممکن است دنبال شوند.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "جهان را کوچکتر می کند و آن را با TAA بازسازی می کند. سریع تر، نرم تر.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "تصویر ارتقایافته را تیز می‌کند. بیشتر: لبه‌های واضح‌تر، درخشش بیشتر.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "خروجی HDR در صفحه نمایش HDR: گدازه، آتش و نور خورشید روشن تر می تابد.",
"How frames reach the screen while VSync is off.": "چگونه فریم‌ها در حالی که VSync خاموش است به صفحه نمایش می‌رسند.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "خواب های کارآمد تا فریم بعدی. چرخش دقیق، مانند وانیل.",
"Fills the screen (borderless).": "صفحه را پر می کند (بدون حاشیه).",
"Brightens dark places.": "مکان های تاریک را روشن می کند.",
"Lowers the frame rate when minimised, or idle too.": "در صورت به حداقل رساندن یا بیکار بودن، نرخ فریم را کاهش می دهد.",
"Sways the view while walking.": "هنگام راه رفتن منظره را تغییر می دهد.",
"Fades newly loaded chunks in.": "تکه های تازه بارگذاری شده را محو می کند.",
"Darkens the screen's edges.": "لبه های صفحه نمایش را تیره می کند.",
"Shows when the world saves.": "زمانی نشان می دهد که جهان نجات می دهد.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "این سرور در حالت آنلاین است: نمایه‌های آفلاین نمی‌توانند بپیوندند، هر بازیکن به حساب Minecraft خودش نیاز دارد.",
"horizon.splitscreen.own_account": "این سرور به حساب Minecraft هر بازیکن نیاز دارد",
"horizon.splitscreen.local_only": "بازیکنان دیگر فقط با حساب Minecraft خودشان می‌توانند به این سرور بپیوندند: نمایه‌های آفلاین در دنیای شما، در LAN یا در سروری در شبکه محلی‌تان بازی می‌کنند.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "مدل ها را پشت بلوک های مات پنهان می کند. Async بررسی های خارج از موضوع. موجودیت ها تیک می زنند.",
"Block Entities": "مسدود کردن نهادها",
"Shulker Boxes": "جعبه های شولکر",
"Reuses settled boxes; lid movement stays animated.": "از جعبه های ته نشین شده مجدد استفاده می کند. حرکت درب متحرک باقی می ماند.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "برای این جلسه توسط برنامه شروع کننده بازی باز شد.",
"horizon.agent.socket": "سوکت: %s (جزئیات را برای مسیر کامل آن کپی کنید)",
"horizon.agent.local_only": "فقط محلی: عوامل روی این رایانه، هرگز شبکه.",
"%s nits": "%s نیت",
"Auto (%s nits)": "خودکار (%s نیت)",
"%.2f nits": "%.2f نیت",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "مدل ها را پشت بلوک های مات پنهان می کند. به روز رسانی نهادها خاموش با بسته های سفارشی.",
"Entity Culling Precheck": "پیش‌بررسی کالینگ موجودیت",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "پیش‌بررسی AABB موجودات را پس از این تعداد موجود بارگذاری‌شده اجرا می‌کند. صفر آن را غیرفعال می‌کند.",
"%s mobs": "%s موجود",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Karkea etäinen maasto paikallisissa maailmoissa. Integroidut GPU:t pysähtyvät 128 palaan.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Vähentynyt piirtää paljon karkeampaa maastoa: nopeampi tällä integroidulla grafiikkasuorittimella.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduced piirtää paljon maastoa karkeammin, GPU:illa se hidastaa.",
"Field of view. Wider shows more terrain at once.": "Näkökenttä. Leveämpi näyttää enemmän maastoa kerralla.",
"Caps frames per second; a cap saves power and heat.": "Caps ruutua sekunnissa; korkki säästää sähköä ja lämpöä.",
"Waits for the display's refresh: no tearing, a little latency.": "Odottaa näytön päivitystä: ei repeytymistä, pieni latenssi.",
"Size of menus and the HUD.": "Valikkojen koko ja HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Tasoittaa rosoiset reunat. FXAA: pehmeämpi. TAA: Tasaisimmat, liikkuvat asiat voivat seurata.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Pienentää maailmaa ja rakentaa sen uudelleen TAA:lla. Nopeampi, pehmeämpi.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Terävöittää skaalattua kuvaa. Korkeampi: terävämmät reunat, enemmän värettä.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-lähtö HDR-näytöllä: laava, tuli ja auringonvalo loistavat kirkkaammin.",
"How frames reach the screen while VSync is off.": "Kuinka kehykset saavuttavat näytön, kun VSync on pois päältä.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Tehokkaat unet seuraavaan ruutuun asti; Tarkat pyöräytykset, kuten vanilja.",
"Fills the screen (borderless).": "Täyttää näytön (reunaton).",
"Brightens dark places.": "Kirkastaa pimeitä paikkoja.",
"Lowers the frame rate when minimised, or idle too.": "Alentaa kuvataajuutta minimoituna tai myös tyhjäkäynnillä.",
"Sways the view while walking.": "Heiluttaa näkymää kävellessä.",
"Fades newly loaded chunks in.": "Häivyttää juuri ladatut palat sisään.",
"Darkens the screen's edges.": "Tummentaa näytön reunoja.",
"Shows when the world saves.": "Näyttää, milloin maailma pelastaa.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Tämä palvelin on online-tilassa: offline-profiilit eivät voi liittyä siihen, jokainen pelaaja tarvitsee oman Minecraft-tilinsä.",
"horizon.splitscreen.own_account": "Tämä palvelin vaatii jokaiselle pelaajalle oman Minecraft-tilin",
"horizon.splitscreen.local_only": "Muut pelaajat voivat liittyä tähän palvelimeen vain omalla Minecraft-tilillään: offline-profiilit pelaavat maailmassasi lähiverkossa tai paikallisverkkosi palvelimella.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Piilottaa mallit läpinäkymättömien lohkojen taakse. Async tarkistaa säiettä; entiteetit tikittää.",
"Block Entities": "Estä entiteetit",
"Shulker Boxes": "Shulker laatikot",
"Reuses settled boxes; lid movement stays animated.": "Käyttää uudelleen laskeutuneita laatikoita; kannen liike pysyy animoituna.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Pelin aloittaneen ohjelman avaa tälle istunnolle.",
"horizon.agent.socket": "Socket: %s (kopioi sen koko polun tiedot)",
"horizon.agent.local_only": "Vain paikalliset: agentit tällä tietokoneella, ei koskaan verkko.",
"%s nits": "%s nitiä",
"Auto (%s nits)": "Automaattinen (%s nits)",
"%.2f nits": "%.2f nitiä",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Piilottaa mallit läpinäkymättömien lohkojen taakse. Kokonaisuudet päivitys. Pois mukautetuilla pakkauksilla.",
"Entity Culling Precheck": "Entiteettien karsinnan esitarkistus",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Suorittaa mobien AABB-esitarkistuksen tämän määrän ladattuja mobeja jälkeen. Nolla poistaa sen käytöstä.",
"%s mobs": "%s mobia",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Magaspang na malayong lupain sa mga lokal na mundo. Humihinto ang mga pinagsamang GPU sa 128 chunks.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Ang pinababang kumukuha ng malayong lupain ay mas magaspang: mas mabilis sa pinagsamang GPU na ito.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Ang pinababang kumukuha ng malayong lupain ay mas magaspang, para sa mga GPU ay bumagal ito.",
"Field of view. Wider shows more terrain at once.": "Larangan ng pananaw. Ang mas malawak ay nagpapakita ng mas maraming lupain nang sabay-sabay.",
"Caps frames per second; a cap saves power and heat.": "I-cap ang mga frame sa bawat segundo; ang takip ay nakakatipid ng kuryente at init.",
"Waits for the display's refresh: no tearing, a little latency.": "Naghihintay para sa pag-refresh ng display: walang punit, kaunting latency.",
"Size of menus and the HUD.": "Sukat ng mga menu at ang HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Makinis ang tulis-tulis na mga gilid. FXAA: mas malambot. TAA: Ang pinakamakinis, gumagalaw na mga bagay ay maaaring masunod.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Ginagawang mas maliit ang mundo at muling itinatayo ito gamit ang TAA. Mas mabilis, mas malambot.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Pinatatalas ang naka-upscale na larawan. Mas mataas: mas matalas na gilid, mas maraming shimmer.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR na output sa isang HDR display: lava, apoy at sikat ng araw ay kumikinang nang mas maliwanag.",
"How frames reach the screen while VSync is off.": "Paano naaabot ng mga frame ang screen habang naka-off ang VSync.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Mahusay na pagtulog hanggang sa susunod na frame; Mga tumpak na pag-ikot, tulad ng vanilla.",
"Fills the screen (borderless).": "Pinuno ang screen (walang hangganan).",
"Brightens dark places.": "Nagpapaliwanag ng mga madilim na lugar.",
"Lowers the frame rate when minimised, or idle too.": "Ibinababa ang frame rate kapag pinaliit, o idle din.",
"Sways the view while walking.": "Iniindayog ang tanawin habang naglalakad.",
"Fades newly loaded chunks in.": "Nagfades ang mga bagong na-load na chunks.",
"Darkens the screen's edges.": "Pinadidilim ang mga gilid ng screen.",
"Shows when the world saves.": "Ipinapakita kung kailan nagliligtas ang mundo.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Nasa online mode ang server na ito: hindi makakasali ang mga offline na profile, kailangan ng bawat manlalaro ng sarili niyang Minecraft account.",
"horizon.splitscreen.own_account": "Kailangan ng server na ito ng sariling Minecraft account ng bawat manlalaro",
"horizon.splitscreen.local_only": "Makakasali lamang ang ibang manlalaro sa server na ito gamit ang sarili nilang Minecraft account: ang mga offline na profile ay naglalaro sa iyong mundo, sa LAN o sa isang server sa iyong lokal na network.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Itinatago ang mga modelo sa likod ng mga opaque na bloke. Sinusuri ng Async ang off-thread; lagyan ng tsek ang mga entidad.",
"Block Entities": "I-block ang mga Entity",
"Shulker Boxes": "Mga Kahon ng Shulker",
"Reuses settled boxes; lid movement stays animated.": "Muling ginagamit ang mga nakaayos na kahon; nananatiling animated ang paggalaw ng talukap ng mata.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Binuksan para sa session na ito ng program na nagsimula ng laro.",
"horizon.agent.socket": "Socket: %s (kopyahin ang mga detalye para sa buong path nito)",
"horizon.agent.local_only": "Lokal lamang: mga ahente sa computer na ito, hindi sa network.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Itinatago ang mga modelo sa likod ng mga opaque na bloke. Pag-update ng mga entity. I-off gamit ang mga custom na pack.",
"Entity Culling Precheck": "Paunang Pagsusuri ng Pag-cull ng Entity",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Pinapatakbo ang AABB precheck ng mob pagkatapos ng ganitong karaming na-load na mob. Pinapatay ito ng zero.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grovt fjarskotið lendi í lokalum heimum. Integreraðir GPU'ar steðga á 128 klumpum.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Minkað dregur langt lendi grovari: skjótari á hesum integreraða GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Minkað dregur langt lendið grovari, fyri GPU'ar tað bremsar.",
"Field of view. Wider shows more terrain at once.": "Sjónarringur. Breiðari vísir meira lendi í senn.",
"Caps frames per second; a cap saves power and heat.": "Hettar rammur um sekundið; hetta sparir streym og hita.",
"Waits for the display's refresh: no tearing, a little latency.": "Bíðar eftir at skjárin verður uppdateraður: einki rív, eitt sindur av latency.",
"Size of menus and the HUD.": "Stødd á valmyndum og HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Slættar snøggaðar kantar. FXAA: mjúkari. TAA: slættast, rørandi ting kunnu slóða.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Ger heimin minni og umbyggir hann við TAA. Skjótari, mjúkari.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Ger uppstillaðu myndina skýrari. Hægri: skarpari kantar, meira glitran.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR útgangur á HDR skjái: lava, eldur og sólarljós skína ljósari.",
"How frames reach the screen while VSync is off.": "Hvussu rammur røkka skerminum meðan VSync er sløkt.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Effektivur svevur til næstu rammu; Nágreinilig snúningar, sum vanilja.",
"Fills the screen (borderless).": "Fyllir skermin (markleysur).",
"Brightens dark places.": "Lýsir myrk støð.",
"Lowers the frame rate when minimised, or idle too.": "Lækkar rammufrekvensin tá hon er minkað, ella idle eisini.",
"Sways the view while walking.": "Sveiggjar útsýnið, meðan tú gongur.",
"Fades newly loaded chunks in.": "Doyvir nýlastaðar klumpar í.",
"Darkens the screen's edges.": "Myrkir kantarnar á skerminum.",
"Shows when the world saves.": "Vísir tá heimurin bjargar.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Hesin ambætarin er í online-stilling: offline-profilar kunnu ikki melda seg til hann, hvør spælari hevur brúk fyri síni egnu Minecraft kontu.",
"horizon.splitscreen.own_account": "Hesin ambætarin hevur brúk fyri hvørjum spælara egna Minecraft kontu",
"horizon.splitscreen.local_only": "Aðrir spælarar kunnu bert melda seg til hendan ambætaran við egnari Minecraft konto: offline profilar spæla í tínum heimi, á LAN ella á einum ambætara á tínum lokala neti.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Goymir modellir aftan fyri ógjøgnumskygdar blokkar. Async kannar uttan fyri tráðin; eindir merkja.",
"Block Entities": "Blokk eindir",
"Shulker Boxes": "Shulker kassar",
"Reuses settled boxes; lid movement stays animated.": "Endurnýtir avgjørdar kassar; lok rørslan heldur seg lívgaða.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Opnað fyri hesa setuna av skránni sum byrjaði dystin.",
"horizon.agent.socket": "Socket: %s (kopiera smálutirnar fyri alla leiðina)",
"horizon.agent.local_only": "Einans lokalt: umboðsmenn á hesi telduni, ongantíð netið.",
"%s nits": "%s nitur",
"Auto (%s nits)": "Sjálvvirkandi (%s nits)",
"%.2f nits": "%.2f nitur",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Goymir modellir aftan fyri ógjøgnumskygdar blokkar. Eindir dagførast. Av við sersniðgivnum pakkum.",
"Entity Culling Precheck": "Forkanning av eindarskurði",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Koyrir AABB-forkanningina av mobbum eftir hesi nógvar lastaðar mobbar. Null sløkkir tað.",
"%s mobs": "%s mobbar",
@@ -309,6 +309,9 @@
"Draws ice in the solid pass, without its see-through texture.": "Dessine la glace dans la passe solide, sans sa texture transparente.",
"Hidden Faces": "Faces cachées",
"Drops leaf faces behind two leaf layers: faster, same crowns.": "Supprime les faces de feuilles derrière deux couches de feuilles : plus rapide, mêmes houppiers.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Entity Culling Precheck": "Pré-vérification du culling des entités",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Lance la pré-vérification AABB des créatures après ce nombre de créatures chargées. Zéro la désactive.",
"%s mobs": "%s créatures",
@@ -322,6 +325,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terrain lointain simplifié, mondes locaux. GPU intégrés : 128 max.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Réduit : terrain lointain simplifié, plus rapide sur ce GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Réduit : terrain simplifié, pour les GPU qui ralentissent.",
"Field of view. Wider shows more terrain at once.": "Champ de vision. Plus large, il montre plus de terrain à la fois.",
"Caps frames per second; a cap saves power and heat.": "Limite les images par seconde ; économise énergie et chaleur.",
"Waits for the display's refresh: no tearing, a little latency.": "Attend l'écran : pas de déchirure, un peu de latence.",
"Size of menus and the HUD.": "Taille des menus et de l'interface (HUD).",
@@ -354,11 +358,13 @@
"World pixels per screen pixel. Below 100% is faster on the GPU.": "Pixels du monde par pixel d'écran. Sous 100 %, GPU plus rapide.",
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Lisse les bords. FXAA : doux. TAA : lisse, traînées possibles.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Rendu réduit, reconstruit par TAA. Plus rapide, plus doux.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Sortie HDR sur écran HDR : lave, feu et soleil plus vifs.",
"How frames reach the screen while VSync is off.": "Comment les images arrivent à l'écran sans synchro verticale.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Économe attend l'image suivante ; Précis tourne en boucle.",
"Fills the screen (borderless).": "Remplit l'écran (sans bordure).",
"Brightens dark places.": "Éclaircit les endroits sombres.",
"Lowers the frame rate when minimised, or idle too.": "Réduit les FPS si la fenêtre est réduite, ou aussi inactive.",
"Sways the view while walking.": "Fait osciller la vue pendant la marche.",
"Fades newly loaded chunks in.": "Fait apparaître en fondu les chunks nouvellement chargés.",
"Darkens the screen's edges.": "Assombrit les bords de l'écran.",
"Shows when the world saves.": "Indique quand le monde est sauvegardé.",
@@ -524,6 +530,7 @@
"horizon.splitscreen.own_account": "Ce serveur demande un compte Minecraft par joueur",
"horizon.splitscreen.local_only": "Les autres joueurs ne peuvent rejoindre ce serveur qu'avec leur propre compte Minecraft : les profils hors ligne jouent dans votre monde, en LAN ou sur un serveur de votre réseau local.",
"Culling": "Occlusion",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Masque les modèles derrière les blocs opaques. Vérification en arrière-plan ; les entités continuent.",
"Leaf Culling": "Occlusion feuillage",
"Every leaf face. Vanilla's fancy leaves.": "Toutes les faces de feuillage, comme les feuilles détaillées de Minecraft.",
"Distant Plant Dither": "Tramage des plantes",
@@ -697,6 +704,7 @@
"Reuses poles; flags and pattern layers still update.": "Réutilise les mâts ; les drapeaux et calques de motifs continuent de se mettre à jour.",
"Copper Golem Statues": "Statues de golem de cuivre",
"Reuses statue geometry until its block state changes.": "Réutilise la géométrie de la statue jusqu'à ce que son état de bloc change.",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Masque les modèles derrière les blocs opaques. Les entités se mettent à jour. Désactivé avec les packs personnalisés.",
"horizon.extras.repro_keys": "Raccourcis d'enregistrement",
"horizon.extras.repro_keys.tooltip": "F3+R démarre ou arrête un enregistrement de reproduction et F3+E écrit son archive. Désactivé par défaut : un enregistrement copie le monde.",
"horizon.agent.record_session": "Démarrer la session d'enregistrement",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terrens lontans grossiers tai monts locâi. I GPU integrâts a si fermin a 128 tocs.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Ridot al tire un teren une vore plui gros: plui veloç su chest GPU integrât.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "La riduzion e puarte il teren plui gros, pai GPU al ralente.",
"Field of view. Wider shows more terrain at once.": "Camp di viodi. Plui larc al mostre plui teren une volte.",
"Caps frames per second; a cap saves power and heat.": "Caps cuadris par secont; un capel al sparagne energjie e calôr.",
"Waits for the display's refresh: no tearing, a little latency.": "Al spete il rinfresc dal display: no straçadure, un pocje di latence.",
"Size of menus and the HUD.": "Dimension dai menus e dal HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Lissâ i ôrs sgjavâts. FXAA: plui morbide. TAA: lis robis plui lissis e in moviment a puedin traciâ.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Al rint il mont plui piçul e lu torne a costruî cun TAA. Plui veloç, plui morbide.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Al nitidìs la imagjine ridimensionade. Plui alt: oris plui netis, plui sflandôr.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Uscite HDR suntun display HDR: lave, fûc e lûs dal soreli a lusin plui.",
"How frames reach the screen while VSync is off.": "Come che i cuadris a rivin sul schermi intant che VSync al è spent.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Eficient al durmìs fin al cuadri sucessîf; Giris precîsis, come la vanilie.",
"Fills the screen (borderless).": "Al jemple il schermi (cence confins).",
"Brightens dark places.": "Al ilumine i lûcs scurts.",
"Lowers the frame rate when minimised, or idle too.": "Al sbasse la frecuence di fotograms cuant che al è minimizât, o ancje inatîf.",
"Sways the view while walking.": "Oscilâ la viste intant che si cjamine.",
"Fades newly loaded chunks in.": "Svanìs i tocs gnûfs cjargâts dentri.",
"Darkens the screen's edges.": "Scure i ôrs dal schermi.",
"Shows when the world saves.": "Al mostre cuant che il mont al salve.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Chest servidôr al è in modalitât online: i profîi offline no puedin jentrâ, ogni zuiadôr al à bisugne dal so conto Minecraft.",
"horizon.splitscreen.own_account": "Chest servidôr al à bisugne dal conto Minecraft di ogni zuiadôr",
"horizon.splitscreen.local_only": "Altris zuiadôrs a puedin jentrâ in chest servidôr dome cul lôr conto Minecraft: i profîi offline a zuiin tal to mont, su LAN o suntun servidôr su la tô rêt locâl.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Scuind i modei daûr di blocs opacs. Async al controle fûr dal fil; entitâts segn.",
"Block Entities": "Entitâts di bloc",
"Shulker Boxes": "Scatolis Shulker",
"Reuses settled boxes; lid movement stays animated.": "Riutilizâ lis cjasis stabilidis; il moviment dal cuviert al reste animât.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Viert par cheste session dal program che al à scomençât il zûc.",
"horizon.agent.socket": "Prese: %s (copiâ i detais pal so percors complet)",
"horizon.agent.local_only": "Dome locâl: agjents su chest ordenadôr, mai la rêt.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automatic (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Scuind i modei daûr di blocs opacs. Agjiornament des entitâts. Off cun pachetis personalizadis.",
"Entity Culling Precheck": "Precontrole de liminazion des entitâts",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Al fâs il precontrole AABB dai mobs dopo che chest tante mobs a son cjariadis. Zero al lu disabilite.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grof fier terrein yn lokale wrâlden. Yntegreare GPU's stopje by 128 brokken.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Fermindere lûkt fier terrein grofter: flugger op dizze yntegrearre GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Fermindere lûkt fier terrein grofter, foar GPUs it fertraagt.",
"Field of view. Wider shows more terrain at once.": "Gesichtsfjild. Wider toant mear terrein tagelyk.",
"Caps frames per second; a cap saves power and heat.": "Caps frames per sekonde; in pet besparret macht en waarmte.",
"Waits for the display's refresh: no tearing, a little latency.": "Wachtet op it ferfarskjen fan it display: gjin tearing, in bytsje latency.",
"Size of menus and the HUD.": "Grutte fan menu's en de HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Smakket skerpe rânen. FXAA: sêfter. TAA: soepelste, bewegende dingen kinne trailje.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Makket de wrâld lytser en bout it opnij mei TAA. Sneller, sêfter.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Meitsje it opskale byld skerper. Heger: skerpere rânen, mear shimmer.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-útfier op in HDR-display: lava, fjoer en sinneljocht skine helderder.",
"How frames reach the screen while VSync is off.": "Hoe frames it skerm berikke wylst VSync út is.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Effisjinte sliept oant it folgjende frame; Precise spins, lykas vanille.",
"Fills the screen (borderless).": "Folt it skerm (rânleas).",
"Brightens dark places.": "Ferljochtet tsjustere plakken.",
"Lowers the frame rate when minimised, or idle too.": "Ferleget de framerate as minimalisearre, of ek idle.",
"Sways the view while walking.": "Swaait it útsicht by it kuierjen.",
"Fades newly loaded chunks in.": "Fades nij laden brokken yn.",
"Darkens the screen's edges.": "Fertsjustert de rânen fan it skerm.",
"Shows when the world saves.": "Toant wannear't de wrâld rêdt.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Dizze tsjinner stiet yn online modus: offline-profylen kinne net meidwaan, elke spiler hat syn eigen Minecraft-akkount nedich.",
"horizon.splitscreen.own_account": "Dizze tsjinner freget fan elke spiler in eigen Minecraft-akkount",
"horizon.splitscreen.local_only": "Oare spilers kinne allinnich mei har eigen Minecraft-akkount oan dizze tsjinner meidwaan: offline-profylen spylje yn jo wrâld, op LAN of op in tsjinner yn jo lokale netwurk.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Ferberget modellen efter opake blokken. Async kontrolearret off-thread; entiteiten tikke.",
"Block Entities": "Block Entiteiten",
"Shulker Boxes": "Shulkerdoazen",
"Reuses settled boxes; lid movement stays animated.": "Reuses fêstige doazen; lid beweging bliuwt animearre.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Iepenje foar dizze sesje troch it programma dat it spultsje begon.",
"horizon.agent.socket": "Socket: %s (kopiearje de details foar it folsleine paad)",
"horizon.agent.local_only": "Allinnich lokaal: aginten op dizze kompjûter, nea it netwurk.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Ferberget modellen efter opake blokken. Entiteiten update. Ut mei oanpaste pakketten.",
"Entity Culling Precheck": "Foarôfkontrôle by entiteitsculling",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Rint de AABB-foarôfkontrôle foar mobs pas by safolle laden mobs. Nul skeakelet it út.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Tír-raon garbh i bhfad i gcéin sa saol áitiúil. Stopann GPUanna comhtháite ag 128 smután.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Tarraingíonn laghdaithe tír-raon i bhfad níos garbh: níos tapúla ar an GPU comhtháite seo.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Tarraingíonn laghdaithe tír-raon i bhfad níos garbh, do GPUanna mhoillíonn sé síos.",
"Field of view. Wider shows more terrain at once.": "Réimse radhairc. Léiríonn níos leithne tír-raon níos mó ag an am céanna.",
"Caps frames per second; a cap saves power and heat.": "Frámaí caipíní in aghaidh an tsoicind; sábhálann caipín cumhacht agus teas.",
"Waits for the display's refresh: no tearing, a little latency.": "Ag fanacht le hathnuachan an taispeántais: gan stróiceadh, beagán foighne.",
"Size of menus and the HUD.": "Méid na biachláir agus an HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Smooths imill garbh. FXAA: níos boige. TAA: d’fhéadfadh rudaí bogtha is míne a leanúint.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Déanann sé an domhan níos lú agus atógáil le TAA. Níos tapúla, níos boige.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Géaraíonn sé an pictiúr uasscála. Níos airde: imill níos géire, níos mó lonrachais.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Aschur HDR ar taispeáint HDR: lava, tine agus solas na gréine ag taitneamh níos gile.",
"How frames reach the screen while VSync is off.": "Conas a shroicheann frámaí an scáileán agus VSync múchta.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Codlaíonn éifeachtach go dtí an chéad fhráma eile; Spins beachta, cosúil le fanaile.",
"Fills the screen (borderless).": "Líonann an scáileán (gan teorainn).",
"Brightens dark places.": "Brightens áiteanna dorcha.",
"Lowers the frame rate when minimised, or idle too.": "Íslíonn sé an ráta fráma nuair a íoslaghdaítear é, nó díomhaoin freisin.",
"Sways the view while walking.": "Sways an radharc agus tú ag siúl.",
"Fades newly loaded chunks in.": "Fades píosaí nua-luchtaithe isteach.",
"Darkens the screen's edges.": "Dorchaigh imill an scáileáin.",
"Shows when the world saves.": "A thaispeáint nuair a shábháil ar fud an domhain.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Tá an freastalaí seo i mód ar líne: ní féidir le próifílí as líne teacht isteach ann, teastaíonn a chuntas Minecraft féin ó gach imreoir.",
"horizon.splitscreen.own_account": "Teastaíonn a chuntas Minecraft féin ó gach imreoir don fhreastalaí seo",
"horizon.splitscreen.local_only": "Ní féidir le himreoirí eile teacht isteach sa fhreastalaí seo ach lena gcuntas Minecraft féin: imríonn próifílí as líne i do dhomhan, ar LAN nó ar fhreastalaí ar do líonra áitiúil.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Seithí samhlacha taobh thiar de bhloic teimhneach. Seiceálann Async as an snáithe; aonáin tic.",
"Block Entities": "Aonáin Bloc",
"Shulker Boxes": "Boscaí Shulker",
"Reuses settled boxes; lid movement stays animated.": "Athúsáideann sé boscaí socraithe; Fanann gluaiseacht clúdach beochan.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Ar oscailt don seisiún seo ag an gclár a thosaigh an cluiche.",
"horizon.agent.socket": "Soicéad: %s (cóipeáil na sonraí dá chonair iomlán)",
"horizon.agent.local_only": "Áitiúil amháin: gníomhairí ar an ríomhaire seo, ní an líonra.",
"%s nits": "%s nits",
"Auto (%s nits)": "Uathoibríoch (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Seithí samhlacha taobh thiar de bhloic teimhneach. Nuashonrú aonáin. Lasmuigh le pacáistí saincheaptha.",
"Entity Culling Precheck": "Réamhsheiceáil Maraithe Aonán",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Ritheann sé réamhsheiceáil AABB na mobs tar éis an méid seo mobs luchtaithe. Díchumasaíonn nialas é.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Cruth-tìre garbh fad às ann an saoghal ionadail. Bidh GPUs aonaichte a’ stad aig 128 pìosan.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Lùghdachadh a’ tarraing talamh fada nas garbh: nas luaithe air an GPU amalaichte seo.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Lùghdaich a’ tarraing talamh fada nas garbh, airson GPUs bidh e a’ slaodadh sìos.",
"Field of view. Wider shows more terrain at once.": "Raon sealladh. Nas fharsainge a 'sealltainn barrachd talmhainn aig an aon àm.",
"Caps frames per second; a cap saves power and heat.": "frèamaichean caiptean gach diog; bidh caip a 'sàbhaladh cumhachd agus teas.",
"Waits for the display's refresh: no tearing, a little latency.": "A’ feitheamh ri ùrachadh an taisbeanaidh: gun reubadh, beagan latency.",
"Size of menus and the HUD.": "Meud clàran-bìdh agus an HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Smooths garbh oirean. FXAA: nas buige. TAA: faodaidh rudan gluasadach a bhith a’ leantainn.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "A’ toirt an t-saoghail nas lugha agus ga ath-thogail le TAA. Nas luaithe, nas buige.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "A' geurachadh an dealbh àrdaichte. Nas àirde: oirean nas gèire, barrachd deàlradh.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Toradh HDR air taisbeanadh HDR: làbha, teine agus solas na grèine a’ deàrrsadh nas gile.",
"How frames reach the screen while VSync is off.": "Mar a ruigeas frèamaichean an sgrion fhad ‘s a tha VSync dheth.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Èifeachdach cadal gus an ath fhrèam; Spionnadh mionaideach, mar vanilla.",
"Fills the screen (borderless).": "A 'lìonadh an sgrion (gun chrìoch).",
"Brightens dark places.": "A 'soilleireachadh àiteachan dorcha.",
"Lowers the frame rate when minimised, or idle too.": "Lùghdaich an ìre frèam nuair a thèid a lughdachadh, no leisg cuideachd.",
"Sways the view while walking.": "Tionndaidh an sealladh fhad ‘s a tha thu a’ coiseachd.",
"Fades newly loaded chunks in.": "A ' gearradh pìosan a luchdadh a-nuas.",
"Darkens the screen's edges.": "A’ dorchachadh oirean an sgrion.",
"Shows when the world saves.": "A 'sealltainn nuair a tha an saoghal a' sàbhaladh.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Tha am frithealaiche seo ann am modh air loidhne: chan urrainn dha pròifilean far-loidhne a dhol còmhla ris, feumaidh gach cluicheadair a chunntas Minecraft fhèin.",
"horizon.splitscreen.own_account": "Feumaidh am frithealaiche seo cunntas Minecraft gach cluicheadair fhèin",
"horizon.splitscreen.local_only": "Chan urrainn do chluicheadairean eile a dhol còmhla ris an fhrithealaiche seo ach le an cunntas Minecraft fhèin: bidh pròifilean far-loidhne a' cluich anns an t-saoghal agad, air LAN no air frithealaiche air an lìonra ionadail agad.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Falaich mhodalan air cùl blocaichean neo-shoilleir. Bidh Async a’ sgrùdadh far-snàthainn; cuir diog air buidhnean.",
"Block Entities": "Bloc aonadan",
"Shulker Boxes": "Bogsaichean Shulker",
"Reuses settled boxes; lid movement stays animated.": "Ath-chleachdadh bhogsaichean suidhichte; gluasad mullach a 'fuireach beòthail.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Air fhosgladh airson an t-seisein seo leis a’ phrògram a thòisich an geama.",
"horizon.agent.socket": "Socaid: %s (Dèan lethbhreac den fhiosrachadh airson a shlighe slàn)",
"horizon.agent.local_only": "Ionadail a-mhàin: àidseantan air a’ choimpiutair seo, chan e an lìonra a-riamh.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Falaich mhodalan air cùl blocaichean neo-shoilleir. Ùrnaighean airson buidhnean. Cuir dheth le pacaidean àbhaisteach.",
"Entity Culling Precheck": "Ro-sgrùdadh culadh aonadan",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "A' ruith ro-sgrùdadh AABB nam mob às deidh an uiread seo de mhob luchdaichte. Tha neoni ga chur dheth.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terreo afastado groso nos mundos locais. As GPU integradas paran en 128 anacos.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Deseños reducidos moito terreo máis groso: máis rápido nesta GPU integrada.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Os debuxos reducidos son moito máis grosos, para as GPU ralentízase.",
"Field of view. Wider shows more terrain at once.": "Campo de visión. Máis ancho mostra máis terreo á vez.",
"Caps frames per second; a cap saves power and heat.": "Capas de fotogramas por segundo; un tapón aforra enerxía e calor.",
"Waits for the display's refresh: no tearing, a little latency.": "Agarda a que se actualice a pantalla: sen rasgaduras, un pouco de latencia.",
"Size of menus and the HUD.": "Tamaño dos menús e do HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Alisa os bordos irregulares. FXAA: máis suave. TAA: máis suave, as cousas en movemento poden seguir.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Fai o mundo máis pequeno e reconstrúeo con TAA. Máis rápido, máis suave.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Aumenta a nitidez da imaxe ampliada. Máis alto: bordos máis nítidos, máis tremelucido.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Saída HDR nunha pantalla HDR: a lava, o lume e a luz solar brillan máis.",
"How frames reach the screen while VSync is off.": "Como chegan os fotogramas á pantalla mentres VSync está desactivado.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Sonos eficientes ata o seguinte cadro; Xiros precisos, como vainilla.",
"Fills the screen (borderless).": "Enche a pantalla (sen bordes).",
"Brightens dark places.": "Ilumina os lugares escuros.",
"Lowers the frame rate when minimised, or idle too.": "Reduce a frecuencia de fotogramas cando se minimiza ou tamén está inactivo.",
"Sways the view while walking.": "Balancea a vista mentres camiña.",
"Fades newly loaded chunks in.": "Desvanece os anacos recentemente cargados.",
"Darkens the screen's edges.": "Escurece os bordos da pantalla.",
"Shows when the world saves.": "Mostra cando o mundo salva.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Este servidor está en modo en liña: os perfís sen conexión non poden unirse, cada xogador necesita a súa propia conta de Minecraft.",
"horizon.splitscreen.own_account": "Este servidor necesita a conta de Minecraft propia de cada xogador",
"horizon.splitscreen.local_only": "Outros xogadores só poden unirse a este servidor coa súa propia conta de Minecraft: os perfís sen conexión xogan no teu mundo, en LAN ou nun servidor da túa rede local.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Oculta modelos detrás de bloques opacos. Async comproba fóra do fío; as entidades marcan.",
"Block Entities": "Bloquear Entidades",
"Shulker Boxes": "Caixas Shulker",
"Reuses settled boxes; lid movement stays animated.": "Reutiliza caixas asentadas; o movemento da tapa permanece animado.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Aberto para esta sesión polo programa que iniciou o xogo.",
"horizon.agent.socket": "Socket: %s (copie os detalles da súa ruta completa)",
"horizon.agent.local_only": "Só local: axentes deste equipo, nunca da rede.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automático (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Oculta modelos detrás de bloques opacos. Actualización das entidades. Desconta con paquetes personalizados.",
"Entity Culling Precheck": "Comprobación previa do culling de entidades",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Executa a comprobación previa AABB das turbas a partir deste número de turbas cargadas. Cero desactívaa.",
"%s mobs": "%s turbas",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "ʻĀina mamao loa ma nā honua kūloko. Hoʻopau nā GPU i hoʻohui ʻia ma nā ʻāpana 128.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "ʻOi aku ka wikiwiki o kēia GPU hoʻohui ʻia.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Hoʻemi ʻia ka huki ʻana i ka ʻāina mamao loa, no nā GPU e lohi ia.",
"Field of view. Wider shows more terrain at once.": "Kahua ʻike. Hōʻike ʻia ka ʻāina ākea i ka manawa hoʻokahi.",
"Caps frames per second; a cap saves power and heat.": "Hoʻopili i nā kiʻi i kēlā me kēia kekona; ʻO ka pāpale e mālama i ka mana a me ka wela.",
"Waits for the display's refresh: no tearing, a little latency.": "Ke kali nei no ka hōʻike hou ʻana: ʻaʻohe haehae, liʻiliʻi liʻiliʻi.",
"Size of menus and the HUD.": "Ka nui o nā menus a me ka HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Hoʻomaʻamaʻa i nā ʻaoʻao ʻeke. FXAA: palupalu. TAA: ʻoi aku ka maʻalahi a me ka neʻe ʻana o nā mea.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Hoʻolilo i ka honua i mea liʻiliʻi a kūkulu hou me TAA. ʻOi aku ka wikiwiki, ʻoi aku ka palupalu.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Hoʻoi i ke kiʻi i hoʻonui ʻia. Kiʻekiʻe: ʻoi aʻe nā ʻaoʻao, ʻoi aku ka ʻālohilohi.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Hoʻopuka HDR ma kahi hōʻike HDR: ʻālohilohi ka pele, ke ahi a me ka lā.",
"How frames reach the screen while VSync is off.": "Pehea e hiki ai nā kiʻi i ka pale ke pio ʻo VSync.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Moe maikaʻi a hiki i ke kiʻi aʻe; ʻO nā milo pololei, e like me vanilla.",
"Fills the screen (borderless).": "Hoʻopiha i ka pale (palena ʻole).",
"Brightens dark places.": "Hoʻomālamalama i nā wahi pouli.",
"Lowers the frame rate when minimised, or idle too.": "E hoʻohaʻahaʻa i ka helu kiʻi ke hoʻemi ʻia, a i ʻole hoʻi.",
"Sways the view while walking.": "Hoʻoluliluli i ka ʻike i ka wā e hele ana.",
"Fades newly loaded chunks in.": "Hoʻopau i nā ʻāpana hou i hoʻouka ʻia.",
"Darkens the screen's edges.": "Pōuliuli i nā kihi o ka pale.",
"Shows when the world saves.": "Hōʻike i ka wā e hoʻopakele ai ke ao.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Aia kēia kikowaena ma ke ʻano pūnaewele: ʻaʻole hiki i nā ʻaoʻao offline ke hui, pono i kēlā me kēia mea pāʻani kāna moʻokāki Minecraft ponoʻī.",
"horizon.splitscreen.own_account": "Pono kēia kikowaena i ka moʻokāki Minecraft ponoʻī o kēlā me kēia mea pāʻani",
"horizon.splitscreen.local_only": "Hiki i nā mea pāʻani ʻē aʻe ke hui i kēia kikowaena me ko lākou moʻokāki Minecraft ponoʻī wale nō: pāʻani nā ʻaoʻao offline i kou honua, ma LAN a i ʻole ma kahi kikowaena ma kāu pūnaewele kūloko.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Hūnā nā kumu hoʻohālike ma hope o nā poloka opaque. Ke nānā nei ʻo Async i waho-thread; nā mea hoʻohui.",
"Block Entities": "Paʻa i nā hui",
"Shulker Boxes": "Nā Pahu Shulker",
"Reuses settled boxes; lid movement stays animated.": "Hoʻohana hou i nā pahu i hoʻopaʻa ʻia; hoʻomau ka neʻe ʻana o ka poʻi.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Wehe ʻia no kēia kau e ka papahana i hoʻomaka i ka pāʻani.",
"horizon.agent.socket": "Socket: %s (kope i nā kikoʻī no kona ala piha)",
"horizon.agent.local_only": "Kaiakū wale nō: nā ʻelele ma kēia kamepiula, ʻaʻole i ka pūnaewele.",
"%s nits": "%s nits",
"Auto (%s nits)": "Akomi (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Hūnā nā kumu hoʻohālike ma hope o nā poloka opaque. Hōʻano hou nā hui. Hoʻopau me nā pūʻolo maʻamau.",
"Entity Culling Precheck": "Nānā Mua o ka Kaʻili ʻElele",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Holo ka nānā mua AABB o nā holoholona ma hope o kēia nui o nā holoholona i hoʻouka ʻia. Hoʻopau ka ʻole iā ia.",
"%s mobs": "%s holoholona",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "שטח מרוחק גס בעולמות מקומיים. GPUs משולבים עוצרים ב-128 נתחים.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "מצומצם שואב שטח גס יותר: מהיר יותר ב-GPU המשולב הזה.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "מצומצם מושך פני שטח גס יותר, עבור GPUs הוא מאט.",
"Field of view. Wider shows more terrain at once.": "שדה ראיה. רחב יותר מציג יותר שטח בבת אחת.",
"Caps frames per second; a cap saves power and heat.": "מכסים פריימים לשנייה; מכסה חוסך חשמל וחום.",
"Waits for the display's refresh: no tearing, a little latency.": "ממתין לרענון התצוגה: ללא קריעה, מעט השהייה.",
"Size of menus and the HUD.": "גודל התפריטים וה-HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "מחליק קצוות משוננים. FXAA: רך יותר. TAA: הדברים הנעים והחלקים ביותר עשויים להיגרר.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "הופך את העולם לקטן יותר ובונה אותו מחדש עם TAA. מהר יותר, רך יותר.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "מחדד את התמונה המוגדלת. גבוה יותר: קצוות חדים יותר, יותר נצנוץ.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "פלט HDR על צג HDR: לבה, אש ואור שמש זוהרים יותר.",
"How frames reach the screen while VSync is off.": "איך מסגרות מגיעות למסך בזמן ש-VSync כבוי.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "שינה יעילה עד הפריים הבא; סיבובים מדויקים, כמו וניל.",
"Fills the screen (borderless).": "ממלא את המסך (ללא שוליים).",
"Brightens dark places.": "מאיר מקומות חשוכים.",
"Lowers the frame rate when minimised, or idle too.": "מוריד את קצב הפריימים כאשר הוא ממוזער, או גם במצב סרק.",
"Sways the view while walking.": "מטלטל את הנוף תוך כדי הליכה.",
"Fades newly loaded chunks in.": "דוהה פנימה נתחים שנטענו לאחרונה.",
"Darkens the screen's edges.": "מכהה את קצוות המסך.",
"Shows when the world saves.": "מראה מתי העולם מציל.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "השרת הזה במצב מקוון: פרופילים לא מקוונים לא יכולים להצטרף אליו, כל שחקן צריך חשבון Minecraft משלו.",
"horizon.splitscreen.own_account": "השרת הזה דורש חשבון Minecraft משל כל שחקן",
"horizon.splitscreen.local_only": "שחקנים אחרים יכולים להצטרף לשרת הזה רק עם חשבון Minecraft משלהם: פרופילים לא מקוונים משחקים בעולם שלך, ב-LAN או בשרת ברשת המקומית שלך.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "מסתיר דגמים מאחורי בלוקים אטומים. א-סינכרון בודק מחוץ לשרשור; ישויות מתקתקות.",
"Block Entities": "חסום ישויות",
"Shulker Boxes": "שולקר קופסאות",
"Reuses settled boxes; lid movement stays animated.": "עושה שימוש חוזר בקופסאות מיושבות; תנועת המכסה נשארת מונפשת.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "נפתח להפעלה זו על ידי התוכנית שהתחילה את המשחק.",
"horizon.agent.socket": "שקע: %s (העתק את הפרטים לנתיב המלא שלו)",
"horizon.agent.local_only": "מקומי בלבד: סוכנים במחשב זה, לעולם לא ברשת.",
"%s nits": "%s ניטים",
"Auto (%s nits)": "אוטומטי (%s ניטים)",
"%.2f nits": "%.2f ניטים",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "מסתיר דגמים מאחורי בלוקים אטומים. עדכון ישויות. כבוי עם חבילות מותאמות אישית.",
"Entity Culling Precheck": "בדיקה מקדימה של חיתוך ישויות",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "מריץ את בדיקת ה-AABB של היצורים אחרי מספר כזה של יצורים טעונים. אפס מכבה אותה.",
"%s mobs": "%s יצורים",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "स्थानीय दुनिया में मोटा दूर का भू-भाग। एकीकृत GPU 128 चंक्स पर रुक जाते हैं।",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "घटाया गया मोड दूर के भू-भाग को मोटा बनाता है: इस एकीकृत GPU पर तेज़।",
"Reduced draws far terrain coarser, for GPUs it slows down.": "घटाया गया मोड दूर के भू-भाग को मोटा बनाता है, कुछ GPU के लिए यह धीमा हो जाता है।",
"Field of view. Wider shows more terrain at once.": "फ़ील्ड ऑफ़ व्यू। चौड़ा होने पर एक साथ अधिक भू-भाग दिखाई देता है।",
"Caps frames per second; a cap saves power and heat.": "प्रति सेकंड फ्रेम सीमा तय करता है; एक सीमा बिजली और गर्मी बचाती है।",
"Waits for the display's refresh: no tearing, a little latency.": "डिस्प्ले के रिफ्रेश का इंतज़ार करता है: कोई टियरिंग नहीं, थोड़ी सी लेटेंसी।",
"Size of menus and the HUD.": "मेनू और HUD का आकार।",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "टेढ़े-मेढ़े किनारों को चिकना करता है। FXAA: नरम। TAA: सबसे चिकना, गतिमान चीज़ों के पीछे निशान हो सकते हैं।",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "दुनिया को छोटा रेंडर करता है और TAA के साथ पुनर्निर्माण करता है। तेज़, नरम।",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "अपस्केल की गई तस्वीर को तेज़ करता है। अधिक: तेज़ किनारे, अधिक शिमर।",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR डिस्प्ले पर HDR आउटपुट: लावा, आग और धूप अधिक चमकीले चमकते हैं।",
"How frames reach the screen while VSync is off.": "VSync बंद होने पर फ्रेम स्क्रीन तक कैसे पहुँचते हैं।",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "दक्ष मोड अगले फ्रेम तक सोता है; सटीक मोड वैनिला की तरह घूमता है।",
"Fills the screen (borderless).": "स्क्रीन भरता है (बॉर्डरलेस)।",
"Brightens dark places.": "अंधेरी जगहों को चमकाता है।",
"Lowers the frame rate when minimised, or idle too.": "न्यूनतम किए जाने पर या निष्क्रिय होने पर फ्रेम दर कम कर देता है।",
"Sways the view while walking.": "चलते समय दृश्य को झुकाता है।",
"Fades newly loaded chunks in.": "नए लोड किए गए चंक्स को फेड इन करता है।",
"Darkens the screen's edges.": "स्क्रीन के किनारों को गहरा करता है।",
"Shows when the world saves.": "दिखाता है कि दुनिया कब सेव होती है।",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "यह सर्वर ऑनलाइन मोड में है: ऑफ़लाइन प्रोफ़ाइल इसमें शामिल नहीं हो सकते, प्रत्येक खिलाड़ी को अपना Minecraft खाता चाहिए।",
"horizon.splitscreen.own_account": "इस सर्वर के लिए प्रत्येक खिलाड़ी का अपना Minecraft खाता चाहिए",
"horizon.splitscreen.local_only": "अन्य खिलाड़ी इस सर्वर में केवल अपने Minecraft खाते से शामिल हो सकते हैं: ऑफ़लाइन प्रोफ़ाइल आपकी दुनिया में, LAN पर या आपके स्थानीय नेटवर्क के सर्वर पर खेलते हैं।",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "अपारदर्शी ब्लॉकों के पीछे मॉडल छुपाता है। एंसिंक जाँचें ऑफ-थ्रेड होती हैं; एंटिटीज टिक करती हैं।",
"Block Entities": "ब्लॉक एंटिटीज",
"Shulker Boxes": "शल्कर बॉक्सेस",
"Reuses settled boxes; lid movement stays animated.": "स्थिर बॉक्स का पुन उपयोग करता है; ढक्कन की गति एनिमेटेड रहती है।",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "गेम शुरू करने वाले प्रोग्राम द्वारा इस सत्र के लिए खोला गया।",
"horizon.agent.socket": "सॉकेट: %s (इसके पूर्ण पथ के लिए विवरण कॉपी करें)",
"horizon.agent.local_only": "केवल स्थानीय: इस कंप्यूटर पर एजेंट, नेटवर्क पर कभी नहीं।",
"%s nits": "%s निट्स",
"Auto (%s nits)": "ऑटो (%s निट्स)",
"%.2f nits": "%.2f निट्स",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "अपारदर्शी ब्लॉकों के पीछे मॉडल छुपाता है। एंटिटीज अपडेट होती हैं। कस्टम पैक के साथ बंद।",
"Entity Culling Precheck": "एंटिटी कलिंग पूर्व-जाँच",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "इतने लोडेड मॉब्स के बाद मॉब AABB पूर्व-जाँच चलाता है। शून्य इसे बंद कर देता है।",
"%s mobs": "%s मॉब्स",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grubi udaljeni teren u lokalnim svjetovima. Integrirani GPU-ovi staju na 128 komadića.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Smanjeno crtanje prikazuje udaljeni teren grubljim: brže na ovom integriranom GPU-u.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Smanjeno crtanje prikazuje udaljeni teren grubljim, za neke GPU-ove to usporava rad.",
"Field of view. Wider shows more terrain at once.": "Vidno polje. Šire vidno polje prikazuje više terena odjednom.",
"Caps frames per second; a cap saves power and heat.": "Ograničava broj sličica u sekundi; ograničenje štedi energiju i smanjuje zagrijavanje.",
"Waits for the display's refresh: no tearing, a little latency.": "Čeka osvježavanje zaslona: nema trganja slike, ali uzrokuje malu latenciju.",
"Size of menus and the HUD.": "Veličina izbornika i HUD-a.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Ublažava nazubljene rubove. FXAA: mekše. TAA: najmekše, pokretni objekti mogu ostavljati trag.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Prikazuje svijet manjim i ponovno ga gradi pomoću TAA. Brže, mekše.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Izoštrava uvećanu sliku. Više: oštriji rubovi, više treperenja.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR izlaz na HDR zaslonu: lava, vatra i sunčeva svjetlost sjaje jače.",
"How frames reach the screen while VSync is off.": "Kako sličice dospijevaju na zaslon dok je VSync isključen.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Učinkovito spava do sljedeće sličice; Precizno se vrti, kao u vanila verziji.",
"Fills the screen (borderless).": "Ispunjava zaslon (bez obruba).",
"Brightens dark places.": "Osvjetljava tamna mjesta.",
"Lowers the frame rate when minimised, or idle too.": "Smanjuje broj sličica u sekundi kada je prozor minimiziran ili neaktivan.",
"Sways the view while walking.": "Ziba pogled tijekom hodanja.",
"Fades newly loaded chunks in.": "Postupno prikazuje novoučitane komadiće.",
"Darkens the screen's edges.": "Zatamnjuje rubove zaslona.",
"Shows when the world saves.": "Prikazuje kada se svijet sprema.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Ovaj poslužitelj je u mrežnom načinu rada: izvanmrežni profili mu se ne mogu pridružiti, svaki igrač treba vlastiti Minecraft račun.",
"horizon.splitscreen.own_account": "Ovaj poslužitelj zahtijeva vlastiti Minecraft račun svakog igrača",
"horizon.splitscreen.local_only": "Drugi se igrači mogu pridružiti ovom poslužitelju samo s vlastitim Minecraft računom: izvanmrežni profili igraju u vašem svijetu, na LAN-u ili na poslužitelju na vašoj lokalnoj mreži.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Sakriva modele iza neprozirnih blokova. Asinkrone provjere izvan dretve; entiteti obavljaju takt.",
"Block Entities": "Blokovski entiteti",
"Shulker Boxes": "Shulker kutije",
"Reuses settled boxes; lid movement stays animated.": "Ponovno koristi smirene kutije; kretanje poklopca ostaje animirano.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Ovu sesiju je otvorio program koji je pokrenuo igru.",
"horizon.agent.socket": "Utičnica: %s (kopirajte pojedinosti za njezinu punu stazu)",
"horizon.agent.local_only": "Samo lokalno: agenti na ovom računalu, nikada mreža.",
"%s nits": "%s nita",
"Auto (%s nits)": "Automatski (%s nita)",
"%.2f nits": "%.2f nita",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Sakriva modele iza neprozirnih blokova. Entiteti se ažuriraju. Isključeno s prilagođenim paketima.",
"Entity Culling Precheck": "Predprovjera određivanja vidljivosti entiteta",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Pokreće AABB predprovjeru čudovišta nakon ovoliko učitanih čudovišta. Nula je isključuje.",
"%s mobs": "%s čudovišta",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Durva távoli terep a helyi világokban. Az integrált GPU-k 128 darabnál állnak meg.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "A csökkentett rajz sokkal durvább: gyorsabb ezen az integrált GPU-n.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "A redukált sokkal durvábban rajzolja meg a terepet, a GPU-knál lassul.",
"Field of view. Wider shows more terrain at once.": "Látómező. A szélesebb egyszerre több terepet mutat.",
"Caps frames per second; a cap saves power and heat.": "Képkocka sebessége másodpercenként; a sapka energiát és hőt takarít meg.",
"Waits for the display's refresh: no tearing, a little latency.": "Várja a kijelző frissítését: nincs szakadás, egy kis késleltetés.",
"Size of menus and the HUD.": "A menük mérete és a HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Kisimítja a szaggatott széleket. FXAA: lágyabb. TAA: a legsimább, mozgó dolgok nyomába eredhetnek.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Kisebbé teszi a világot, és TAA-val újjáépíti. Gyorsabb, lágyabb.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Élesíti a felskálázott képet. Magasabb: élesebb élek, több csillogás.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR kimenet HDR kijelzőn: a láva, a tűz és a napfény erősebben ragyog.",
"How frames reach the screen while VSync is off.": "Hogyan érik el a keretek a képernyőt, amikor a VSync ki van kapcsolva.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Hatékony alvás a következő képkockáig; Pontos pörgetések, mint a vanília.",
"Fills the screen (borderless).": "Kitölti a képernyőt (szegély nélkül).",
"Brightens dark places.": "Világosítja a sötét helyeket.",
"Lowers the frame rate when minimised, or idle too.": "Csökkenti a képkockasebességet minimálisra csökkentve vagy üresjáratban is.",
"Sways the view while walking.": "Séta közben megingatja a kilátást.",
"Fades newly loaded chunks in.": "Elhalványítja az újonnan betöltött darabokat.",
"Darkens the screen's edges.": "Sötétíti a képernyő széleit.",
"Shows when the world saves.": "Megmutatja, mikor ment meg a világ.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Ez a szerver online módban van: offline profilok nem csatlakozhatnak hozzá, minden játékosnak saját Minecraft-fiókja kell legyen.",
"horizon.splitscreen.own_account": "Ez a szerver minden játékosnak saját Minecraft-fiókot igényel",
"horizon.splitscreen.local_only": "Más játékosok csak saját Minecraft-fiókjukkal csatlakozhatnak ehhez a szerverhez: az offline profilok az Ön világában játszanak, LAN-on vagy a helyi hálózatán lévő szerveren.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "A modelleket átlátszatlan blokkok mögé rejti. Async ellenőrzi a szálon kívüli; entitások ketyegnek.",
"Block Entities": "Entitások blokkolása",
"Shulker Boxes": "Shulker dobozok",
"Reuses settled boxes; lid movement stays animated.": "Újrafelhasználja az ülepített dobozokat; a fedél mozgása animált marad.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Erre a munkamenetre a játékot elindító program nyitotta meg.",
"horizon.agent.socket": "Socket: %s (másolja a részleteket a teljes elérési úthoz)",
"horizon.agent.local_only": "Csak helyi: ügynökök ezen a számítógépen, soha a hálózaton.",
"%s nits": "%s nit",
"Auto (%s nits)": "Automatikus (%s nits)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "A modelleket átlátszatlan blokkok mögé rejti. Az entitások frissítése. Egyedi csomagokkal.",
"Entity Culling Precheck": "Entitásselejtezés előellenőrzés",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Ennyi betöltött mob után futtatja a mob AABB előellenőrzést. A nulla kikapcsolja.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Կոպիտ հեռավոր տեղանք տեղական աշխարհներում: Ինտեգրված GPU-ները կանգ են առնում 128 կտորի վրա:",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Նվազեցված գծերը ավելի կոպիտ են՝ ավելի արագ այս ինտեգրված GPU-ում:",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Նվազեցված տարածքը ավելի կոպիտ է ձգում, իսկ GPU-ների համար այն դանդաղում է:",
"Field of view. Wider shows more terrain at once.": "Տեսադաշտ. Wider-ը ցույց է տալիս միանգամից ավելի շատ տեղանք:",
"Caps frames per second; a cap saves power and heat.": "Կափարիչներով շրջանակներ վայրկյանում; գլխարկը խնայում է էներգիան և ջերմությունը:",
"Waits for the display's refresh: no tearing, a little latency.": "Սպասում է էկրանի թարմացմանը՝ առանց պատռվելու, մի փոքր ուշացում:",
"Size of menus and the HUD.": "Ցանկերի չափը և HUD-ը:",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Հարթեցնում է ատամնավոր եզրերը։ FXAA: ավելի մեղմ: TAA. ամենասահուն, շարժվող իրերը կարող են հետևել:",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Փոքրացնում է աշխարհը և վերակառուցում այն TAA-ով: Ավելի արագ, ավելի մեղմ:",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Սրում է մեծացված պատկերը։ Բարձր՝ ավելի հստակ եզրեր, ավելի շատ շողշողում։",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR ելք HDR էկրանի վրա. լավան, կրակը և արևի լույսն ավելի պայծառ են փայլում:",
"How frames reach the screen while VSync is off.": "Ինչպես են կադրերը հասնում էկրանին, երբ VSync-ն անջատված է:",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Արդյունավետ քուն մինչև հաջորդ կադր; Ճշգրիտ պտույտներ, ինչպես վանիլինը:",
"Fills the screen (borderless).": "Լցնում է էկրանը (անսահման):",
"Brightens dark places.": "Պայծառացնում է մութ տեղերը։",
"Lowers the frame rate when minimised, or idle too.": "Նվազեցնում է կադրերի արագությունը, երբ այն նվազագույնի է հասցվում կամ նույնպես անգործուն է:",
"Sways the view while walking.": "Շեղում է տեսարանը քայլելիս:",
"Fades newly loaded chunks in.": "Գունաթափում է նոր բեռնված կտորները:",
"Darkens the screen's edges.": "Մթնում է էկրանի եզրերը:",
"Shows when the world saves.": "Ցույց է տալիս, երբ աշխարհը փրկում է:",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Այս սերվերը առցանց ռեժիմում է. անցանց պրոֆիլները չեն կարող միանալ, յուրաքանչյուր խաղացողի պետք է իր Minecraft հաշիվը։",
"horizon.splitscreen.own_account": "Այս սերվերին յուրաքանչյուր խաղացողի պետք է իր Minecraft հաշիվը",
"horizon.splitscreen.local_only": "Այլ խաղացողները կարող են միանալ այս սերվերին միայն իրենց Minecraft հաշվով. անցանց պրոֆիլները խաղում են ձեր աշխարհում՝ LAN-ով կամ ձեր տեղական ցանցի սերվերում։",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Թաքցնում է մոդելները անթափանց բլոկների հետևում: Async-ը ստուգում է թեմայից դուրս; սուբյեկտները նշում են.",
"Block Entities": "Արգելափակել սուբյեկտները",
"Shulker Boxes": "Շուլկերի տուփեր",
"Reuses settled boxes; lid movement stays animated.": "Վերօգտագործում է նստեցված տուփերը; կափարիչի շարժումը մնում է անիմացիոն:",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Այս նիստի համար բացվել է այն ծրագրի կողմից, որը սկսել է խաղը:",
"horizon.agent.socket": "Socket՝ %s (պատճենել մանրամասները դրա ամբողջական ուղու համար)",
"horizon.agent.local_only": "Միայն տեղական. գործակալներ այս համակարգչում, ոչ երբեք ցանց:",
"%s nits": "%s նիտ",
"Auto (%s nits)": "Ավտոմատ (%s nits)",
"%.2f nits": "%.2f նիտ",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Թաքցնում է մոդելները անթափանց բլոկների հետևում: Սուբյեկտների թարմացում: Անջատված է հատուկ փաթեթներով:",
"Entity Culling Precheck": "Սուբյեկտների կտրման նախաստուգում",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Ամբոխի AABB նախաստուգումն աշխատում է այսքան բեռնված ամբոխից հետո։ Զրոն անջատում է այն։",
"%s mobs": "%s ամբոխ",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Medan jauh kasar di dunia lokal. GPU terintegrasi berhenti pada 128 chunk.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Mode dikurangi menggambar medan jauh lebih kasar: lebih cepat pada GPU terintegrasi ini.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Mode dikurangi menggambar medan jauh lebih kasar, untuk GPU yang mungkin melambat.",
"Field of view. Wider shows more terrain at once.": "Bidang pandang (FOV). Semakin luas, semakin banyak medan yang terlihat sekaligus.",
"Caps frames per second; a cap saves power and heat.": "Membatasi bingkai per detik; batasan ini menghemat daya dan panas.",
"Waits for the display's refresh: no tearing, a little latency.": "Menunggu penyegaran layar: tanpa robekan gambar (tearing), namun ada sedikit latensi.",
"Size of menus and the HUD.": "Ukuran menu dan HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Menghaluskan tepi bergerigi. FXAA: lebih lembut. TAA: paling halus, objek bergerak dapat meninggalkan jejak.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Merender dunia lebih kecil dan membangunnya ulang dengan TAA. Lebih cepat dan lembut.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Mempertajam gambar hasil peningkatan skala. Lebih tinggi: tepi lebih tajam, lebih banyak kedipan.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Output HDR pada layar HDR: lava, api, dan cahaya matahari bersinar lebih terang.",
"How frames reach the screen while VSync is off.": "Bagaimana bingkai mencapai layar saat VSync nonaktif.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efisien: tidur hingga bingkai berikutnya; Tepat: berputar aktif, seperti versi vanilla.",
"Fills the screen (borderless).": "Memenuhi layar (tanpa batas/borderless).",
"Brightens dark places.": "Mencerahkan tempat gelap.",
"Lowers the frame rate when minimised, or idle too.": "Menurunkan kecepatan bingkai saat diminimalkan atau sedang menganggur (idle).",
"Sways the view while walking.": "Mengayunkan pandangan saat berjalan.",
"Fades newly loaded chunks in.": "Memunculkan chunk yang baru dimuat secara perlahan (fade-in).",
"Darkens the screen's edges.": "Menggelapkan bagian tepi layar.",
"Shows when the world saves.": "Menunjukkan saat dunia disimpan.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Server ini dalam mode online: profil offline tidak dapat bergabung, setiap pemain memerlukan akun Minecraft sendiri.",
"horizon.splitscreen.own_account": "Server ini memerlukan akun Minecraft milik setiap pemain",
"horizon.splitscreen.local_only": "Pemain lain hanya dapat bergabung dengan server ini menggunakan akun Minecraft mereka sendiri: profil offline bermain di dunia Anda, di LAN atau di server pada jaringan lokal Anda.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Menyembunyikan model di balik blok opak. Pemeriksaan asinkron di luar thread; entitas tetap diperbarui.",
"Opaque Ice": "Es Opak",
"Draws ice in the solid pass, without its see-through texture.": "Menggambar es pada tahap padat, tanpa teksturnya yang tembus pandang.",
"Shaders": "Shader",
@@ -568,6 +572,7 @@
"Picks a shader pack, Horizon's or a shaders/ folder one, and sets its options.": "Memilih paket shader, milik Horizon atau yang ada di folder shaders/, dan mengatur opsinya.",
"Hidden Faces": "Sisi Tersembunyi",
"Drops leaf faces behind two leaf layers: faster, same crowns.": "Menghapus sisi daun di balik dua lapisan daun: lebih cepat, tajuk tetap sama.",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Sembunyikan model di balik blok opak. Entitas tetap diperbarui. Nonaktif saat menggunakan paket kustom.",
"Block Entities": "Entitas Blok",
"Shulker Boxes": "Shulker Box",
"Reuses settled boxes; lid movement stays animated.": "Menggunakan kembali box yang diam; gerakan tutupnya tetap dianimasikan.",
@@ -617,6 +622,9 @@
"horizon.agent.session_opened": "Dibuka untuk sesi ini oleh program yang memulai game.",
"horizon.agent.socket": "Socket: %s (salin detail untuk jalur lengkapnya)",
"horizon.agent.local_only": "Khusus lokal: agen di komputer ini, tidak pernah melalui jaringan.",
"%s nits": "%s nit",
"Auto (%s nits)": "Otomatis (%s nit)",
"%.2f nits": "%.2f nit",
"Entity Culling Precheck": "Praperiksa Penyortiran Entitas",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Menjalankan praperiksa AABB mob setelah sejumlah mob dimuat ini. Nol menonaktifkannya.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Ala dị anya n'ime ụwa ime obodo. GPU agbakwunyere na-akwụsị na 128 chunks.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Obere ala na-adọta oke ala: ngwa ngwa na GPU agbakwunyere.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Mbelata na-adọta oke ala, maka GPU ọ na-agbada.",
"Field of view. Wider shows more terrain at once.": "Mpaghara anya. Wider na-egosi oke ala n'otu oge.",
"Caps frames per second; a cap saves power and heat.": "Okpokoro okpu kwa nkeji; okpu na-azọpụta ike na okpomọkụ.",
"Waits for the display's refresh: no tearing, a little latency.": "Na-echere ume ọhụrụ ngosi: enweghị ndọkasị, ntakịrị latency.",
"Size of menus and the HUD.": "Nha menu na HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Na-eme ka akụkụ ndị gbagọrọ agbagọ. FXAA: dị nro. TAA: ihe kacha dị nro, ihe na-akpụ akpụ nwere ike ịzọ ya.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Na-eme ka ụwa dị ntakịrị ma jiri TAA wughachi ya. Ọsọ ọsọ, dị nro.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Na-eme ka foto ebulitere dị nkọ. Elu karịa: ọnụ dị nkọ karịa, iju karịa.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Mmepụta HDR na ngosipụta HDR: lava, ọkụ na ìhè anyanwụ na-enwu karịa.",
"How frames reach the screen while VSync is off.": "Kedu ka okpokolo agba si enweta ihuenyo mgbe VSync gbanyụrụ.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Oru oma na-ehi ụra ruo mgbe etiti ọzọ; Akpụkpọ ụkwụ dị mma, dị ka vanilla.",
"Fills the screen (borderless).": "Na-ejuputa ihuenyo (enweghị oke).",
"Brightens dark places.": "Na-amụba ebe gbara ọchịchịrị.",
"Lowers the frame rate when minimised, or idle too.": "Na-ewetu ọ̀tụ̀tụ̀ fekere ahụ mgbe o wedara ya, ma ọ bụ na-abaghị uru.",
"Sways the view while walking.": "Na-emegharị anya mgbe ị na-eje ije.",
"Fades newly loaded chunks in.": "Na-adaba ntụtụ ndị ebugoro ọhụrụ.",
"Darkens the screen's edges.": "Na-eme ka akụkụ ihuenyo gbaa ọchịchịrị.",
"Shows when the world saves.": "Na-egosi mgbe ụwa na-azọpụta.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Sava a nọ na online mode: profaịlụ offline enweghị ike iso ya, onye ọkpụkpọ ọ bụla chọrọ akaụntụ Minecraft nke ya.",
"horizon.splitscreen.own_account": "Sava a chọrọ akaụntụ Minecraft nke onye ọkpụkpọ ọ bụla",
"horizon.splitscreen.local_only": "Ndị ọkpụkpọ ndị ọzọ nwere ike iso sava a naanị na akaụntụ Minecraft nke ha: profaịlụ offline na-egwu n'ụwa gị, na LAN ma ọ bụ na sava dị na netwọk mpaghara gị.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Na-ezobe ụdị n'azụ blocks na-adịghị ahụkebe. Async na-enyocha anya-eriri; ihe ndị akọrọ.",
"Block Entities": "Ụlọ ọrụ ngọngọ",
"Shulker Boxes": "Igbe Shulker",
"Reuses settled boxes; lid movement stays animated.": "Na-ejigharị igbe ndị edoziri; mmegharị mkpuchi na-adị egwu.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Meghere maka nnọkọ a site na mmemme malitere egwuregwu ahụ.",
"horizon.agent.socket": "Socket: %s (detuo nkọwa maka ụzọ ya zuru oke)",
"horizon.agent.local_only": "Naanị mpaghara: ndị ọrụ na kọmputa a, ọ bụghị netwọk.",
"%s nits": "%s nit",
"Auto (%s nits)": "Akpaaka (%s nits)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Na-ezobe ụdị n'azụ blocks na-adịghị ahụkebe. Mmelite ụlọ ọrụ. Gbanyụọ na ngwugwu omenala.",
"Entity Culling Precheck": "Nyocha mbụ Culling Entity",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Na-agba nyocha mbụ AABB nke mob mgbe ọnụọgụ mob a buuru gachara. Efu na-agbanyụ ya.",
"%s mobs": "%s mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Gróft fjarlægt landslag í heimaheimum. Innbyggt GPU stoppar við 128 klumpur.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Minnkað dregur miklu grófara landslag: hraðari á þessari samþættu GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Minnkað dregur grófara landslag, fyrir GPUs hægir það á sér.",
"Field of view. Wider shows more terrain at once.": "Sjónsvið. Breiðari sýnir meira landslag í einu.",
"Caps frames per second; a cap saves power and heat.": "Caps rammar á sekúndu; loki sparar orku og hita.",
"Waits for the display's refresh: no tearing, a little latency.": "Bíður eftir endurnýjun skjásins: ekkert rif, smá leynd.",
"Size of menus and the HUD.": "Stærð valmynda og HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Sléttir oddhvassar brúnir. FXAA: mýkri. TAA: sléttustu hlutir sem hreyfast geta verið slóðir.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Gerir heiminn minni og endurbyggir hann með TAA. Hraðari, mýkri.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Skerpir stækkuðu myndina. Hærra: skarpari brúnir, meira glit.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR úttak á HDR skjá: hraun, eldur og sólarljós skína skærar.",
"How frames reach the screen while VSync is off.": "Hvernig rammar ná til skjásins á meðan slökkt er á VSync.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Duglegur svefn fram að næsta ramma; Nákvæmar snúningar, eins og vanillu.",
"Fills the screen (borderless).": "Fyllir skjáinn (randalaus).",
"Brightens dark places.": "Lýsir upp dimma staði.",
"Lowers the frame rate when minimised, or idle too.": "Lækkar rammahraðann þegar hann er í lágmarki, eða aðgerðalaus líka.",
"Sways the view while walking.": "Sveiflar útsýninu á meðan þú gengur.",
"Fades newly loaded chunks in.": "Fölnar inn nýhlaðna bita.",
"Darkens the screen's edges.": "Dökkar brúnir skjásins.",
"Shows when the world saves.": "Sýnir þegar heimurinn bjargar.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Þessi netþjónn er í netham: prófílar án nettengingar komast ekki inn, hver leikmaður þarf sinn eigin Minecraft reikning.",
"horizon.splitscreen.own_account": "Þessi netþjónn krefst þess að hver leikmaður noti sinn eigin Minecraft reikning",
"horizon.splitscreen.local_only": "Aðrir leikmenn komast aðeins inn á þennan netþjón með eigin Minecraft reikningi: prófílar án nettengingar spila í heiminum þínum, á LAN eða netþjóni á staðarnetinu þínu.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Felur módel á bak við ógegnsæjar blokkir. Ósamstilltur athugar útþráð; aðilar merkja við.",
"Block Entities": "Loka einingar",
"Shulker Boxes": "Shulker kassar",
"Reuses settled boxes; lid movement stays animated.": "Endurnotar setta kassa; hreyfing loksins heldur áfram að vera fjör.",
@@ -616,6 +620,10 @@
"horizon.agent.session_opened": "Opnað fyrir þessa lotu af forritinu sem byrjaði leikinn.",
"horizon.agent.socket": "Innstunga: %s (afritaðu upplýsingarnar fyrir alla leiðina)",
"horizon.agent.local_only": "Aðeins staðbundið: umboðsmenn á þessari tölvu, aldrei netið.",
"%s nits": "%s nit",
"Auto (%s nits)": "Sjálfvirkt (%s nits)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Felur módel á bak við ógegnsæjar blokkir. Uppfærsla aðila. Burt með sérsniðna pakka.",
"Entity Culling Precheck": "Forprófun niðurskurðar eininga",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Keyrir AABB-forprófun múgs eftir þetta marga hlaðna múga. Núll slekkur á henni.",
"%s mobs": "%s múgur",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terreni distanti e grossolani nei mondi locali. Le GPU integrate si fermano a 128 blocchi.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Ridotti disegna terreni lontani più ruvidi: più veloce su questa GPU integrata.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Il ridotto disegna terreni lontani più grossolani, per le GPU rallenta.",
"Field of view. Wider shows more terrain at once.": "Campo visivo. Più ampio mostra più terreno contemporaneamente.",
"Caps frames per second; a cap saves power and heat.": "Limita i fotogrammi al secondo; un cappuccio consente di risparmiare energia e calore.",
"Waits for the display's refresh: no tearing, a little latency.": "Attende il refresh del display: niente strappi, poca latenza.",
"Size of menus and the HUD.": "Dimensioni dei menu e dell'HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Leviga i bordi frastagliati. FXAA: più morbido. TAA: le cose più fluide e in movimento possono trascinarsi.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Rende il mondo più piccolo e lo ricostruisce con TAA. Più veloce, più morbido.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Nitidizza l'immagine ricampionata. Più alto: bordi più nitidi, più sfarfallio.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Uscita HDR su un display HDR: lava, fuoco e luce solare brillano più luminosi.",
"How frames reach the screen while VSync is off.": "In che modo i frame raggiungono lo schermo mentre VSync è disattivato.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Sonni efficienti fino al fotogramma successivo; Rotazioni precise, come la vaniglia.",
"Fills the screen (borderless).": "Riempie lo schermo (senza bordi).",
"Brightens dark places.": "Illumina i luoghi bui.",
"Lowers the frame rate when minimised, or idle too.": "Riduce il frame rate quando è ridotto al minimo o anche inattivo.",
"Sways the view while walking.": "Oscilla la vista mentre si cammina.",
"Fades newly loaded chunks in.": "Dissolve i blocchi appena caricati.",
"Darkens the screen's edges.": "Scurisce i bordi dello schermo.",
"Shows when the world saves.": "Mostra quando il mondo salva.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Questo server è in modalità online: i profili offline non possono unirsi, ogni giocatore ha bisogno del proprio account Minecraft.",
"horizon.splitscreen.own_account": "Questo server richiede l'account Minecraft personale di ogni giocatore",
"horizon.splitscreen.local_only": "Gli altri giocatori possono unirsi a questo server solo con il proprio account Minecraft: i profili offline giocano nel tuo mondo, in LAN o su un server della tua rete locale.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Nasconde i modelli dietro blocchi opachi. Async controlla fuori thread; le entità spuntano.",
"Block Entities": "Blocca entità",
"Shulker Boxes": "Scatole Shulker",
"Reuses settled boxes; lid movement stays animated.": "Riutilizza le scatole depositate; il movimento del coperchio rimane animato.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Aperto per questa sessione dal programma che ha avviato il gioco.",
"horizon.agent.socket": "Socket: %s (copia i dettagli per il percorso completo)",
"horizon.agent.local_only": "Solo locale: agenti su questo computer, mai sulla rete.",
"%s nits": "%s lendini",
"Auto (%s nits)": "Auto (%s nit)",
"%.2f nits": "%.2f lendini",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Nasconde i modelli dietro blocchi opachi. Aggiornamento delle entità. Via con i pacchetti personalizzati.",
"Entity Culling Precheck": "Precontrollo del culling delle entità",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Esegue il precontrollo AABB dei mob dopo questo numero di mob caricati. Zero lo disattiva.",
"%s mobs": "%s mob",
@@ -308,6 +308,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "ローカルワールドの粗い遠くの地形。統合 GPU は 128 チャンクで停止します。",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "遠くの地形の描画を減らすと、より粗く、この統合された GPU ではより速く描画されます。",
"Reduced draws far terrain coarser, for GPUs it slows down.": "縮小すると、遠くの地形の描画が粗くなり、GPU の場合は速度が低下します。",
"Field of view. Wider shows more terrain at once.": "視野。幅を広くすると、より多くの地形が一度に表示されます。",
"Caps frames per second; a cap saves power and heat.": "1 秒あたりのフレーム数を制限します。キャップは電力と熱を節約します。",
"Waits for the display's refresh: no tearing, a little latency.": "ディスプレイの更新を待ちます。ティアリングはありませんが、待ち時間は少しあります。",
"Size of menus and the HUD.": "メニューと HUD のサイズ。",
@@ -340,11 +341,13 @@
"World pixels per screen pixel. Below 100% is faster on the GPU.": "画面ピクセルごとのワールド ピクセル。 100% 未満の場合、GPU での速度が速くなります。",
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "ギザギザのエッジを滑らかにします。 FXAA: 柔らかめ。 TAA: 最もスムーズですが、動いているものは尾を引く可能性があります。",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "世界を小さくレンダリングし、TAA で再構築します。より速く、よりソフトに。",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR ディスプレイ上の HDR 出力: 溶岩、火、太陽光がより明るく輝きます。",
"How frames reach the screen while VSync is off.": "VSync がオフのときにフレームが画面に到達する方法。",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "次のフレームまで効率的にスリープします。バニラのような正確なスピン。",
"Fills the screen (borderless).": "画面いっぱい(フチなし)に表示します。",
"Brightens dark places.": "暗い場所を明るくします。",
"Lowers the frame rate when minimised, or idle too.": "最小化またはアイドル時にもフレーム レートを下げます。",
"Sways the view while walking.": "歩いていると景色が揺れます。",
"Fades newly loaded chunks in.": "新しくロードされたチャンクをフェードインします。",
"Darkens the screen's edges.": "画面の端を暗くします。",
"Shows when the world saves.": "世界が救われるときを示します。",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "このサーバーはオンラインモードです: オフラインプロフィールは参加できず、各プレイヤーに専用の Minecraft アカウントが必要です。",
"horizon.splitscreen.own_account": "このサーバーでは各プレイヤー専用の Minecraft アカウントが必要です",
"horizon.splitscreen.local_only": "他のプレイヤーがこのサーバーに参加できるのは、自分の Minecraft アカウントを使う場合だけです: オフラインプロフィールは LAN かローカルネットワーク上のサーバーで、あなたのワールドをプレイします。",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "モデルを不透明なブロックの後ろに隠します。非同期チェックはオフスレッドで行われます。エンティティがティックします。",
"Block Entities": "ブロックエンティティ",
"Shulker Boxes": "シュルカーボックス",
"Reuses settled boxes; lid movement stays animated.": "固定されたボックスを再利用します。蓋の動きはアニメーションのままです。",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "ゲームを開始したプログラムによってこのセッション用に開かれました。",
"horizon.agent.socket": "ソケット: %s (フルパスの詳細をコピーします)",
"horizon.agent.local_only": "ローカルのみ: このコンピュータ上にエージェントがあり、ネットワーク上には存在しません。",
"%s nits": "%sニット",
"Auto (%s nits)": "自動 (%s ニット)",
"%.2f nits": "%.2fニット",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "モデルを不透明なブロックの後ろに隠します。エンティティが更新されます。カスタムパックでオフ。",
"Entity Culling Precheck": "エンティティカリングの事前チェック",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "読み込まれた Mob がこの数に達すると Mob の AABB 事前チェックを実行します。0 で無効。",
"%s mobs": "%s 体の Mob",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "უხეში შორეული რელიეფი ადგილობრივ სამყაროებში. ინტეგრირებული GPU ჩერდება 128 ბლოკზე.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "შემცირებული მიზიდულობა შორს რელიეფზე უფრო უხეში: უფრო სწრაფი ამ ინტეგრირებულ GPU-ზე.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "შემცირებული მიზიდულობა უფრო უხეშია, GPU-ებისთვის ის ანელებს.",
"Field of view. Wider shows more terrain at once.": "ხედვის ველი. Wider აჩვენებს მეტ რელიეფს ერთდროულად.",
"Caps frames per second; a cap saves power and heat.": "კედები წამში; თავსახური დაზოგავს ენერგიას და სითბოს.",
"Waits for the display's refresh: no tearing, a little latency.": "ელოდება ეკრანის განახლებას: არ იშლება, მცირე შეყოვნება.",
"Size of menus and the HUD.": "მენიუს ზომა და HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "არბილებს დაკბილულ კიდეებს. FXAA: უფრო რბილი. TAA: ყველაზე გლუვი, მოძრავი ნივთები შეიძლება გაიაროს.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "ამცირებს სამყაროს და აღადგენს მას TAA-ით. უფრო სწრაფი, რბილი.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "ამკვეთრებს გაზრდილ სურათს. მაღალი: უფრო მკაფიო კიდეები, მეტი ციმციმი.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR გამომავალი HDR ეკრანზე: ლავა, ცეცხლი და მზის შუქი უფრო კაშკაშა ანათებს.",
"How frames reach the screen while VSync is off.": "როგორ აღწევს ჩარჩოები ეკრანზე, როდესაც VSync გამორთულია.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "ეფექტური ძილი მომდევნო კადრამდე; ზუსტი ტრიალები, ვანილის მსგავსად.",
"Fills the screen (borderless).": "ავსებს ეკრანს (უსაზღვრო).",
"Brightens dark places.": "ანათებს ბნელ ადგილებს.",
"Lowers the frame rate when minimised, or idle too.": "ამცირებს კადრების სიხშირეს მინიმიზაციისას ან ასევე უმოქმედო მდგომარეობაში.",
"Sways the view while walking.": "სიარულის დროს ახვევს ხედს.",
"Fades newly loaded chunks in.": "აქრობს ახლად ჩატვირთულ ნაჭრებს.",
"Darkens the screen's edges.": "ბნელებს ეკრანის კიდეებს.",
"Shows when the world saves.": "აჩვენებს, როდესაც სამყარო ზოგავს.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "ეს სერვერი ონლაინ რეჟიმშია: ოფლაინ პროფილები ვერ შეუერთდებიან, თითოეულ მოთამაშეს საკუთარი Minecraft ანგარიში სჭირდება.",
"horizon.splitscreen.own_account": "ამ სერვერს თითოეული მოთამაშის საკუთარი Minecraft ანგარიში სჭირდება",
"horizon.splitscreen.local_only": "სხვა მოთამაშეები ამ სერვერს მხოლოდ საკუთარი Minecraft ანგარიშით შეუერთდებიან: ოფლაინ პროფილები თამაშობენ თქვენს სამყაროში, LAN-ზე ან თქვენს ლოკალურ ქსელში არსებულ სერვერზე.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "მალავს მოდელებს გაუმჭვირვალე ბლოკების მიღმა. ასინქრონული ამოწმებს ხაზგარეშე; ერთეულები აღნიშნავენ.",
"Block Entities": "ერთეულების დაბლოკვა",
"Shulker Boxes": "შულკერის ყუთები",
"Reuses settled boxes; lid movement stays animated.": "ხელახლა იყენებს დასახლებულ ყუთებს; სახურავის მოძრაობა ანიმაციური რჩება.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "გახსნილია ამ სესიისთვის პროგრამის მიერ, რომელმაც დაიწყო თამაში.",
"horizon.agent.socket": "სოკეტი: %s (დააკოპირეთ დეტალები მისი სრული ბილიკისთვის)",
"horizon.agent.local_only": "მხოლოდ ლოკალური: აგენტები ამ კომპიუტერზე, არასოდეს ქსელში.",
"%s nits": "%s nits",
"Auto (%s nits)": "ავტომატური (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "მალავს მოდელებს გაუმჭვირვალე ბლოკების მიღმა. ერთეულების განახლება. გამორთულია მორგებული პაკეტებით.",
"Entity Culling Precheck": "ობიექტების ამოჭრის წინასწარი შემოწმება",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "ბრბოს AABB წინასწარ შემოწმებას უშვებს ამ რაოდენობის ჩატვირთული ბრბოს შემდეგ. ნული გამორთავს.",
"%s mobs": "%s მობი",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Жергілікті әлемдердегі өрескел шалғай жер. Біріктірілген графикалық процессорлар 128 бөлікте тоқтайды.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Кішірейтілген жер бедерін дөрекі тартады: осы біріктірілген графикалық процессорда жылдамырақ.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Азайтылған жер бедерін дөрекі тартады, графикалық процессорлар үшін ол баяулайды.",
"Field of view. Wider shows more terrain at once.": "Көру алаңы. Кеңірек жерді бірден көрсетеді.",
"Caps frames per second; a cap saves power and heat.": "Секундына кадр санын басады; қалпақ қуат пен жылуды үнемдейді.",
"Waits for the display's refresh: no tearing, a little latency.": "Дисплейдің жаңаруын күтеді: жыртылмайды, аздап кідіріс.",
"Size of menus and the HUD.": "Мәзірлердің және HUD өлшемі.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Кесілген жиектерді тегістейді. FXAA: жұмсақ. TAA: ең тегіс, қозғалатын заттар ізі түсуі мүмкін.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Әлемді кішірейтеді және оны TAA көмегімен қалпына келтіреді. Жылдамырақ, жұмсақ.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Көбейтілген кескінді өткірлендіреді. Жоғарырақ: жиектер анық, жылтырау көбірек.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR дисплейіндегі HDR шығысы: лава, от және күн сәулесі жарқырайды.",
"How frames reach the screen while VSync is off.": "VSync өшірулі кезде кадрлар экранға қалай жетеді.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Келесі кадрға дейін тиімді ұйқы; Ваниль сияқты дәл айналдыру.",
"Fills the screen (borderless).": "Экранды толтырады (шексіз).",
"Brightens dark places.": "Қараңғы жерлерді жарықтандырады.",
"Lowers the frame rate when minimised, or idle too.": "Кішірейтілгенде немесе бос тұрғанда кадр жиілігін төмендетеді.",
"Sways the view while walking.": "Жүру кезінде көріністі өзгертеді.",
"Fades newly loaded chunks in.": "Жаңадан жүктелген бөліктерді өшіреді.",
"Darkens the screen's edges.": "Экранның жиектерін күңгірттендіреді.",
"Shows when the world saves.": "Әлемнің қашан құтқаратынын көрсетеді.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Бұл сервер онлайн режимінде: офлайн профильдер қосыла алмайды, әр ойыншыға өзінің Minecraft тіркелгісі қажет.",
"horizon.splitscreen.own_account": "Бұл сервер әр ойыншының жеке Minecraft тіркелгісін талап етеді",
"horizon.splitscreen.local_only": "Басқа ойыншылар бұл серверге тек өз Minecraft тіркелгісімен қосыла алады: офлайн профильдер сіздің әлеміңізде, LAN-да немесе жергілікті желідегі серверде ойнайды.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Үлгілерді мөлдір емес блоктардың артына жасырады. Асинхронды ағынды тексереді; нысандарды белгілеңіз.",
"Block Entities": "Нысандарды блоктау",
"Shulker Boxes": "Шулкер қораптары",
"Reuses settled boxes; lid movement stays animated.": "Тұндырылған қораптарды қайта пайдаланады; қақпақ қозғалысы жанды болып қалады.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Осы сеанс үшін ойынды бастаған бағдарлама ашты.",
"horizon.agent.socket": "Розетка: %s (толық жолының мәліметтерін көшіріңіз)",
"horizon.agent.local_only": "Тек жергілікті: осы компьютердегі агенттер, ешқашан желі.",
"%s nits": "%s нит",
"Auto (%s nits)": "Автоматты (%s нит)",
"%.2f nits": "%.2f нит",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Үлгілерді мөлдір емес блоктардың артына жасырады. Нысандарды жаңарту. Арнаулы бумалармен өшіру.",
"Entity Culling Precheck": "Нысандарды кесудің алдын ала тексеруі",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Осынша жүктелген мобтан кейін мобтардың AABB алдын ала тексеруін іске қосады. Нөл оны өшіреді.",
"%s mobs": "%s моб",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "ಸ್ಥಳೀಯ ಪ್ರಪಂಚಗಳಲ್ಲಿ ಒರಟಾದ ದೂರದ ಭೂಪ್ರದೇಶ. ಇಂಟಿಗ್ರೇಟೆಡ್ ಜಿಪಿಯುಗಳು 128 ಭಾಗಗಳಲ್ಲಿ ನಿಲ್ಲುತ್ತವೆ.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "ಕಡಿಮೆಗೊಳಿಸಿದ ದೂರದ ಭೂಪ್ರದೇಶವನ್ನು ಒರಟಾಗಿ ಸೆಳೆಯುತ್ತದೆ: ಈ ಇಂಟಿಗ್ರೇಟೆಡ್ GPU ನಲ್ಲಿ ವೇಗವಾಗಿ.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "ಕಡಿಮೆಗೊಳಿಸುವಿಕೆಯು ದೂರದ ಭೂಪ್ರದೇಶವನ್ನು ಒರಟಾಗಿ ಸೆಳೆಯುತ್ತದೆ, GPU ಗಳಿಗೆ ಇದು ನಿಧಾನಗೊಳಿಸುತ್ತದೆ.",
"Field of view. Wider shows more terrain at once.": "ವೀಕ್ಷಣೆಯ ಕ್ಷೇತ್ರ. ವೈಡರ್ ಒಮ್ಮೆ ಹೆಚ್ಚು ಭೂಪ್ರದೇಶವನ್ನು ತೋರಿಸುತ್ತದೆ.",
"Caps frames per second; a cap saves power and heat.": "ಪ್ರತಿ ಸೆಕೆಂಡಿಗೆ ಕ್ಯಾಪ್ ಚೌಕಟ್ಟುಗಳು; ಒಂದು ಕ್ಯಾಪ್ ಶಕ್ತಿ ಮತ್ತು ಶಾಖವನ್ನು ಉಳಿಸುತ್ತದೆ.",
"Waits for the display's refresh: no tearing, a little latency.": "ಡಿಸ್‌ಪ್ಲೇಯ ರಿಫ್ರೆಶ್‌ಗಾಗಿ ಕಾಯುತ್ತಿದೆ: ಯಾವುದೇ ಹರಿದಿಲ್ಲ, ಸ್ವಲ್ಪ ಸುಪ್ತತೆ.",
"Size of menus and the HUD.": "ಮೆನುಗಳ ಗಾತ್ರ ಮತ್ತು HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "ಮೊನಚಾದ ಅಂಚುಗಳನ್ನು ಸುಗಮಗೊಳಿಸುತ್ತದೆ. FXAA: ಮೃದುವಾದ. TAA: ನಯವಾದ, ಚಲಿಸುವ ವಸ್ತುಗಳು ಜಾಡು ಹಿಡಿಯಬಹುದು.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "ಜಗತ್ತನ್ನು ಚಿಕ್ಕದಾಗಿಸುತ್ತದೆ ಮತ್ತು TAA ಯೊಂದಿಗೆ ಅದನ್ನು ಮರುನಿರ್ಮಾಣ ಮಾಡುತ್ತದೆ. ವೇಗವಾಗಿ, ಮೃದುವಾಗಿ.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "ಅಪ್‌ಸ್ಕೇಲ್ ಮಾಡಿದ ಚಿತ್ರವನ್ನು ತೀಕ್ಷ್ಣಗೊಳಿಸುತ್ತದೆ. ಹೆಚ್ಚು: ಸ್ಪಷ್ಟ ಅಂಚುಗಳು, ಹೆಚ್ಚು ಮಿನುಗುವಿಕೆ.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR ಪ್ರದರ್ಶನದಲ್ಲಿ HDR ಔಟ್‌ಪುಟ್: ಲಾವಾ, ಬೆಂಕಿ ಮತ್ತು ಸೂರ್ಯನ ಬೆಳಕು ಪ್ರಕಾಶಮಾನವಾಗಿ ಹೊಳೆಯುತ್ತದೆ.",
"How frames reach the screen while VSync is off.": "VSync ಆಫ್ ಆಗಿರುವಾಗ ಫ್ರೇಮ್‌ಗಳು ಹೇಗೆ ಪರದೆಯನ್ನು ತಲುಪುತ್ತವೆ.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "ಮುಂದಿನ ಚೌಕಟ್ಟಿನವರೆಗೆ ಸಮರ್ಥ ನಿದ್ರೆ; ವೆನಿಲ್ಲಾದಂತಹ ನಿಖರವಾದ ಸ್ಪಿನ್‌ಗಳು.",
"Fills the screen (borderless).": "ಪರದೆಯನ್ನು ತುಂಬುತ್ತದೆ (ಗಡಿರಹಿತ).",
"Brightens dark places.": "ಡಾರ್ಕ್ ಸ್ಥಳಗಳನ್ನು ಬೆಳಗಿಸುತ್ತದೆ.",
"Lowers the frame rate when minimised, or idle too.": "ಕಡಿಮೆಗೊಳಿಸಿದಾಗ ಅಥವಾ ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದಾಗ ಫ್ರೇಮ್ ದರವನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ.",
"Sways the view while walking.": "ನಡೆಯುವಾಗ ನೋಟವನ್ನು ತಿರುಗಿಸುತ್ತದೆ.",
"Fades newly loaded chunks in.": "ಹೊಸದಾಗಿ ಲೋಡ್ ಮಾಡಿದ ಭಾಗಗಳನ್ನು ಮಸುಕಾಗಿಸುತ್ತದೆ.",
"Darkens the screen's edges.": "ಪರದೆಯ ಅಂಚುಗಳನ್ನು ಕಪ್ಪಾಗಿಸುತ್ತದೆ.",
"Shows when the world saves.": "ಜಗತ್ತು ಉಳಿಸಿದಾಗ ತೋರಿಸುತ್ತದೆ.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "ಈ ಸರ್ವರ್ ಆನ್‌ಲೈನ್ ಮೋಡ್‌ನಲ್ಲಿದೆ: ಆಫ್‌ಲೈನ್ ಪ್ರೊಫೈಲ್‌ಗಳು ಸೇರಲಾಗುವುದಿಲ್ಲ, ಪ್ರತಿ ಆಟಗಾರನಿಗೂ ತನ್ನದೇ Minecraft ಖಾತೆ ಬೇಕು.",
"horizon.splitscreen.own_account": "ಈ ಸರ್ವರ್‌ಗೆ ಪ್ರತಿ ಆಟಗಾರನ ತನ್ನದೇ Minecraft ಖಾತೆ ಬೇಕು",
"horizon.splitscreen.local_only": "ಇತರ ಆಟಗಾರರು ತಮ್ಮದೇ Minecraft ಖಾತೆಯಿಂದ ಮಾತ್ರ ಈ ಸರ್ವರ್‌ಗೆ ಸೇರಬಹುದು: ಆಫ್‌ಲೈನ್ ಪ್ರೊಫೈಲ್‌ಗಳು ನಿಮ್ಮ ಜಗತ್ತಿನಲ್ಲಿ, LAN ನಲ್ಲಿ ಅಥವಾ ನಿಮ್ಮ ಸ್ಥಳೀಯ ನೆಟ್‌ವರ್ಕ್‌ನ ಸರ್ವರ್‌ನಲ್ಲಿ ಆಡುತ್ತವೆ.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "ಅಪಾರದರ್ಶಕ ಬ್ಲಾಕ್ಗಳ ಹಿಂದೆ ಮಾದರಿಗಳನ್ನು ಮರೆಮಾಡುತ್ತದೆ. ಅಸಿಂಕ್ ಆಫ್-ಥ್ರೆಡ್ ಅನ್ನು ಪರಿಶೀಲಿಸುತ್ತದೆ; ಘಟಕಗಳು ಟಿಕ್.",
"Block Entities": "ಘಟಕಗಳನ್ನು ನಿರ್ಬಂಧಿಸಿ",
"Shulker Boxes": "ಶುಲ್ಕರ್ ಪೆಟ್ಟಿಗೆಗಳು",
"Reuses settled boxes; lid movement stays animated.": "ನೆಲೆಗೊಂಡ ಪೆಟ್ಟಿಗೆಗಳನ್ನು ಮರುಬಳಕೆ ಮಾಡುತ್ತದೆ; ಮುಚ್ಚಳದ ಚಲನೆಯು ಅನಿಮೇಟೆಡ್ ಆಗಿರುತ್ತದೆ.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "ಆಟವನ್ನು ಪ್ರಾರಂಭಿಸಿದ ಕಾರ್ಯಕ್ರಮದಿಂದ ಈ ಸೆಶನ್‌ಗಾಗಿ ತೆರೆಯಲಾಗಿದೆ.",
"horizon.agent.socket": "ಸಾಕೆಟ್: %s (ಅದರ ಸಂಪೂರ್ಣ ಮಾರ್ಗಕ್ಕಾಗಿ ವಿವರಗಳನ್ನು ನಕಲಿಸಿ)",
"horizon.agent.local_only": "ಸ್ಥಳೀಯ ಮಾತ್ರ: ಈ ಕಂಪ್ಯೂಟರ್‌ನಲ್ಲಿ ಏಜೆಂಟ್‌ಗಳು, ಎಂದಿಗೂ ನೆಟ್‌ವರ್ಕ್ ಅಲ್ಲ.",
"%s nits": "%s ನಿಟ್ಸ್",
"Auto (%s nits)": "ಸ್ವಯಂ (%s ನಿಟ್ಸ್)",
"%.2f nits": "%.2f ನಿಟ್ಸ್",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "ಅಪಾರದರ್ಶಕ ಬ್ಲಾಕ್ಗಳ ಹಿಂದೆ ಮಾದರಿಗಳನ್ನು ಮರೆಮಾಡುತ್ತದೆ. ಘಟಕಗಳನ್ನು ನವೀಕರಿಸಿ. ಕಸ್ಟಮ್ ಪ್ಯಾಕ್‌ಗಳೊಂದಿಗೆ ಆಫ್ ಮಾಡಿ.",
"Entity Culling Precheck": "ಘಟಕ ಕಲ್ಲಿಂಗ್ ಪೂರ್ವಪರಿಶೀಲನೆ",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "ಇಷ್ಟು ಮಾಬ್‌ಗಳು ಲೋಡ್ ಆದ ನಂತರ ಮಾಬ್ AABB ಪೂರ್ವಪರಿಶೀಲನೆಯನ್ನು ಚಲಾಯಿಸುತ್ತದೆ. ಶೂನ್ಯ ಅದನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.",
"%s mobs": "%s ಮಾಬ್‌ಗಳು",
@@ -308,6 +308,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "로컬 월드의 거친 원거리 지형. 내장 GPU는 128청크에서 제한됩니다.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "감소 설정 시 원거리 지형을 더 거칠게 그려 이 내장 GPU에서 더 빠르게 작동합니다.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "감소 설정 시 원거리 지형을 더 거칠게 그려 GPU 속도가 느려질 수 있습니다.",
"Field of view. Wider shows more terrain at once.": "시야각. 넓을수록 한 번에 더 많은 지형이 표시됩니다.",
"Caps frames per second; a cap saves power and heat.": "초당 최대 프레임을 제한합니다. 제한하면 전력과 발열을 줄일 수 있습니다.",
"Waits for the display's refresh: no tearing, a little latency.": "디스플레이 새로 고침을 기다립니다: 화면 찢김이 없지만 약간의 지연 시간이 발생합니다.",
"Size of menus and the HUD.": "메뉴 및 HUD의 크기입니다.",
@@ -340,11 +341,13 @@
"World pixels per screen pixel. Below 100% is faster on the GPU.": "화면 픽셀당 월드 픽셀 수입니다. 100% 미만으로 설정하면 GPU에서 더 빨라집니다.",
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "거친 모서리를 부드럽게 합니다. FXAA: 부드러움. TAA: 가장 부드러움, 움직이는 물체에 잔상이 남을 수 있음.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "월드를 작게 렌더링한 후 TAA로 재구성합니다. 더 빠르고 부드러움.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR 디스플레이에서 HDR 출력: 용암, 불, 햇빛이 더 밝게 빛납니다.",
"How frames reach the screen while VSync is off.": "수직 동기화가 꺼져있을 때 프레임이 화면에 도달하는 방식입니다.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "효율적 모드는 다음 프레임까지 대기(sleep)하고, 정밀 모드는 바닐라처럼 회전(spin)합니다.",
"Fills the screen (borderless).": "화면을 채웁니다(테두리 없는 창 모드).",
"Brightens dark places.": "어두운 곳을 밝게 합니다.",
"Lowers the frame rate when minimised, or idle too.": "창이 최소화되거나 유휴 상태일 때 프레임 레이트를 낮춥니다.",
"Sways the view while walking.": "걸을 때 시야가 흔들립니다.",
"Fades newly loaded chunks in.": "새로 로드된 청크가 서서히 나타나도록 합니다.",
"Darkens the screen's edges.": "화면 가장자리를 어둡게 합니다.",
"Shows when the world saves.": "월드가 저장되는 시점을 표시합니다.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "이 서버는 온라인 모드입니다: 오프라인 프로필은 참가할 수 없으며 각 플레이어에게 자체 Minecraft 계정이 필요합니다.",
"horizon.splitscreen.own_account": "이 서버는 각 플레이어의 자체 Minecraft 계정이 필요합니다",
"horizon.splitscreen.local_only": "다른 플레이어는 자체 Minecraft 계정으로만 이 서버에 참가할 수 있습니다: 오프라인 프로필은 LAN 또는 로컬 네트워크의 서버에서 내 월드로 플레이합니다.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "불투명 블록 뒤의 모델을 숨깁니다. 비동기 검사는 오프스레드에서 실행되며 엔티티는 틱을 진행합니다.",
"Block Entities": "블록 엔티티",
"Shulker Boxes": "셜커 상자",
"Reuses settled boxes; lid movement stays animated.": "고정된 상자를 재사용하며 뚜껑 움직임은 애니메이션이 유지됩니다.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "게임을 시작한 프로그램에 의해 이 세션이 열렸습니다.",
"horizon.agent.socket": "소켓: %s (전체 경로는 세부 정보 복사 사용)",
"horizon.agent.local_only": "로컬 전용: 이 컴퓨터의 에이전트만 허용하며 네트워크는 허용하지 않습니다.",
"%s nits": "%s 니트",
"Auto (%s nits)": "자동 (%s 니트)",
"%.2f nits": "%.2f 니트",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "불투명 블록 뒤의 모델을 숨깁니다. 엔티티는 업데이트됩니다. 커스텀 팩 사용 시 꺼집니다.",
"Entity Culling Precheck": "엔티티 컬링 사전 검사",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "로드된 몹이 이 수를 넘으면 몹 AABB 사전 검사를 실행합니다. 0이면 비활성화됩니다.",
"%s mobs": "%s마리 몹",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Жергиликтүү дүйнөдө одоно алыскы рельеф. Интеграцияланган GPU 128 бөлүктө токтойт.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Кыскартылган жер рельефин одонораак тартат: бул интеграцияланган GPUде ылдамыраак.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Кыскартылган жер рельефин катуураак тартат, ал эми GPU үчүн ал жайлатат.",
"Field of view. Wider shows more terrain at once.": "Көрүү талаасы. Кененирээк бир эле учурда көбүрөөк жерди көрсөтөт.",
"Caps frames per second; a cap saves power and heat.": "Кадрларды секундасына баш тамгалар; капкак электр жана жылуулукту үнөмдөйт.",
"Waits for the display's refresh: no tearing, a little latency.": "Дисплейдин жаңыланышын күтөт: жыртылбайт, бир аз кечигүү.",
"Size of menus and the HUD.": "Менюлардын өлчөмү жана HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Тиштелген четтерин тегиздейт. FXAA: жумшак. TAA: эң жылмакай, кыймылдуу нерселер артта калышы мүмкүн.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Дүйнөнү кичирейтип, TAA менен кайра курат. Тезирээк, жумшак.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Масштабдалган сүрөттү курчутат. Жогору: кырлар ачык, бирок жалтылдоо көп.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR дисплейдеги HDR чыгарылышы: лава, от жана күн нуру жаркырайт.",
"How frames reach the screen while VSync is off.": "VSync өчүк болгондо кадрлар экранга кантип жетет.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Кийинки кадрга чейин эффективдүү уктоо; Ваниль сыяктуу так айлануу.",
"Fills the screen (borderless).": "Экранды толтурат (чексиз).",
"Brightens dark places.": "Караңгы жерлерди жарык кылат.",
"Lowers the frame rate when minimised, or idle too.": "Кичирейтилгенде же бош турганда кадр ылдамдыгын төмөндөтөт.",
"Sways the view while walking.": "Басып баратканда көз карашты бурат.",
"Fades newly loaded chunks in.": "Жаңы жүктөлгөн бөлүктөрдү өчүрөт.",
"Darkens the screen's edges.": "Экрандын четтерин караңгылатат.",
"Shows when the world saves.": "Дүйнө качан сактаарын көрсөтөт.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Бул сервер онлайн режиминде: офлайн профилдер кошула албайт, ар бир оюнчуга өзүнүн Minecraft аккаунту керек.",
"horizon.splitscreen.own_account": "Бул сервер ар бир оюнчунун өз Minecraft аккаунтун талап кылат",
"horizon.splitscreen.local_only": "Башка оюнчулар бул серверге өз Minecraft аккаунту менен гана кошула алышат: офлайн профилдер сиздин дүйнөңүздө, LANда же жергиликтүү тармактагы серверде ойной алышат.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Тунук эмес блоктордун артына моделдерди жашырат. Асинхрондук текшерүүлөр жиптен тышкары; субъектилер белги.",
"Block Entities": "Блок объектилери",
"Shulker Boxes": "Shulker кутучалары",
"Reuses settled boxes; lid movement stays animated.": "отургузулган кутуларды кайра колдонот; капкак кыймылы жандуу бойдон кала берет.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Бул сессия үчүн оюнду баштаган программа тарабынан ачылган.",
"horizon.agent.socket": "Розетка: %s (анын толук жолунун чоо-жайын көчүрүңүз)",
"horizon.agent.local_only": "Жергиликтүү гана: бул компьютердеги агенттер, тармак эч качан.",
"%s nits": "%s нит",
"Auto (%s nits)": "Авто (%s нит)",
"%.2f nits": "%.2f нит",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Тунук эмес блоктордун артына моделдерди жашырат. Объекттерди жаңыртуу. Ыңгайлаштырылган пакеттер менен өчүрүү.",
"Entity Culling Precheck": "Объектилерди кесүүнүн алдын ала текшерүүсү",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Жүктөлгөн жаныбарлардын саны ушунча болгондон кийин AABB алдын ала текшерүүсүн иштетет. Нөл өчүрөт.",
"%s mobs": "%s жаныбар",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Crassum longinquis locorum in mundos. Integrated GPUs consistunt in 128 chunks.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reducitur ad loca longe crassius: citius in hoc GPU integratur.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Crassiorem re- trahit loca longe, GPUs enim retardat.",
"Field of view. Wider shows more terrain at once.": "Ager conspectus. Latiora simul loca plura ostendit.",
"Caps frames per second; a cap saves power and heat.": "Caps tabulae secundae; pileus virtutem et calorem servat.",
"Waits for the display's refresh: no tearing, a little latency.": "Expectat ad ostentationem reficiendam: non laceratio, paulo latens.",
"Size of menus and the HUD.": "Magnitudo menus et TESTA.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Marginibus teretibus serratis. FXAA: mollior. TAA: lenissima, mo- res trahens.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Mundum reddit minorem et aedificat cum TAA. Velocius, mollior.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Imaginem upscalatam acuit. Altius: margines acutiores, plus fulgoris.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR output in HDR ostensio: lava, ignis et lux clarius lucent.",
"How frames reach the screen while VSync is off.": "Quomodo tabulae ad tentorium perveniunt dum VSync absistit.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efficacior deinde artubus dum dormit; Plane rotat, ut vanilla.",
"Fills the screen (borderless).": "Velamentum implet (borderless).",
"Brightens dark places.": "Lucet latebras.",
"Lowers the frame rate when minimised, or idle too.": "Framam rate demittit cum minimo, vel nimis otioso.",
"Sways the view while walking.": "Visum flectit ambulans.",
"Fades newly loaded chunks in.": "Ventris nuper onustus chunks in.",
"Darkens the screen's edges.": "Obtenebrat oras scrinii.",
"Shows when the world saves.": "Ostendit quando mundus salvatur.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Hic servus in modo online est: profila offline iungere non possunt, quisque lusor rationem Minecraft suam requirit.",
"horizon.splitscreen.own_account": "Hic servus rationem Minecraft cuiusque lusoris requirit",
"horizon.splitscreen.local_only": "Alii lusores hunc servum solum ratione Minecraft sua iungere possunt: profila offline in mundo tuo, in LAN aut in servo retis localis tui ludunt.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Coria post caudices opaca exempla. Async linum cohibet; entia tick.",
"Block Entities": "Obstructionum Entities",
"Shulker Boxes": "Shulker Pyxidas",
"Reuses settled boxes; lid movement stays animated.": "Reuses scriniorum consederunt; operculo motus animatus.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Aperta est huic sessioni per rationem quam ludum incepit.",
"horizon.agent.socket": "Tabernae:%s(Effingo singula ad suum plenum iter)",
"horizon.agent.local_only": "Local only: agentes in hoc computatorio, aeneum numquam.",
"%s nits": "%snits",
"Auto (%s nits)": "Automaticum (%s nits)",
"%.2f nits": "%.2f.2nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Coria post caudices opaca exempla. Renovatio entia. More off cum sarcinis.",
"Entity Culling Precheck": "Praecensura exclusionis entium",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Praecensuram AABB mobium post tot mobs oneratos agit. Nihil eam exstinguit.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grof wäitem Terrain an lokal Welten. Integréiert GPUs stoppen op 128 Stécker.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Reduzéiert zitt wäit Terrain méi grober: méi séier op dëser integréiert GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Reduzéiert zitt wäit terrain méi grober, fir GPUs et bremst.",
"Field of view. Wider shows more terrain at once.": "Gesiichtsfeld. Breet weist méi Terrain op eemol.",
"Caps frames per second; a cap saves power and heat.": "Caps Rummen pro Sekonn; eng Kap spuert Kraaft an Hëtzt.",
"Waits for the display's refresh: no tearing, a little latency.": "Waart op d'Erfrëschung vum Display: kee räissen, e bësse latency.",
"Size of menus and the HUD.": "Gréisst vun de Menüen an den HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Gläicht geckeg Kanten. FXAA: méi mëll. TAA: glatsten, bewegt Saachen kënnen verfollegen.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Maacht d'Welt méi kleng a baut se mat TAA op. Méi séier, méi mëll.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Macht d'upscalte Bild méi schaarf. Méi héich: méi schaarf Kanten, méi Schimmer.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR Ausgang op engem HDR Display: Lava, Feier a Sonneliicht blénken méi hell.",
"How frames reach the screen while VSync is off.": "Wéi Rummen erreechen Écran iwwerdeems VSync aus ass.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Effikass schléift bis den nächsten Frame; Präzis Spins, wéi Vanille.",
"Fills the screen (borderless).": "Fëllt den Ecran (randlos).",
"Brightens dark places.": "Helles däischter Plazen.",
"Lowers the frame rate when minimised, or idle too.": "Senkt de Frame Taux wann miniméiert, oder och Idle.",
"Sways the view while walking.": "Sways d'Vue beim Fouss.",
"Fades newly loaded chunks in.": "Fades nei gelueden Stécker an.",
"Darkens the screen's edges.": "Däischter d'Kante vum Écran.",
"Shows when the world saves.": "Weist wann d'Welt rett.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Dëse Server ass am Online-Modus: Offline-Profiler kënnen net bäitrieden, all Spiller brauch säin eegene Minecraft-Kont.",
"horizon.splitscreen.own_account": "Dëse Server brauch fir all Spiller säin eegene Minecraft-Kont",
"horizon.splitscreen.local_only": "Aner Spiller kënnen dësem Server nëmme mat hirem eegene Minecraft-Kont bäitrieden: Offline-Profiler spillen an Ärer Welt, am LAN oder op engem Server an Ärem lokalen Netz.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Verstoppt Modeller hannert opaken Blöcke. Async kontrolléiert Off-Thread; Entitéiten ticken.",
"Block Entities": "Block Entitéiten",
"Shulker Boxes": "Shulker Këschte",
"Reuses settled boxes; lid movement stays animated.": "Wiederbenotzt geséchert Këschte; Deckelbewegung bleift animéiert.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Opgemaach fir dës Sessioun vum Programm deen d'Spill ugefaang huet.",
"horizon.agent.socket": "Socket: %s (kopéiert d'Detailer fir säi ganze Wee)",
"horizon.agent.local_only": "Nëmme lokal: Agenten op dësem Computer, ni am Netz.",
"%s nits": "%s nit",
"Auto (%s nits)": "Auto (%s Nits)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Verstoppt Modeller hannert opaken Blöcke. Entitéiten update. Off mat personaliséierte Packs.",
"Entity Culling Precheck": "Entitéit-Culling-Virprüfung",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Féiert d'Mob-AABB-Virprüfung no dëser Unzuel geluedene Mobs aus. Null deaktivéiert se.",
"%s mobs": "%s Mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grof aafgelege terrein in lokale werelde. Geïntegreerde GPU’s stoppe op 128 stukke.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Verminderd trek terrein väöl grover: sneller op deze geïntegreerde GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Verminderd trek ‘t terrein väöl grover, veur GPU’s vertraag ‘t.",
"Field of view. Wider shows more terrain at once.": "Gezichtsveld. Breider toent mie terrein tegeliekertied.",
"Caps frames per second; a cap saves power and heat.": "Cap frames per seconde; ‘n pet spaart energie en wermte.",
"Waits for the display's refresh: no tearing, a little latency.": "Wacht op ‘t verfrisse vaan ‘t sjerm: gein scheur, ‘n bietje vertraging.",
"Size of menus and the HUD.": "Grootte vaan de menu’s en de HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Maak gekarfde rande glad. FXAA: zachter. TAA: vloeiendste, bewegende dinger kinne achterloupe.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Maak de wereld kleiner en verbouwt ‘m mit TAA. Sneller, zachter.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Maak ‘t opgesjkaold beeld sjerper. Hoeger: sjerpere rande, mie glans.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR-oetvoer op un HDR-display: lava, vuur en zonleech schijne helderder.",
"How frames reach the screen while VSync is off.": "Wie frames ‘t sjerm bereike onderwieles dat VSync oet is.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efficiënte slaop tot ‘t volgende frame; Precieze spins, wie vanille.",
"Fills the screen (borderless).": "Völt ‘t sjerm (grensloos).",
"Brightens dark places.": "Verheldert doonkere plekke.",
"Lowers the frame rate when minimised, or idle too.": "Verlieg de framesnelheid es ‘t minimaliseerd is, of ouch inactief.",
"Sways the view while walking.": "Swaai ‘t oetzich onderwieles dat ge laope.",
"Fades newly loaded chunks in.": "Vervaag nuuj gelaoje stukke in.",
"Darkens the screen's edges.": "Verduustert de rande vaan ‘t sjerm.",
"Shows when the world saves.": "Laot zien wienie de wereld redt.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Dees server is in online modus: offline profiele kinne d’r neet aonslete, eder speuler heet zien eige Minecraft-account nuudig.",
"horizon.splitscreen.own_account": "Deze server heet eder speuler zien eige Minecraft-account nuudig",
"horizon.splitscreen.local_only": "Aandere speulers kinne allein mit hun eige Minecraft-account bij deze server aantrejje: offline profiele spele in eur wereld, op LAN of op un server op eur lokaal netwerk.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Verberg modelle achter ondudelike blokke. Async controleert off-thread; entiteite tikke.",
"Block Entities": "Entiteite blokkere",
"Shulker Boxes": "Shulkerbokse",
"Reuses settled boxes; lid movement stays animated.": "Hergebruuk geplaatste kiste; de beweginge vaan de deksel blief geanimeerd.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Geopend veur deze sessie door ‘t programma dat ‘t spel heet begós.",
"horizon.agent.socket": "Socket: %s (kopieer de details veur de volledige paad)",
"horizon.agent.local_only": "Allein lokaal: agente op deze computer, noets op ‘t netwerk.",
"%s nits": "%s nits",
"Auto (%s nits)": "Auto (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Verberg modelle achter ondudelike blokke. Entiteite update. Aaf mit aangepaste pakke.",
"Entity Culling Precheck": "Entiteit-culling veurcontrole",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Voert de AABB-veurcontrole oet vaanaaf dit aontal gelaoje mobs. Nöl sjelt ‘t oet.",
"%s mobs": "%s mobs",
@@ -301,6 +301,7 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Terren luntan gross in di mund locai. I GPU integrà se ferman a 128 pezz.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Disegn ridott el terren püsee gross: püsee veloce sü chesta GPU integrada.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Disegn ridott tira un terren püsee gross, per i GPU rallenta.",
"Field of view. Wider shows more terrain at once.": "Camp de vista. Plü grand mustra püsee terren a la volta.",
"Caps frames per second; a cap saves power and heat.": "Caps fotogramm al segund; un tapp risparmia energia e calor.",
"Waits for the display's refresh: no tearing, a little latency.": "Aspetta el rinfresc del schermu: nissun stracc, un pooch de latenza.",
"Size of menus and the HUD.": "Dimensiun di menù e del HUD.",
@@ -338,11 +339,13 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Liscia i bord sgrifolà. FXAA: püsee morbido. TAA: i ròbb püsee lisc e en muviment pœden traccià.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Rend el mund püsee piscinin e el recostruiss cun TAA. Püsee veloce, püsee morbido.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "El fà püsee nitida la imagen scalada. Püsee volt: bord püsee nets, püsee scintillament.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "Uscita HDR sü un schermu HDR: lava, fœuch e lüs del sul brillan püsee.",
"How frames reach the screen while VSync is off.": "Cuma i fotogramm rivan al schermo menter VSync l’è desligaa.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Dormi eficient fin al quader sucesif; Spin precis, come la vaniglia.",
"Fills the screen (borderless).": "Riempi el schermo (senza cunfin).",
"Brightens dark places.": "Illumina i sit scüri.",
"Lowers the frame rate when minimised, or idle too.": "Sbassa la frequenza di fotogramm quand l’è minimizzada o anca inattiva.",
"Sways the view while walking.": "Oscilla la vista mentre camina.",
"Fades newly loaded chunks in.": "Sbiadiss i pezz appena caricà denter.",
"Darkens the screen's edges.": "Scüra i bord del schermo.",
"Shows when the world saves.": "Mostra quand el mund salva.",
@@ -553,6 +556,7 @@
"horizon.splitscreen.online_only": "Chestu server l’è en modalità online: i profil fœura linea pœden minga entrà denter, ogni giucadur g’ha bisogn de un propri cunt Minecraft.",
"horizon.splitscreen.own_account": "Chestu server g’ha bisogn de un cunt Minecraft de ogni giucadur",
"horizon.splitscreen.local_only": "Olter giucadur pœden entrà en chestu server sultant cunt el propri cunt Minecraft: i profil offline giœgan in del vòster mund, sü LAN o sü un server sü la vòstra red local.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Ascünd i mudei deré di blocch opach. Async checks off-thread; entità marca.",
"Block Entities": "Entità de blocch",
"Shulker Boxes": "Scatole Shulker",
"Reuses settled boxes; lid movement stays animated.": "Reuses settled boxes; el muviment de la tapa resta animad.",
@@ -617,6 +621,10 @@
"horizon.agent.session_opened": "Apert per chesta sesiun dal prugrama che g’ha inizià el giœugh.",
"horizon.agent.socket": "Presa: %s (copia i detai per el sò percors cumplet)",
"horizon.agent.local_only": "Sultant local: agent sü chestu urdinaduur, mai sü la red.",
"%s nits": "%s nit",
"Auto (%s nits)": "Auto (%s nit)",
"%.2f nits": "%.2f nit",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Ascünd i mudei deré di blocch opach. Aggiornament di entità. Off cun i pachett personalizà.",
"Entity Culling Precheck": "Precontroll de l'eliminaziun di entità",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "El fà girà el precontroll AABB di mob dopu chest tanti mob cargà. Zero el disabilita.",
"%s mobs": "%s mob",
Loaded 100 of 742 files, more files were not shown because too many files have changed in this diff. Show more