Compare commits

...
485 Commits
Author SHA1 Message Date
rdbt a30ed9e44d Merge pull request #15746 from Joansitoh/fix/prediction-history-gap-rebase
Anticheat prediction: a history gap rebases the replay instead of dropping it
2026-11-13 02:55:01 +00:00
rdbt 1a6885f931 Merge pull request #15700 from kacpherek/feat/graphics-presets
Graphics: a Full Performance preset, and every preset a fixed table
2026-11-13 02:54:57 +00:00
rdbt ea50823946 Merge pull request #15695 from NikitaMGrimm/docs/pr-size-what-counts
Docs: say what counts towards the 500-line pull request size
2026-11-13 02:54:52 +00:00
rdbt 98d7a0ce3c Merge pull request #15637 from kacpherek/fix/vanilla-glider-wear
Wear a glider held in a hand like a worn one
2026-11-13 02:54:48 +00:00
rdbt b6db19caad Merge pull request #15636 from kacpherek/fix/vanilla-mob-equipment-compass
Tick the compasses mobs hold or wear so a gone lodestone clears their target
2026-11-13 02:54:44 +00:00
rdbt fce155af99 Merge pull request #15634 from kacpherek/fix/vanilla-player-fall-block-sound
Play the block fall sound after a player's damaging fall
2026-11-13 02:54:40 +00:00
rdbt f0d82fdfd4 Merge pull request #15630 from kacpherek/fix/vanilla-item-damage
Hurt dropped items by lightning and explosions through damage_resistant, as vanilla does
2026-11-13 02:54:36 +00:00
rdbt 532f398264 Merge pull request #15629 from kacpherek/fix/vanilla-mending-effect
Pick Mending repair slots by the repair_with_xp effect, as vanilla does
2026-11-13 02:54:31 +00:00
rdbt e8ce5ad796 Merge pull request #15626 from kacpherek/fix/vanilla-powder-snow
Give every mob and a LAN guest's prediction powder snow's contextual collision
2026-11-13 02:54:27 +00:00
rdbt f88e4141b3 Merge pull request #15625 from kacpherek/fix/vanilla-item-use
End item use the way vanilla does: bundle completion, a changed hand item, stopUsingItem paths
2026-11-13 02:54:23 +00:00
rdbt eb17be4d56 Merge pull request #15513 from yahya-nusseibeh/fix/websocket-control-frames
WebSocket: control frames must come whole and short
2026-11-13 02:54:19 +00:00
rdbt cf0ed1d1ad Merge pull request #15442 from Ragbie/fix/windows-open-folder-shell
Windows: open the pack, world and backup folders in the default file manager
2026-11-13 02:54:15 +00:00
rdbt 7f469386ae Merge pull request #15440 from kacpherek/revert/13737-boat-fire
Revert #13737: boats fail the boat_fire harness
2026-11-13 02:54:10 +00:00
rdbt f1fe19a41e Merge pull request #15431 from Detimes/oc-equipment-ids
Older clients through 1.21.6: read equipment in the client's ids
2026-11-13 02:54:06 +00:00
rdbt 3f25aa9af4 Merge pull request #15430 from Detimes/oc-entity-data
Older clients: entity data in their own serializer ids
2026-11-13 02:54:01 +00:00
rdbt 77f66c55e5 Merge pull request #15428 from lucasmts59/fix/core-shader-int-constant-arrays
Core shaders: an array sized by a local int constant takes its expression
2026-11-13 02:53:57 +00:00
rdbt 07244d141b Merge pull request #15426 from kacpherek/fix/13648-crossbow-arrow-hit-sound
A crossbow arrow switches to the arrow hit sound after its first block hit
2026-11-13 02:53:52 +00:00
rdbt 0d83e5950c Merge pull request #15425 from kacpherek/fix/12320-debug-world-type
Offer Debug Mode on the world type button while Alt is held
2026-11-13 02:53:48 +00:00
rdbt 0ffa0ca457 Merge pull request #15203 from darkliro/perf/upload-budget-follows-frame
perf: adapt chunk mesh upload budget to frame pace
2026-11-13 02:53:40 +00:00
rdbt 4a63b64a17 Merge pull request #15128 from MSedgeMC/fix/wololo-visibility-percent
An invisible flag shrinks the wololo range
2026-11-13 02:53:32 +00:00
rdbt d19eb22735 Merge pull request #14901 from MSedgeMC/fix/chat-double-click-word
Double-clicking the chat box selects the word
2026-11-13 02:53:22 +00:00
rdbt d68f973fab Merge pull request #14811 from tarzinio/fix-far-detail-resample
Sample LOD tiles again when Far detail changes
2026-11-13 02:53:15 +00:00
rdbt fe56b24a49 Merge pull request #14642 from JustKarkat/fix/crafting-book-non-craftable-retry
fix: allow retry-clicking non-craftable recipes in the recipe book
2026-11-13 02:53:09 +00:00
rdbt 824b351d69 Merge pull request #14395 from oloion/perf/label-layout-no-alloc
ui: eliminate heap allocations in label layout and measurement
2026-11-13 02:53:05 +00:00
rdbt 3ccb74b6c1 Merge pull request #14294 from MSedgeMC/fix/piglin-cannot-hunt
A piglin keeps its saved CannotHunt flag
2026-11-13 02:53:01 +00:00
rdbt 7b5114bb29 Merge pull request #14268 from Joansitoh/fix/13632-atlas-sprites
Resolve inline atlas sprites in their named atlas
2026-11-13 02:52:55 +00:00
rdbt b7bf1c97c6 Merge pull request #14257 from vnsmoreira/fix/crafter-triggered-int
A crafter keeps its triggered int and triggers only at 1
2026-11-13 02:52:51 +00:00
rdbt d3723c53b5 Merge pull request #13831 from RINNECODER/up13/lang-dead-keys
Game translations: drop 8 keys no code asks for, and check en_us against the code
2026-11-13 02:52:47 +00:00
rdbt 9f42064c11 Merge pull request #15867 from rdbtCVS/fix/pet-owner-teleport-stroll
pet_owner_teleport: a wolf that came may stroll off; count 16 blocks as near
2026-11-13 02:39:12 +00:00
rdbtCVSandClaude Opus 5.5 a13a21c522 pet_owner_teleport: count a wolf within 16 blocks as come to its owner
A tame wolf that teleported to Alice keeps strolling (WaterAvoidingRandomStrollGoal,
up to 10 blocks) and only walks back from 10 blocks, so a few seconds later it can
be 6 to 12 blocks from her, in vanilla as in Horizon. The 6-block check failed on
that at random (#15483; parity-main 43332620951 bisected it to unrelated merges).
Wolves left behind stay 28 blocks or more away.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-13 02:35:07 +00:00
rdbt 36eb98b6f6 Merge pull request #15815 from rdbtCVS/t3/fix-nightly-parity-regressions
Fix seven parity regressions blocking nightly builds
2026-11-12 23:53:35 +00:00
rdbtCVSandCodex GPT-6.1 a884525213 Align the head cache test with whole-payload texture rejection
Co-Authored-By: Codex GPT-6.1 <[email protected]>
2026-11-12 23:23:18 +00:00
rdbtCVSandCodex GPT-6.1 c35f0ba323 Clarify the authlib reference outside the game port ledger
Co-Authored-By: Codex GPT-6.1 <[email protected]>
2026-11-12 23:04:01 +00:00
rdbtCVSandCodex GPT-6.1 7e6b2db114 Merge main with the manual-proof parity fix
Co-Authored-By: Codex GPT-6.1 <[email protected]>
2026-11-12 22:55:36 +00:00
rdbtCVSandCodex GPT-6.1 768f0ddb83 Fix seven parity regressions blocking nightly builds
Restore vanilla void thresholds, HUD backdrops and profile texture validation; repair the block-event, AI-label, display-name and save-timer harness contracts.

Co-Authored-By: Codex GPT-6.1 <[email protected]>
2026-11-12 22:55:15 +00:00
rdbt 7c1a43138c Merge pull request #15570 from ilguerro/fix/parity-manual-proof-scripts
Leave the six hand-run proof scripts out of parity runs
2026-11-12 22:43:08 +00:00
rdbt 1a62ef7eb8 Merge pull request #15501 from rdbtCVS/t3/mob-turn-hooks-at-build
Mob islands: find mods that hook a mob's turn at build time
2026-11-12 19:45:27 +00:00
rdbtCVSandClaude Opus 5.5 fd448c5dc3 Mob islands: a mod hooking trample or a block contact keeps the mob tick serial
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 19:23:16 +00:00
rdbtCVSandClaude Opus 5.5 e0d0e34ba3 Mob islands: find mods that hook a mob's turn at build time
Replaces the opt-in native_mob_phase_quiet hook, which every existing mod
leaves unanswered, so any native mod kept the mob tick serial. The build
script now looks itself (horizon_mod_api_gen::mob_turn) and tells the
game through HORIZON_MOB_TURN:

- Mixins: the stage record names each injection's target. One into a
  hook a mob's turn calls, or into anything but a native_* hook point,
  keeps the loop serial.
- Trait mods: a staged trait package or its crates defining a function
  named for a hook the turn waits on keeps it serial. Jump and damage
  post are heard at the join, so overriding them doesn't.

A build without that finding but with trait mods stays serial, as before.
This also covers mixin-only bundles, which the opt-in hook never asked.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 19:23:16 +00:00
rdbt 4e459bf8e7 Merge pull request #15497 from rdbtCVS/t3/mob-island-bounded-reach
Mob islands: bounded reaches instead of serial fallbacks
2026-11-12 19:23:05 +00:00
rdbt 15f090e126 Merge pull request #15627 from senjinthedragon/cem-rot-radians
Custom entity models read rot_x, rot_y and player_rot_x/y in radians
2026-11-12 19:17:38 +00:00
rdbt f21b83c8b2 Merge pull request #15752 from rdbtCVS/fix/launcher-needless-bool
Launcher: fix Rust 1.100's needless_bool lint that fails main's launcher check
2026-11-12 19:16:28 +00:00
rdbt b929bea501 Merge pull request #15514 from yahya-nusseibeh/fix/launcher-safe-name-devices
Launcher: no Windows device names or disguising marks in downloaded file names
2026-11-12 19:12:32 +00:00
rdbtCVSandClaude Opus 5.5 ed2d455bf1 Launcher: Rust 1.100's needless_bool in is_link_or_junction
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 19:12:27 +00:00
rdbt 6dd6357962 Merge pull request #15555 from KBroneZ/claude/up-12038b
A sulfur cube's emptied body slot is not saved from its earlier NBT (#12038)
2026-11-12 19:11:27 +00:00
rdbt 6416121902 Merge pull request #15614 from Akirabane/fix/management-player-id-whole-uuid
Management protocol: a player id is a whole 8-4-4-4-12 UUID, as vanilla's PlayerDto reads it
2026-11-12 19:11:21 +00:00
rdbt eb8b298f9e Merge pull request #14195 from RLC248/fix/predicate-terms-holder-forms
A predicate's terms may be one holder alone or a tag (part of #12711)
2026-11-12 19:11:13 +00:00
rdbt c5127a8777 Merge pull request #15603 from Akirabane/fix/init-validates-config
horizon-server init: refuse a port or world name that server.toml would refuse
2026-11-12 19:10:06 +00:00
rdbt 911bbf054b Merge pull request #15605 from Akirabane/fix/backup-find-whole-label
horizon-server: restore and backups find a backup by its whole label
2026-11-12 19:10:01 +00:00
rdbt f646074830 Merge pull request #14712 from Skr1zzzz/falling-spawn-lookup
Client: spawning a falling block or TNT no longer walks the whole list
2026-11-12 19:09:56 +00:00
rdbt 5e3b0f03b6 Merge pull request #15599 from Akirabane/fix/idle-kick-not-during-end-credits
Dedicated server: no idle kick while the End poem is showing, as vanilla
2026-11-12 19:09:50 +00:00
rdbt bb64b215fe Merge pull request #15720 from angel2rider/fix/15494-glsl-feature
fix(shaders): compile the GLSL frontend independently
2026-11-12 19:08:36 +00:00
rdbt 779ea29839 Merge pull request #15670 from ilguerro/fix/stonecutter-scroll-reset
Stonecutter: the recipe list goes back to the top when its input changes
2026-11-12 19:08:32 +00:00
rdbt 74fd49ced0 Merge pull request #15596 from Akirabane/test/anticheat-e2e-log-off
anticheat_e2e: log = "" writes no flag log and the checks still act (log-off)
2026-11-12 19:07:21 +00:00
rdbt 8cf76b5ced Merge pull request #15669 from ilguerro/fix/fish-sounds-voice-sting
Fish play their sounds at their voice pitch, and silent fish play none
2026-11-12 19:06:03 +00:00
rdbt 53759e036a Merge pull request #15616 from Akirabane/fix/console-ban-already-banned
Dedicated console: /ban and /ban-ip of someone banned already change nothing, as vanilla
2026-11-12 19:05:57 +00:00
rdbt 950b9fed63 Merge pull request #15655 from TiggerTakkyTTT/fix/flint-steel-double-sound
Fix duplicate flint and steel sounds for guests
2026-11-12 19:05:47 +00:00
rdbtCVSandClaude Opus 5.5 01f8706d10 Mob islands: grouped turns reach no trample or block contact hook
A mob's turn calls native_trample (farmland) and the native_block_* contacts (a content mod's
blocks) from the movement code, on the group's own thread. Like the other hooks that hand a value
back, they are skipped in a grouped turn, and a quiet mod must not hook them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 19:00:49 +00:00
rdbtCVSandClaude Opus 5.5 ba4e4cf377 Mob islands: bounded reaches instead of serial fallbacks
The parallel mob tick (#14457) no longer falls back to serial for pets,
raids, changed speeds, teleporting meals, withers, wardens, the tick
profiler or quiet native mods. Each case gets a bounded reach or joins
the mobs involved into one island:

- Pets: the owner's teleport destination box is a second place of the
  pet's island, so it joins the mobs near its owner and none between.
- Raids: islands() already joins a raid's raiders; verify compares
  mobs without the process-wide hurt counter.
- Speed, jump and flying speed: a per-mob locomotion bound from the
  attributes and effects at their highest, derived in docs/mob-islands.md.
- Teleport consumables: half the item's TeleportRandomly diameter, and
  the body reaches down as far as the mob can fall.
- Wither and warden: the ids they keep are links.
- Native mods: a new opt-in hook, native_mob_phase_quiet; while every
  mod says it is quiet, grouped turns skip the hooks that hand a value
  back and replay living_jump and damage_post at the join, in order.
- Tick profiler: each island thread samples into its own sums, merged
  at the join.

native_hooks.rs may not grow, so mod_sound_ok, mod_particles_ok and
sound_id move unchanged to native_level_effects.rs, their main user.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 19:00:49 +00:00
rdbt c442809fa7 Merge pull request #13970 from horizon-rust/fix/sprite-mcmeta-trailing-text
Read a sprite's .mcmeta up to its first value, as vanilla does
2026-11-12 18:55:59 +00:00
JoansitohandClaude Sonnet 5.5 7528ca15ff Anticheat prediction: a history gap rebases the replay instead of dropping it
When the record no longer kept the ticks or changes the replay hadn't
played (a server that stalled for seconds), or a tick couldn't be played,
guest_replay dropped the replay and the check stayed off until the player's
next teleport. It now starts again from the server's own position for the
guest, excused until the moves agree with the client's again (at most 40
ticks), so the check resumes.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 19:49:41 +01:00
rdbtCVSandClaude Sonnet 5.5 af682746e0 Merge main into branch
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 18:40:53 +00:00
rdbtCVSandClaude Sonnet 5.5 f34daa1a75 Merge main into branch
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 18:40:53 +00:00
rdbtCVSandClaude Sonnet 5.5 130d3ce7b6 Merge main into branch
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 18:40:53 +00:00
rdbt 4acdda54f2 Merge pull request #15690 from Akirabane/fix/console-runs-as-server-source
The dedicated console and RCON run as the server's own source, named Server or Rcon, as vanilla's do
2026-11-12 18:40:47 +00:00
rdbt a1c4de50b1 Merge pull request #15607 from Akirabane/fix/management-permission-level-clamp
Management protocol: a permission level is clamped as vanilla's codec reads it
2026-11-12 18:40:41 +00:00
rdbt 3b48fdf7c4 Merge branch 'main' into claude/up-12038b 2026-11-12 18:38:52 +00:00
rdbt 02b94e5b12 Merge branch 'main' into falling-spawn-lookup 2026-11-12 18:38:48 +00:00
rdbt 51a4fe79e6 Merge branch 'main' into fix/fish-sounds-voice-sting 2026-11-12 18:38:44 +00:00
rdbt cd0f850c12 Merge branch 'main' into fix/idle-kick-not-during-end-credits 2026-11-12 18:38:41 +00:00
rdbt 97fc687ceb Merge branch 'main' into fix/console-ban-already-banned 2026-11-12 18:38:38 +00:00
rdbt f7fce57158 Merge branch 'main' into fix/15494-glsl-feature 2026-11-12 18:38:35 +00:00
rdbt fb50a7ad88 Merge branch 'main' into fix/stonecutter-scroll-reset 2026-11-12 18:38:33 +00:00
rdbt db82ec5ba0 Merge branch 'main' into cem-rot-radians 2026-11-12 18:38:30 +00:00
rdbt 0f93711e13 Merge branch 'main' into fix/management-player-id-whole-uuid 2026-11-12 18:38:27 +00:00
rdbt 2524bc9ea2 Merge branch 'main' into fix/sprite-mcmeta-trailing-text 2026-11-12 18:38:24 +00:00
rdbt fcfa91e598 Merge branch 'main' into fix/predicate-terms-holder-forms 2026-11-12 18:38:17 +00:00
rdbt deb3b4fec3 Merge branch 'main' into fix/flint-steel-double-sound 2026-11-12 18:38:15 +00:00
rdbt 3fd1593ca6 Merge branch 'main' into fix/launcher-safe-name-devices 2026-11-12 18:38:09 +00:00
rdbt db7c87c6b5 Merge branch 'main' into fix/websocket-control-frames 2026-11-12 18:38:06 +00:00
rdbt 95d99935ea Merge pull request #15745 from rdbtCVS/fix/studio-needless-bool
CI: fix two Rust 1.100 lints that fail main's verify
2026-11-12 18:37:35 +00:00
rdbtCVSandClaude Opus 5.5 31fc9ce21d CI: two Rust 1.100 lints on main (needless_bool in studio.rs, unreachable_code without audio)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 18:35:26 +00:00
rdbt 72f92a5ef7 Merge pull request #15594 from Akirabane/test/anticheat-timer-tick-rates
Anticheat timer: test the balance at tick rates other than 20
2026-11-12 18:35:11 +00:00
rdbt 914d5e664d Merge pull request #15644 from Akirabane/fix/server-perf-block-s-linux-only
server_perf: build block_s only on Linux, where its only users are
2026-11-12 18:31:55 +00:00
rdbt 23b4c9c411 Merge pull request #15671 from Akirabane/fix/relay-host-ping-schedule
relay: a host is pinged every 20 s whatever joins arrive, so join traffic cannot end a live host
2026-11-12 18:23:58 +00:00
rdbt 95e346c9ad Merge pull request #15586 from Akirabane/test/anticheat-e2e-combat-restart
anticheat_e2e: a player's kicks are kept across a restart (combat-restart)
2026-11-12 18:23:43 +00:00
rdbt 6f478a6cad Merge pull request #13981 from horizon-rust/fix/feed-particles-tadpole-panda-dolphin
Feeding shows its particles: tadpole slime ball, panda love hearts, dolphin treasure
2026-11-12 18:22:36 +00:00
rdbt 737f81c32d Merge pull request #15656 from Akirabane/fix/ban-date-format-as-simpledateformat
Ban and user cache dates are read as vanilla's SimpleDateFormat reads them
2026-11-12 18:22:28 +00:00
rdbt 408c08e029 Merge pull request #15646 from Akirabane/fix/play-cookie-response-disconnects
LAN and dedicated: a cookie response in play disconnects the player, as vanilla
2026-11-12 18:22:22 +00:00
rdbt 44c7007125 Merge pull request #15601 from Akirabane/fix/stopped-op-permission-level
horizon-server: a stopped op and init --op use op-permission-level, as vanilla's op does
2026-11-12 18:22:13 +00:00
rdbt 551cb3a741 Merge pull request #15592 from Akirabane/fix/pause-when-empty-sprint
Dedicated server: a /tick sprint does not count toward pause-when-empty, as vanilla counts it
2026-11-12 18:22:08 +00:00
rdbt 683603fe21 Merge pull request #15564 from Akirabane/fix/login-unexpected-query-answer
LAN and dedicated login: a query answer or cookie response nobody asked for is refused, as vanilla refuses it
2026-11-12 18:22:02 +00:00
rdbt 5b29177859 Merge pull request #15512 from yahya-nusseibeh/fix/query-challenge-cap
Query: cap the challenges held between prunes
2026-11-12 18:21:55 +00:00
rdbt 3d6224deb4 Merge pull request #15503 from Mayonesu0/up-harness-windows
wire_stream harness runs on Windows: natives, console encoding, .exe
2026-11-12 18:21:49 +00:00
rdbt d1613f705f Merge pull request #15674 from Akirabane/fix/negative-block-sequence-dropped
LAN and dedicated: a block use with a negative sequence is dropped, as vanilla's throw drops it
2026-11-12 18:21:41 +00:00
rdbt e78022f152 Merge pull request #15664 from Akirabane/fix/backup-hand-name-not-auto
horizon-server: a backup made by hand cannot take the name auto, which prune deletes
2026-11-12 18:21:36 +00:00
rdbt 5c4cdb41f6 Merge pull request #15580 from Akirabane/test/anticheat-e2e-off-acting-checks
anticheat_e2e: off also covers the checks that act by default
2026-11-12 18:21:27 +00:00
rdbt 3cac36d0f1 Merge pull request #15577 from Akirabane/fix/anticheat-timer-settings-check
Anticheat: refuse a negative or non-finite timer tolerance_ms or max_lag_ms
2026-11-12 18:21:22 +00:00
rdbt 50d2c4f3e8 Merge pull request #15666 from ilguerro/fix/grindstone-damage-component
Refuse grindstone and anvil inputs without a damage component
2026-11-12 18:14:31 +00:00
rdbt 5e89bcee59 Merge pull request #15661 from ilguerro/fix/happy-ghast-cloud-heal
heal a happy ghast in the clouds every second
2026-11-12 18:14:27 +00:00
rdbt 97aa3cf252 Merge pull request #15590 from TiggerTakkyTTT/fix/flat-light-view
Stop flat and debug worlds retrying light views
2026-11-12 18:14:21 +00:00
rdbt 0ae3420fd5 Merge pull request #15509 from yahya-nusseibeh/fix/panel-login-lockout
Panel: wrong login codes no longer lock out the right one
2026-11-12 18:14:15 +00:00
rdbt 20b1949dbd Merge pull request #15498 from Mayonesu0/up-14807-wire-stream-dig-teleport
wire stream: a teleport's answer ticks keep the position reminder on the script's clock
2026-11-12 18:14:10 +00:00
rdbt 5db98af340 Merge pull request #14387 from martipops/agent/pack-options-shell
Pack Options on the settings shell
2026-11-12 18:14:05 +00:00
rdbt 00b3fa3db7 Merge pull request #14168 from MSedgeMC/fix/block-entity-pos-from-tag
A block entity saved in another chunk moves into the chunk that holds it
2026-11-12 18:14:00 +00:00
rdbt 9b2f425f42 Merge pull request #15618 from Bl4ckspell7/refactor/gfx-in-flight-module
Renderer: frames in flight move out of gfx.rs into gfx/in_flight.rs
2026-11-12 18:13:54 +00:00
rdbt a0a2a53279 Merge pull request #15510 from yahya-nusseibeh/fix/prune-spawn-radius-bound
Prune: a spawn radius past i32 keeps everything instead of nothing
2026-11-12 18:13:49 +00:00
rdbt 13d6ba09ad Merge pull request #15460 from Mayonesu0/up-relbinary-save-reload
entity_save_reload: resolve a relative --binary against the caller's directory
2026-11-12 18:13:45 +00:00
rdbt 1352566ab3 Merge pull request #15452 from Ragbie/tests/world-test-lifecycle-forced-chunk
world_test_def_lifecycle reads a chunk only /forceload holds, and runs automatically again
2026-11-12 18:13:40 +00:00
rdbt ca80643fda Merge pull request #14837 from Xmilon/xmilon/dim-sea
Sea level follows the level's generator
2026-11-12 18:13:36 +00:00
rdbt e9faef471e Merge pull request #14595 from martipops/fix/horizon-preset-name
Graphics: Horizon's own preset row is named Horizon Preset
2026-11-12 18:13:30 +00:00
rdbt 7beafea5e1 Merge pull request #15589 from Akirabane/docs/anticheat-three-sentences
docs/anticheat.md: three sentences that disagreed with the code
2026-11-12 18:13:24 +00:00
rdbt 9e840cecfd Merge pull request #15525 from Mayonesu0/up-15484-pufferfish-contact
Sync randoms before each pufferfish mob contact case
2026-11-12 18:13:18 +00:00
rdbt 78f6ac5536 Merge pull request #14930 from Detimes/perf-effect-meta
Perf: memoise the effect particle lookup in the hub
2026-11-12 17:58:06 +00:00
rdbt 5ca5e36230 Merge pull request #14780 from malithedeveloper/fix/atlas-single-sprite-renames
Resource packs: a renamed atlas sprite reads its resource's texture
2026-11-12 17:58:02 +00:00
rdbt 3e5a89b088 Merge pull request #14580 from DUzzL/fix/14454-minecart-shulker
Let rideable minecarts pick up shulkers beside the rail
2026-11-12 17:57:58 +00:00
rdbt 0609305694 Merge pull request #15511 from yahya-nusseibeh/fix/service-unit-paths
Service: refuse paths a systemd unit would misread
2026-11-12 17:57:53 +00:00
rdbt b723023664 Merge pull request #15445 from AlfaRojo/parity/allay-pickup-cooldown-back
allay_pickup_cooldown back in parity runs; the allay healing test reads the pickup cooldown where it lives
2026-11-12 17:57:47 +00:00
rdbt a5f6b3ba0e Merge pull request #14973 from vermingov/fix/goat-horn-byte-14970
A goat's horn flags are read as bytes (#14970)
2026-11-12 17:57:43 +00:00
rdbt 66129b4902 Merge pull request #14590 from DUzzL/fix/14370-fixture-neighbourhood
Load the 5x5 neighbourhood in prepared-data test fixtures
2026-11-12 17:57:38 +00:00
rdbt ac2603ed41 Merge pull request #15529 from rdbtCVS/t3/explosion-detonate-entities
Native mods: native_explosion_entities spares entities from a blast
2026-11-12 17:51:00 +00:00
rdbt 58d42c41ed Merge branch 'main' into fix/feed-particles-tadpole-panda-dolphin 2026-11-12 17:49:13 +00:00
rdbtandCodex gpt-6.1-sol dffce9c48d Merge pull request #15635 from kacpherek/fix/vanilla-baby-piglin-keeps-ingot
Merge #15635 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:47:04 +00:00
rdbtandCodex gpt-6.1-sol 42e897cc73 Merge pull request #15632 from kacpherek/fix/vanilla-enchant-stack
Merge #15632 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:59 +00:00
rdbtandCodex gpt-6.1-sol ebd4205ea6 Merge pull request #15628 from kacpherek/fix/vanilla-gaze-disguise
Merge #15628 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:55 +00:00
rdbtandCodex gpt-6.1-sol 14859c67b7 Merge pull request #15499 from kacpherek/fix/7922-tessellation-fallback
Merge #15499 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:50 +00:00
rdbtandCodex gpt-6.1-sol 542c7c239e Merge pull request #15344 from Web-mc1/fix/item-count-max-stack
Merge #15344 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:45 +00:00
rdbtandCodex gpt-6.1-sol 93d98006a8 Merge pull request #14961 from SamB440/fix/player-rotation-packet-parity
Merge #14961 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:41 +00:00
rdbtandCodex gpt-6.1-sol 12b96b27c3 Merge pull request #14899 from NikitaMGrimm/shader-api-entity-stage
Merge #14899 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:35 +00:00
rdbtandCodex gpt-6.1-sol 5b912979d4 Merge pull request #14758 from ilguerro/perf/worldgen-noise-masks
Merge #14758 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:30 +00:00
rdbtandCodex gpt-6.1-sol e518cb868d Merge pull request #14687 from Mayonesu0/up-14641-stack-components
Merge #14687 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:25 +00:00
rdbtandCodex gpt-6.1-sol 3c1027d1e1 Merge pull request #14684 from vnsmoreira/fix/end-crystal-saved-fall
Merge #14684 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:20 +00:00
rdbtandCodex gpt-6.1-sol ae8e375feb Merge pull request #14578 from ilguerro/fix/jukebox-song-reload
Merge #14578 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:15 +00:00
rdbtandCodex gpt-6.1-sol 7e8805bb61 Merge pull request #14558 from voidsipp/split/11535-pending-entity-provenance-20261109
Merge #14558 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:11 +00:00
rdbtandCodex gpt-6.1-sol fb089da76c Merge pull request #14459 from ilguerro/fix/wither-star-lifetime
Merge #14459 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:06 +00:00
rdbtandCodex gpt-6.1-sol d162b9f5e5 Merge pull request #14349 from Akirabane/feat/7255-particle-frustum
Merge #14349 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:46:02 +00:00
rdbtandCodex gpt-6.1-sol 748c6ba3d5 Merge pull request #14150 from RLC248/fix/thrown-potion-level-entity
Merge #14150 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:57 +00:00
rdbtandCodex gpt-6.1-sol 3665978732 Merge pull request #14149 from horizon-rust/layers/extras-tweaks
Merge #14149 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:52 +00:00
rdbtandCodex gpt-6.1-sol 5364cb4ebc Merge pull request #14839 from DUzzL/fix/14804-frame-motion
Merge #14839 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:45 +00:00
rdbt 855e215c43 Merge branch 'main' into fix/sprite-mcmeta-trailing-text 2026-11-12 17:45:43 +00:00
rdbtandCodex gpt-6.1-sol 7c8f5e38a6 Merge pull request #14663 from vnsmoreira/fix/painting-on-ground
Merge #14663 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:39 +00:00
rdbtandCodex gpt-6.1-sol 108bf1dd93 Merge pull request #14258 from vnsmoreira/fix/raw-entity-flags
Merge #14258 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:33 +00:00
rdbtandCodex gpt-6.1-sol 3fc31df485 Merge pull request #11261 from Ragbie/fix/hanging-item-stack-config
Merge #11261 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:45:28 +00:00
rdbtandCodex gpt-6.1-sol 633d28079b Merge pull request #14852 from vermingov/fix/evoker-fangs-fall-distance-14847
Merge #14852 after current verify, review, and discussion checks.

Co-Authored-By: Codex gpt-6.1-sol <[email protected]>
2026-11-12 17:44:41 +00:00
rdbt e5efe9dc8d Merge pull request #14301 from Ragbie/tools/fall-clip-wait-neighbourhood
vehicle/mob fall clip wait for the forced chunk's 2-column neighbourhood
2026-11-12 17:44:03 +00:00
rdbtCVSandClaude Opus 5.5 2b8ce785e1 Explosions: list the entities for mods only while native mods are loaded
The spared ids are a set, so a blast over many entities stays linear.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 17:27:10 +00:00
rdbt d52edf0341 Merge pull request #15489 from kacpherek/fix/stack-dump-test-race
Fix the stack dump test that fails one verify run in three
2026-11-12 17:22:19 +00:00
Kacper 9925dccf60 Merge branch 'main' into fix/crafter-triggered-int 2026-11-12 18:18:15 +01:00
Kacper 852dcc5416 Merge pull request #14476 from vnsmoreira/fix/vex-no-gravity
A vex turns its gravity off every tick
2026-11-12 18:18:06 +01:00
Kacper 62d8085479 Merge branch 'main' into fix/vex-no-gravity 2026-11-12 17:56:51 +01:00
angel2riderandGPT 6.1 Sol 72627408bc fix(shaders): compile the GLSL frontend independently
Fixes #15494.

Co-Authored-By: GPT 6.1 Sol <[email protected]>
2026-11-12 16:42:31 +00:00
Kacpherek a660afd3a1 Add a Full Performance graphics preset and make every preset a fixed table
Full Performance sits before Performance: the lowest settings, far terrain off,
opaque ice and a 75% resolution scale. Every preset is now a fixed table, so
picking one after another leaves nothing of the first behind, and every one of
them turns on the optimizations that leave the picture as it is: asynchronous
entity and particle culling, the block-entity caches and GPU Culling's Auto.
2026-11-12 16:35:00 +01:00
Nikita Maximilian GrimmandClaude Fable 5.2 9de182a265 docs: say what counts towards the 500-line pull request size
Fixes #15692.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-12 16:00:19 +01:00
AkirabaneandClaude Opus 5.5 91c0bf1f42 Dedicated console and RCON: commands run as the server's source, as vanilla
The console ran each command with no source, so it ran as the player in
place: `/me waves` said "* Player waves", `teammsg` looked for that player's
team, and relative coordinates (`~ ~ ~`) were that player's position. Vanilla's
console source (MinecraftServer.createCommandSourceStack) has no entity, is
at the world spawn's lower corner and is named "Server"; an RCON client's
(RconConsoleSource) is named "Rcon". as_console_in_overworld now runs the line
with the server's source (feedback heard, as command_harness's console does),
and say, me and the operators' line name it "Server" or "Rcon".

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 15:32:55 +01:00
AkirabaneandClaude Sonnet 5.5 c26187a6f0 A use packet with a negative block sequence is dropped before the hub, as in vanilla
ServerGamePacketListenerImpl.handleUseItemOn and handleUseItem call
ackBlockChangesUpTo(sequence) right after the client-loaded check, and it
throws IllegalArgumentException("Expected packet sequence nr >= 0") for a
negative number. The packet processor catches it and only logs "Failed to
handle packet ..., suppressing error": nothing else in the handler runs, the
idle timer is not reset and the player stays. Horizon passed such a packet to
the hub and the game, which used the item or the block. PlayConn::packet now
drops a UseItem or UseItemOn whose sequence is negative.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 14:46:02 +01:00
TiggerTakkyTTTandCodex 5a135748c8 Fix duplicate flint and steel sounds for guests
Co-Authored-By: Codex <[email protected]>
2026-11-12 20:39:38 +07:00
AkirabaneandClaude Sonnet 5.5 5208a5385b Relay: guest joins no longer hold back a host's pings
The relay pinged a host only after ping_every of quiet: every join line it
sent to the host restarted that wait. The host speaks on its control
connection only to answer a ping, so joins arriving less than ping_every
apart for host_timeout left it silent and the relay dropped a host that was
alive, retiring its code (later guests got `ended`). A ping now goes out
every ping_every whatever else is sent meanwhile.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 14:39:32 +01:00
AkirabaneandClaude Sonnet 5.5 d3c30ae2b0 Server: a hand backup cannot take the automatic backups' name
`horizon-server backup auto` wrote `<time>-auto.zip`, byte for byte the name
of an automatic backup, so the next automatic backup's prune deleted it once
it was beyond `keep`, although backups made by hand are never deleted. `auto`
is now refused as a name for a hand backup, with a message saying why; the
automatic backups are named by auto_name, which no longer goes through that
check.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 14:31:33 +01:00
AkirabaneandClaude Opus 5.5 eb44631ea7 Server files: read a ban or cache date's zone as SimpleDateFormat does
BanListEntry and CachedUserNameToIdResolver parse their dates with
SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z", Locale.ROOT). Its zone field
takes +hhmm with hours to 23 and minutes to 59, GMT alone or
GMT+h:mm / GMT-hh:mm, and UTC, in any case, and leaves what follows
unread. parse_date took any four digits after a sign and nothing else,
so "+2400" was a date and "... UTC" was not: an expiry written with UTC
or GMT became a permanent ban.

zone_offset reads the zone that way; the test's values are those
vanilla's own format gave.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 14:30:24 +01:00
Kacpherek eadd0a9b5e Wear a glider held in a hand like a worn one
LivingEntity.updateFallFlying picks at random among every slot (mainhand,
offhand, feet, legs, chest, head) whose stack can glide, not just armor.
2026-11-12 13:57:06 +01:00
Kacpherek a022ef2e01 End an item use through stopUsingItem on shield disable, swap, slot, spectator and portal
Vanilla BlocksAttacks.disable, handlePlayerAction SWAP_ITEM_WITH_OFFHAND,
handleSetCarriedItem (main hand use), ServerPlayer.setGameMode (spectator)
and ServerPlayer.teleport (another dimension) call stopUsingItem, which
posts the item_interact_finish vibration. These paths only cleared the use.
2026-11-12 13:45:46 +01:00
Kacpherek c0def62a4e Stop an item use when the hand holds another item
Vanilla LivingEntity.updatingUsingItem calls stopUsingItem when the
hand's item is no longer the item the use began with, and
releaseUsingItem runs releaseUsing only for the same item (then
stopUsingItem). Remember the starting stack and do the same for the
host's and the guests' uses.
2026-11-12 13:45:46 +01:00
Kacpherek 7c4be249c2 Tick the compasses mobs hold or wear
LivingEntity.aiStep ticks EntityEquipment, which calls
CompassItem.inventoryTick on each equipment stack: a tracker whose
lodestone is gone loses its target. Only the player and armor stands did
this; a mob keeps a compass pointing at a broken lodestone.
2026-11-12 13:45:05 +01:00
Kacpherek 53209c8800 Keep a hit baby piglin's admired gold ingot
PiglinAi.stopHoldingOffHandItem deletes the off-hand gold ingot (without
bartering) only for an adult. A baby tries to equip it, then holds it in
its main hand. stop_admiring dropped it for any age.
2026-11-12 13:43:50 +01:00
Kacpherek 5700ead75f Enchant loot and trade stacks by their own enchantable component
EnchantmentHelper.enchantItem asks the stack for DataComponents.ENCHANTABLE, so
a stack that changed or removed it is not enchanted as the plain item.
2026-11-12 13:43:37 +01:00
Kacpherek e3b03d4adc Read the gaze disguise from the item tag
LivingEntity.PLAYER_NOT_WEARING_DISGUISE_ITEM checks the helmet against
#gaze_disguise_equipment, which Enderman.isBeingStaredBy and the creaking
both use, not the carved pumpkin by name.
2026-11-12 13:43:29 +01:00
Kacpherek 417e700f73 Play the block fall sound after a player's damaging fall
LivingEntity.causeFallDamage calls playBlockFallSound after the fall
sound: the block at floor(y - 0.2F) plays its fall sound at half volume
and three quarters pitch, unless it is air. The event was queued but no
one played it. Carry the block state and play it where the small and big
fall sounds already play: every other player on the server, and the
landing player's own client.
2026-11-12 13:43:24 +01:00
Kacpherek 8801c809a6 Pick Mending repair slots by the repair_with_xp effect
ExperienceOrb.repairPlayerItems takes EnchantmentHelper.getRandomItemWith
(REPAIR_WITH_XP, ...): one entry per enchantment that has that effect and
applies in the slot, not any item with the minecraft:mending id. A data
pack enchantment with the effect now repairs too.
2026-11-12 13:43:09 +01:00
Kacpherek 779cb6ce5e Decide an item's explosion resistance from its damage_resistant
ItemStack.canBeHurtBy reads the stack's damage_resistant component. The nether
star's #is_explosion came from a hard-coded item name, so other stacks with
the component (or a stack that removed it) were handled wrongly.
2026-11-12 13:43:03 +01:00
Kacpherek 720cee852f Hurt dropped items struck by lightning instead of deleting them
Entity.thunderHit calls ItemEntity.hurtServer for 5: the item loses health,
is destroyed at zero (onDestroyed spills contents), and is spared when its
damage_resistant covers lightning_bolt (ItemStack.canBeHurtBy). Share the
stack-aware resistance check the damage command already used.
2026-11-12 13:42:56 +01:00
SenjinandClaude Opus 5.5 387fc29cb8 Custom entity models read rot_x, rot_y and player_rot_x/y in radians
EMF gives them in radians, the entity ones lerped within the tick
(EMFMath.getEntityRX/RY, getPlayerRX/RY). Degrees made a pack's
turn-in-place counter-rotation spin mobs round several times.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 13:42:46 +01:00
Kacpherek 49a1fcfec0 Predict a guest's leather boots on powder snow
The server copy of a guest's body never learned about leather boots, so its
movement check made a guest wearing them sink in powder snow
(PowderSnowBlock.canEntityWalkOnPowderSnow). Set the flag each tick like
the freeze-immune one.
2026-11-12 13:42:02 +01:00
Kacpherek f7cccbd700 Give every mob powder snow's contextual collision
PowderSnowBlock.getCollisionShape asks any entity for its fall distance,
the powder_snow_walkable_mobs tag and leather boots on its feet. Mob moves
passed that only for striders, so foxes, rabbits, endermites, silverfish
and mobs in leather boots sank in powder snow.
2026-11-12 13:41:24 +01:00
Kacpherek e4f3225d7f Complete a bundle's use on its 200th tick
Vanilla LivingEntity.updateUsingItem calls completeUsingItem when the
remaining ticks reach 0 (BundleItem.getUseDuration is 200, no
useOnRelease), so the use sends entity event 9, runs the finish hook and
ends with stopUsingItem's interact vibration. The bundle only cleared the
use.
2026-11-12 13:40:53 +01:00
Bl4ckspellandClaude Opus 5.5 16448c5ff1 refactor(gfx): move frames in flight into gfx/in_flight.rs
gfx.rs is over the 3000-line limit and may not grow, and the 4x terrain MSAA (#15479) adds to it. The impl block from after_submit to take_readback moves unchanged; the five private methods gfx.rs still calls become pub(super).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 13:10:16 +01:00
AkirabaneandClaude Sonnet 5.5 38f23d16e4 A cookie response in the play state disconnects the player, as vanilla does
ServerCommonPacketListenerImpl.handleCookieResponse disconnects with
multiplayer.disconnect.unexpected_query_response, and the vanilla server asks
for no cookie, so every response is unexpected. Horizon decoded the packet and
let the game drop it. PlayConn::packet now answers it with that disconnect, for
the singleplayer owner too (a keep-alive has an owner exemption, this has none).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 13:01:32 +01:00
AkirabaneandClaude Opus 5.5 5b4d583209 Management protocol: a PlayerDto id of 32 undashed digits is refused, as vanilla's codec does
PlayerDto reads its id with UUIDUtil.STRING_CODEC (UUID.fromString):
vanilla answers "Invalid UUID string" for
0123456789abcdef0123456789abcdef (UUIDUtil.LENIENT_CODEC, an int array
or that same string codec, refuses it too). Horizon's parse_uuid also
took the 32 undashed digits; now only the 8-4-4-4-12 form parses.

The test's 32-digit case moves to the refused ones. UUID.fromString's
other forms (five shorter dashed groups, a sign) stay refused here; that
is not in this change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:55:40 +01:00
AkirabaneandClaude Sonnet 5.5 ebf8069c57 server_perf: build block_s only on Linux, where its only users are
block_s (the sampler's seconds per time block) is called only from the Linux
sampler, `mod linux` of server_perf/samples.rs, which is built for
target_os = "linux". On every other platform clippy with warnings denied
stopped on `function block_s is never used`. It now carries the same cfg as
its users, so Linux builds exactly what it built before.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 12:53:07 +01:00
AkirabaneandClaude Opus 5.5 1751960d36 Dedicated console: /ban and /ban-ip of someone banned already change nothing
BanPlayerCommands.banPlayers skips a player who isBanned, and
BanIpCommands.banIp refuses an address that is, so a second ban keeps the
first one and answers "Nothing changed". The console's own /ban and /ban-ip
relied on UserList::add, which replaces an entry whose reason differs: a
second ban with another reason replaced the first and said "Banned". They now
check isBanned first (Lists::ban and Lists::ban_ip), as the game's /ban does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:42:10 +01:00
AkirabaneandClaude Opus 5.5 35e7459102 Management protocol: a permission level is clamped as vanilla's codec reads it
An OperatorDto's permissionLevel and the value of
serversettings/operator_user_permission_level/set are decoded by
PermissionLevel.INT_CODEC: Codec.INT, then PermissionLevel.byId, whose
ByIdMap clamps. So 5 is 4, -1 is 0 and 2.7 is 2; only a non-number is
refused. Horizon answered invalid params for operators/add|set and an
error for the setter.

permission_level() reads it that way for both; the old test that
expected 5 to be refused now expects 4.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:41:14 +01:00
AkirabaneandClaude Sonnet 5.5 b942e89cd6 Server: restore and backups find a backup by its whole label
`restore NAME` takes "the name given to `backup` (the newest with it)", but
find matched any file name that ends with `-NAME.zip`, so `restore test`
took a newer `<stamp>-my-test.zip` over the `<stamp>-test.zip` it named, and
`restore auto` or `restore update` could take a hand-made `nightly-auto` or
a `before-update` backup. The label is the whole text between the time
stamp and `.zip`.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 12:28:59 +01:00
AkirabaneandClaude Sonnet 5.5 f117ec604a Server: init refuses a port or world name that server.toml would refuse
horizon-server init took its port and world name from a flag or answer and
wrote server.toml without checking them, so `--port 0` or `--world a/b`
gave "Wrote server.toml" and then every run failed to load it (Config::check
refuses port 0 and a world name with a slash, `..`, backups, logs or
.horizon). init now runs Config::check on what it will write, right after
the port is set and before anything else is written, and stops with that
message.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 12:23:22 +01:00
AkirabaneandClaude Sonnet 5.5 34dcda27f0 Server: a stopped op and init --op use op-permission-level
PlayerList.op writes ServerOpListEntry(MinecraftServer.operatorUserPermissions()),
and DedicatedServer.operatorUserPermissions() is the op-permission-level
property. horizon-server's stopped `op` and `init --op` wrote level 4 whatever
the property said; they now write its level (0 to 4, 4 when unset), read as
the game reads it at its next start: server.properties with server.toml's
keys written over it.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 12:19:35 +01:00
AkirabaneandClaude Opus 5.5 ee8b7b891a Dedicated server: no idle kick while the End poem is showing
ServerGamePacketListenerImpl.tick kicks an idle player only when
!player.wonGame: a client showing the credits sends no action until it
asks to respawn. Horizon's kick_idle kicked such a player once
player-idle-timeout passed.

The decision moves into idles_out, which also takes the guest's
won_game, so it is tested without a running server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:19:16 +01:00
9a314a0b5a Fish play their sounds at their voice pitch, and silent fish play none
`Pufferfish.tick` and `AbstractFish.aiStep` go through
`LivingEntity.makeSound`, which plays `Entity.playSound(sound,
getSoundVolume(), getVoicePitch())`: two random draws for the pitch, at the
entity's feet, and nothing when the entity is silent. The raw `Mob::sound`
helper played at eye height, at pitch 1.0, and ignored `Silent`, so a
`{Silent:1b}` pufferfish still blew up and out and a flop never varied.

`Pufferfish.playerTouch` sends `ClientboundGameEventPacket.PUFFER_FISH_STING`
only inside the `hurtServer` branch and only when the fish is not silent; the
sting for the player now comes from there, as a game event for a guest and as
the local play for the host, instead of the fish's AI tick playing it every
tenth tick whether or not any damage landed.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:09:41 +01:00
TiggerTakkyTTTandCodex 68ac8880d3 Fix light views for flat and debug worlds
Flat and debug generator protos already contain their decorated columns, so expose a copy for lighting neighbours outside the kept area. This prevents the chunk pump from retrying impossible light-view jobs indefinitely.

Co-Authored-By: Codex <[email protected]>
2026-11-12 18:03:39 +07:00
AkirabaneandClaude Opus 5.5 717b8d192f anticheat_e2e: log = "" writes no flag log and the checks still act (log-off)
docs/anticheat.md says an empty `log` writes no file, and no e2e case set
it. The new log-off case runs a survival server with `[anticheat] log = ""`
and a bot attacking without swinging: it is still kicked, the console still
has the [Anticheat] warning of the kick, and logs/anticheat.log is never
written.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 12:02:36 +01:00
AkirabaneandClaude Opus 5.5 7cd92e310d Dedicated server: a /tick sprint does not count toward pause-when-empty
MinecraftServer.tickServer counts a tick as empty only with no player
and no sprint running (ServerTickRateManager.isSprinting), and sets the
count back to 0 otherwise. Horizon counted sprinting ticks, so a sprint
on an empty server reached the pause almost at once and then stayed
stuck: the paused tick does not advance it.

The count moves into count_empty_tick, which also takes the sprint, so
the decision is tested without a running server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:56:24 +01:00
AkirabaneandClaude Opus 5.5 541ef4e5fa Anticheat timer: test the balance at tick rates other than 20
Every timer test ran at 20 ticks a second, although Balance::tick_end takes
1000 / rate ms per client tick and the hub passes the server's rate. The new
test runs a client on time at /tick rate 10 and 60 for ten minutes (never
flagged), 1.5 times as fast (flagged again and again), and 20 ticks a second
on a server at 10 (flagged).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:56:23 +01:00
AkirabaneandClaude Opus 5.5 baa43ddf05 docs/anticheat.md: three sentences that disagreed with the code
- A wrong [anticheat] section makes horizon-server start and run refuse to
  start (the error names the key); it is the game, reading server.toml
  itself, that turns the anticheat off with an error.
- ground bans by default too (ban_after = 2), not only combat.
- A kick or a ban always reaches the console; the log line needs a log file
  (log = "" writes none) and the operators' line needs alerts = true.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:54:45 +01:00
AkirabaneandClaude Opus 5.5 337b8a751c anticheat_e2e: a player's kicks are kept across a restart (combat-restart)
docs/anticheat.md says a check's kicks are counted across sessions and
restarts, but check_combat bans on a second session of the same running
server. The new combat-restart case kicks a no-swing bot once, checks that
anticheat-strikes.json holds one combat strike, stops the server and starts
it again on the same folder, and expects the same bot, cheating again, to be
banned with the count back at 0. start() reuses a folder that is already
there.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:44:37 +01:00
AkirabaneandClaude Opus 5.5 f31921a9a3 Anticheat: refuse a negative or non-finite timer tolerance_ms or max_lag_ms
Config::check refused negative thresholds and a prediction tolerance of 0 or
less, but let any [anticheat.timer] tolerance_ms and max_lag_ms through. A
negative tolerance_ms flags a client on time every tick; a max_lag_ms below
-tolerance_ms does too, as the balance rests at the cap; NaN never flags, or
never caps the balance. Both are now numbers of milliseconds from 0 up,
checked by horizon-server before a start and by the game when it reads
server.toml.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:22:56 +01:00
AkirabaneandClaude Opus 5.5 1aa472967f anticheat_e2e: off also covers the checks that act by default
check_off ran only the timer check's 1.5x bot, so nothing showed that
`enabled = false` silences combat and ground, the two checks that drop, kick
and ban by default. It now also runs, on a survival server with allow-flight on
(vanilla's floating kick would end the no-fall bot on its own), the no-swing,
two-target and no-fall bots of check_combat and check_ground: none is flagged,
kicked or banned, no anticheat log is written, and their hits land.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 11:15:04 +01:00
Riccardo GuerrieroandClaude Opus 5.5 cc1fea2714 Leave the six hand-run proof scripts out of parity runs
tools/parity.py runs every tools/test_*_parity.py with no arguments. Six of
them are two-step proofs that need arguments (a Java side, then a native
side against its reference): builtin_component_delivery,
entity_movement_predicate, guest_close_event, machine_recipe_placement,
predicate_reference_startup and self_pose_metadata. Run bare, each exits
in 0 s with a usage error, so every parity-main run since they landed
(11-07 to 11-09) has failed on them, and the Nightly waits for a green
parity-main.

A script can now declare PARITY_MANUAL = "<how to run it>": parity.py
leaves it out of every run (--changed and parity-main included) and,
asked for it by name, says how to run it. The six declare it; nothing
else about them changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Fekd42tRMKJk8JighAmETj
2026-11-12 11:08:41 +01:00
Kacper f25ac92565 Merge branch 'main' into fix/crafter-triggered-int 2026-11-12 11:08:39 +01:00
AkirabaneandClaude Sonnet 5.5 40ca777682 LAN and dedicated login: refuse a query answer or cookie response nobody asked for
In login_and_configure, while the server waits for LoginAcknowledged, a
CustomQueryAnswer or a CookieResponse was skipped and the login went on to
configuration. Vanilla's ServerLoginPacketListenerImpl.handleCustomQueryPacket
and handleCookieResponse both disconnect with
ServerCommonPacketListenerImpl.DISCONNECT_UNEXPECTED_QUERY
(multiplayer.disconnect.unexpected_query_response). The server sends no query
or cookie request at that point (its one query, the proxy forwarding request,
is sent and answered in forward() before LoginFinished), so any answer is
unexpected. It now sends the login disconnect through refuse(), logs the loss
of the connection and ends the login. Those two packets were the only ones the
wait skipped, so it no longer loops: it reads one packet.

Tests: a query answer and a cookie response each get the disconnect and the two
log lines; a login with nothing stray still reaches configuration.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 10:41:16 +01:00
036dc77592 Stonecutter: the recipe list goes back to the top when its input changes
`StonecutterScreen.containerChanged` (StonecutterScreen.java:205-209) resets
`scrollOffs` and `startIndex`, and the screen hangs it on the input container's
listener (StonecutterMenu.java:37-44), so it runs on any change of the input
slot: adding to the stack, a shift-click into it, and taking a result, which
uses one up (StonecutterMenu.java:66). Picking a recipe or clicking in the
player's inventory is not such a change.

Horizon reset only when the input was empty or there were no recipes, and ran
that after every menu session, so a cut left the list scrolled to its last row.
The reset now follows the input slot having changed, as the enchanting table
does, and a server's slot packet for the input runs it too
(AbstractContainerMenu.setItem -> Slot.set -> setChanged).

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 10:40:01 +01:00
Kacper 2a3b142012 Merge branch 'main' into fix/vex-no-gravity 2026-11-12 10:36:57 +01:00
Kacper a2534b622b Merge branch 'main' into fix/crafter-triggered-int 2026-11-12 10:36:49 +01:00
rdbtCVSandClaude Sonnet 5.5 6d3692c673 Keep the geometry-stage note and add a tessellation note
The merged note broke the two tests that read the geometry note; give
tessellation its own note and cover it in the post loader test.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 09:26:02 +00:00
AkirabaneandClaude Sonnet 5.5 383b68b576 port map: the frustum rows follow the move and the particle frustum test
Frustum.offset and Frustum.pointInFrustum are now ported (Frustum::pulled_back,
Frustum::contains_point), Frustum.isVisible and Frustum.cubeInFrustum cite the
file Frustum moved to (gfx/view_frustum.rs), and QuadParticleGroup.extractRenderState
names ParticleEngine::render_in_view, which does its frustum point test, so its
"no frustum point test" gap is gone.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 10:22:19 +01:00
KBroneZandClaude Sonnet 5.5 69fdcefa2a fix: a sulfur cube's emptied body slot is not saved from its earlier NBT
mob_to_nbt starts from the entity's earlier saved equipment and only
inserted the body; a body taken off (/item replace ... armor.body with air)
kept its old entry, so /data get still read it. Vanilla writes
equipment.body only while the slot holds something.

Fixes #12038

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 11:22:08 +02:00
rdbtCVSandClaude Sonnet 5.5 59493f4837 Format the block entity order test with rustfmt
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 09:20:12 +00:00
AkirabaneandClaude Sonnet 5.5 0a80c3d42f Test that a particle is culled at its position this tick
kacpherek's commit 061ba23407 made the frustum test read the particle's
position this tick instead of an interpolated one, but no test told the two
apart: the tests' particles all had previous equal to position.

The new test draws at partial 0.5 a particle that is ahead now and was far
behind a tick ago (kept) and one that is behind now and was ahead a tick ago
(dropped). With the test using the interpolated point instead, the first is
dropped and the test fails (left 0, right 4).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 10:17:43 +01:00
805f69c8a9 Refuse grindstone and anvil inputs without a damage component
ItemStack.isDamageableItem needs MAX_DAMAGE, DAMAGE and no UNBREAKABLE
(ItemStack.java:421-423); GrindstoneMenu's two input slots (GrindstoneMenu.java:50-52,
:56-58) and AnvilMenu's repair branches (AnvilMenu.java:133, :151, :157) use it. A
stick patched with max_damage but neither the item's durability default nor an
explicit damage is therefore not damageable, so it can no longer enter the
grindstone, nor merge into a "repaired" copy, nor combine its enchantments with another
such stack on the anvil.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 09:28:59 +01:00
Kacpherek d78f0c49c9 Merge main into fix/evoker-fangs-fall-distance-14847 2026-11-12 09:21:51 +01:00
Kacper 663ba1239c Merge branch 'main' into fix/crafter-triggered-int 2026-11-12 09:15:18 +01:00
9303b88c79 heal a happy ghast in the clouds every second
HappyGhast.continuousHeal heals every 20 ticks when
`isInClouds() || precipitationAt(blockPosition()) != NONE`, but Horizon
only asked the precipitation, so a hurt ghast in clear air at the cloud
height healed on the 600-tick interval.

Entity.isInClouds reads the dimension's `visual/cloud_color` alpha (0:
no clouds at all) and `visual/cloud_height` (192.33 in the overworld)
and tests the entity's box against the four blocks above that height.
DimensionFacts now carries both, parsed from the dimension type's
attributes, and MobWorld::in_clouds ports the check; ai_step asks it
before the precipitation, in vanilla's order.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 08:41:23 +01:00
Kacper ecc1570388 Merge branch 'main' into fix/vex-no-gravity 2026-11-12 08:35:38 +01:00
rdbtCVSandClaude Opus 5.5 050e90b150 Native mods: native_explosion_entities spares entities from a blast
A new server hook, after native_explosion_detonate: an explosion is about
to hurt and push the entities in its reach, and a mod takes out the ids
to spare (NeoForge's ExplosionEvent.Detonate entity list). Spared
entities are neither hurt nor pushed. Players aren't listed; they keep
native_living_incoming_damage.

native_hooks.rs may not grow, so viewer_changes moves unchanged to
native_menus.rs, beside the menus.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 06:06:39 +00:00
rdbtCVSandClaude Sonnet 5.5 87be63d40a Merge origin/main into portal TNT provenance branch
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 05:57:11 +00:00
Mayonesu0andClaude Opus 5.5 278d0355e9 Sync randoms before each pufferfish mob contact case
The ordinary-AI pufferfish rolls FishSwimGoal on its own random, which
both engines seed from the clock. About one run in ten it started
swimming in one engine only, and its position read failed (#15484).
A sync_randoms step before each fish's summon makes the roll repeat.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 06:52:05 +01:00
martipopsandClaude Opus 5.5 83e0929684 Merge upstream main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 00:47:21 -05:00
rdbtCVSandClaude Sonnet 5.5 e3e866eb41 Merge main into layers/extras-tweaks
Resolves the docs/forking.md and docs/layers.md conflicts: main's rows kept, with game/extras/ in place of game/tweaks.rs.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 05:35:15 +00:00
Kacpherek a4a529a565 Keep save.rs from growing: the order position comes from save/block_entity_order.rs 2026-11-12 06:31:48 +01:00
rdbtCVSandClaude Sonnet 5.5 a77e616a14 Merge main into fix/wololo-visibility-percent
Main's Seen already carries invisible (flag or effect) and moved Mob::seen to
mobs/seen.rs; drop the duplicate field and put visibility_percent beside it so
mobs.rs does not grow.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 04:53:29 +00:00
yahya-nusseibehandClaude Opus 5.5 336b647f63 Launcher: no Windows device names or disguising marks in downloaded file names
safe_name let a mod or pack file named CON, NUL.jar or COM1.zip through: on Windows the
joined path names a device, and the rename from its .part file fails or acts on it. It
also let bidirectional and zero-width marks through, so a shown name could read as
another. Both are now refused, like a path separator.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:43:22 +02:00
yahya-nusseibehandClaude Opus 5.5 65676a7dbd WebSocket: control frames must come whole and short
RFC 6455 5.5 has control frames unfragmented with at most 125 bytes, and Netty's decoder
that vanilla uses fails the connection otherwise. Here a 64 KiB ping was accepted and
echoed, and a fragmented one answered. Both now end the connection.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:35:46 +02:00
yahya-nusseibehandClaude Opus 5.5 f181472b63 Query: cap the challenges held between prunes
Every handshake from a new address added a token, and the map was cleared only every 30 s,
so spoofed UDP handshakes grew it with the packet rate. At 65,536 addresses a new one gets no
answer until the next prune; an address already holding a token still gets a new one.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:33:31 +02:00
yahya-nusseibehandClaude Opus 5.5 875b98b71f Service: refuse paths a systemd unit would misread
service install wrote the server folder and the program path into the unit as they were. A %
in a folder name is a systemd specifier, a line break adds a directive, and a quote or a
backslash changes ExecStart's quoting. Such a path is now refused with a plain message.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:31:43 +02:00
yahya-nusseibehandClaude Opus 5.5 5e177afe1d Prune: a spawn radius past i32 keeps everything instead of nothing
prune_chunks.spawn_radius is a u32 cast to i32, so a value above i32::MAX wrapped negative,
no chunk counted as near spawn and a delete run pruned the spawn area. The radius now
saturates at i32::MAX: as large a radius as asked for, keeping every chunk.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:29:59 +02:00
yahya-nusseibehandClaude Opus 5.5 59972a243d Panel: wrong login codes no longer lock out the right one
Failed logins were counted for everyone and checked before the code, so ten bad /login
requests a minute from anyone who could reach the panel made the owner's own link fail with
429. The limit now applies only to wrong codes; a valid link always signs in.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SJ3stK8iXVDXqoi7midcqd
2026-11-12 06:28:11 +02:00
rdbtCVSandClaude Sonnet 5.5 92eb621473 Merge main into fix/goat-horn-byte-14970
Goat horn flags now read in mobs::goat::read_nbt with the byte-valued rule.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 03:51:12 +00:00
Kacpherek 061ba23407 Cull particles by their current position instead of an interpolated one 2026-11-12 04:41:02 +01:00
Mayonesu0andClaude Opus 5.5 80eca9b7e2 wire_stream harness: run on Windows (natives, console encoding, .exe)
vanilla_client picks the natives jar the launcher's rules keep for this
OS and architecture (natives-windows, natives-windows-arm64, ...) from the
version JSON instead of knowing only macOS and Linux. The JVM writes UTF-8
and the reader replaces stray bytes, so a cp1252/cp850 console no longer
kills it; the log is UTF-8. lab.binary finds horizon-client.exe.

Fixes #15500

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 04:37:34 +01:00
Kacpherek af9e445fbd Reject an item template whose count is outside 1 to 99, as vanilla does 2026-11-12 04:33:16 +01:00
Kacpherek 745274bee2 Skip shader programs with a tessellation stage so their fallback is used
A program with a .tcs or .tes stage was loaded as a plain vertex and
fragment program, silently dropping the tessellation stage. Horizon has
no tessellation backend, so skip such a program with a note, as an
unsupported geometry stage already is, and let the fallback chain pick
the next program.

Fixes #7922
2026-11-12 04:33:15 +01:00
Kacpherek f85db126cc Move the player rotation packet handling out of remote.rs so the file shrinks 2026-11-12 04:32:59 +01:00
Kacpherek 5ca6902528 Fix the two clippy warnings in the text layout pass 2026-11-12 04:32:28 +01:00
Kacpherek 8286150240 Record a moved block entity's load order under its corrected position 2026-11-12 04:31:30 +01:00
Mayonesu0andClaude Opus 5.5 62eb25aa1d wire stream: a teleport's answer ticks keep the position reminder on the script's clock
compare_answered compared the two clients' answer ticks whole. In dig_teleport
(`tp @s ~ ~ ~`) the answer moves nobody, and LocalPlayer.sendPosition's 20-tick
position reminder stays on the script's clock (ClientPacketListener.handleMovePlayer
resets neither positionReminder nor xLast): it falls on tick 27 in both clients.
When the server answers Horizon a tick later than vanilla (26 vs 27), Horizon's
answer tick carries the reminder and vanilla's doesn't, which the nightly reported
as an extra move_player_pos (#14807).

The answer ticks now compare without their moves, and their moves compare tick for
tick, on the script's clock.

Fixes #14807

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 04:26:06 +01:00
Kacpherek c497ba5279 Test that an item frame keeps its loaded Motion, OnGround and fall_distance 2026-11-12 04:20:15 +01:00
Kacpherek 6f2a39f578 Merge commit '571ef142c5' into unstick/14642
# Conflicts:
#	crates/horizon-client/src/game/recipe_book.rs
2026-11-12 04:12:33 +01:00
Kacpherek 22bfbbd417 Merge commit '571ef142c5' into unstick/14459
# Conflicts:
#	crates/horizon-client/src/game/item_entities.rs
2026-11-12 04:11:50 +01:00
Kacpherek 523f142977 Merge commit '571ef142c5' into unstick/15428
# Conflicts:
#	crates/horizon-client-render/src/core_shader/glsl_fixups.rs
#	crates/horizon-client-render/src/core_shader/glsl_fixups/tests/mod.rs
2026-11-12 04:10:52 +01:00
DetimesandClaude Opus 5.5 c950a3dafe Merge the branch's main update from GitHub
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 03:09:32 +00:00
Kacpherek f92b723265 Merge commit '571ef142c5' into unstick/14349
# Conflicts:
#	crates/horizon-client-render/src/particles.rs
2026-11-12 04:06:39 +01:00
Kacpherek fdf5a402aa Merge commit '571ef142c5' into unstick/14901
# Conflicts:
#	crates/horizon-client-render/src/chat_tests.rs
2026-11-12 04:06:31 +01:00
DetimesandClaude Opus 5.5 784eb9f185 Merge upstream/main into perf-effect-meta
Keeps main's new cave_air_tests module next to effect_meta_tests.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 03:06:17 +00:00
Kacpherek aa71621cae Merge commit '571ef142c5' into unstick/14684
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-12 04:02:32 +01:00
Kacpherek e829142877 Merge commit '571ef142c5' into unstick/14476
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-12 04:02:07 +01:00
Kacpherek 4ae80fa5ea Merge commit '571ef142c5' into unstick/14258
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-12 04:01:23 +01:00
DetimesandClaude Opus 5.5 4484d84eed Effect particles: cache only the particle type ids, not the colour
An effect's colour comes from the resource packs (set_pack_colors) and a
pack reload replaces it without replacing the hub's SyncData, so a cached
particle kept the old colour. The cache now holds only the registry id of
each particle type; the colour is read on every call. New test: a pack
colour change shows although the id is cached.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 02:37:06 +00:00
Kacpherek 0cc70624e2 Merge commit '24b778c3b4' into unstick/14663
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-12 02:55:10 +01:00
Kacpherek 2f113e476a Merge commit '24b778c3b4' into unstick/14257
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-12 02:54:34 +01:00
Kacpherek f48bf07992 Merge commit '24b778c3b4' into unstick/14899
# Conflicts:
#	crates/horizon-client/src/game/native_shaders.rs
#	docs/api/shaders.md
2026-11-12 02:52:46 +01:00
Kacpherek 19fa5d003a Merge commit 'aab654d4e8' into unstick/14590
# Conflicts:
#	crates/horizon-client/src/game/item_entities.rs
2026-11-12 02:16:48 +01:00
Kacpherek bad917dea7 Merge commit 'aab654d4e8' into unstick/14663
# Conflicts:
#	crates/horizon-client/src/entity_nbt/hanging.rs
2026-11-12 02:14:00 +01:00
Kacpherek 8604af23c4 Merge commit 'aab654d4e8' into unstick/14294
# Conflicts:
#	crates/horizon-client/src/mobs/piglin.rs
2026-11-12 02:11:45 +01:00
Kacpherek cd1c3ad784 Merge commit 'aab654d4e8' into unstick/14852
# Conflicts:
#	crates/horizon-client/src/entity_nbt.rs
2026-11-12 02:10:43 +01:00
Kacper 018f221041 Merge branch 'main' into revert/13737-boat-fire 2026-11-12 02:01:23 +01:00
Kacpherek 9d9edcc5c7 Ask for the busy thread's stack only once it is in the busy frame
The stack dump test asked for the worker's stack as soon as the worker's
handle arrived. The worker could still be inside the channel send that
woke the test thread, so the sample sometimes held no busy frame and the
test failed about one verify run in three.
2026-11-12 02:00:36 +01:00
Kacpherek b808a25d4b chat_tests: the double click test and the suggestion list test stand apart again 2026-11-12 01:58:33 +01:00
Kacpherek 2b35f4bfc6 Merge remote-tracking branch 'origin/main' into unstick/14901 2026-11-12 01:57:08 +01:00
Kacpherek 2106fb21d8 Camel pose test: saved entities go back in as pending entities 2026-11-12 01:30:39 +01:00
Kacpherek 4752a44392 Merge remote-tracking branch 'origin/main' into unstick/14558 2026-11-12 01:29:04 +01:00
Kacper 869df6be8e Merge branch 'main' into fix/atlas-single-sprite-renames 2026-11-12 01:15:51 +01:00
Kacper 10ea380a42 Merge branch 'main' into xmilon/dim-sea 2026-11-12 01:15:08 +01:00
Kacper da19583b0e Merge branch 'main' into fix/14804-frame-motion 2026-11-12 01:14:59 +01:00
Kacper a4bf39fccf Merge branch 'main' into parity/allay-pickup-cooldown-back 2026-11-12 01:13:23 +01:00
Kacper a856c936d6 Merge branch 'main' into tests/world-test-lifecycle-forced-chunk 2026-11-12 01:13:05 +01:00
Kacper 79b225758e Merge branch 'main' into up-relbinary-save-reload 2026-11-12 01:12:21 +01:00
Kacper f26c009854 Merge branch 'main' into fix/block-entity-pos-from-tag 2026-11-12 01:10:41 +01:00
Kacper 783c5d4bd5 Merge branch 'main' into fix/predicate-terms-holder-forms 2026-11-12 01:10:32 +01:00
Kacper 9108c8ea68 Merge branch 'main' into fix/crafter-triggered-int 2026-11-12 01:10:23 +01:00
Kacper 8c2241221b Merge branch 'main' into agent/pack-options-shell 2026-11-12 01:10:05 +01:00
Kacper fb003e9b48 Merge branch 'main' into fix/horizon-preset-name 2026-11-12 01:08:43 +01:00
Kacper e243b417ec Merge branch 'main' into falling-spawn-lookup 2026-11-12 01:08:27 +01:00
Kacper 0539295b59 Merge branch 'main' into fix/wololo-visibility-percent 2026-11-12 01:07:08 +01:00
Kacper 0e06fcffe8 Merge branch 'main' into fix/player-rotation-packet-parity 2026-11-12 01:05:30 +01:00
Kacper d340ac54e6 Merge branch 'main' into fix/chat-double-click-word 2026-11-12 01:05:20 +01:00
Kacper 30aa7c3cd9 Merge branch 'main' into fix-far-detail-resample 2026-11-12 01:04:52 +01:00
Kacper c187167717 Merge branch 'main' into perf/worldgen-noise-masks 2026-11-12 01:04:34 +01:00
Kacper 09449b8b5a Merge branch 'main' into up-14641-stack-components 2026-11-12 01:03:49 +01:00
Kacper 3a44c61b5c Merge branch 'main' into fix/jukebox-song-reload 2026-11-12 01:03:26 +01:00
Kacper d1617aa506 Merge branch 'main' into perf/upload-budget-follows-frame 2026-11-12 01:03:24 +01:00
Kacper adf711981d Merge branch 'main' into split/11535-pending-entity-provenance-20261109 2026-11-12 01:02:59 +01:00
Kacper b140490175 Merge branch 'main' into fix/vex-no-gravity 2026-11-12 01:02:37 +01:00
Kacper 7244070cdf Merge branch 'main' into fix/end-crystal-saved-fall 2026-11-12 01:02:28 +01:00
Kacper 05ed4ff36f Merge branch 'main' into tools/fall-clip-wait-neighbourhood 2026-11-12 01:02:15 +01:00
Kacper e554afd5a3 Merge branch 'main' into fix/13632-atlas-sprites 2026-11-12 01:02:06 +01:00
Kacper 765595fc00 Merge branch 'main' into fix/thrown-potion-level-entity 2026-11-12 01:01:39 +01:00
Kacper 071685a3cf Merge branch 'main' into fix/raw-entity-flags 2026-11-12 01:00:35 +01:00
Kacper 54a7673ecc Merge branch 'main' into fix/piglin-cannot-hunt 2026-11-12 01:00:25 +01:00
Kacper 6d01f74e39 Merge branch 'main' into oc-entity-data 2026-11-12 00:59:01 +01:00
Kacper 44cb065704 Merge branch 'main' into fix/windows-open-folder-shell 2026-11-12 00:58:43 +01:00
Kacper 1aef29fada Merge branch 'main' into perf-effect-meta 2026-11-12 00:57:32 +01:00
Kacper f701cc7e5a Merge branch 'main' into oc-equipment-ids 2026-11-12 00:56:57 +01:00
Kacper 80ef919e40 Merge branch 'main' into fix/14454-minecart-shulker 2026-11-12 00:56:26 +01:00
Kacper a4c81b629b Merge branch 'main' into up13/lang-dead-keys 2026-11-12 00:55:18 +01:00
Your Name ad8e395f3c Merge main into fix/item-count-max-stack 2026-11-12 12:40:00 +13:00
Evrim Cicek f071ffe84b Merge remote-tracking branch 'upstream/main' into tools/fall-clip-wait-neighbourhood 2026-11-12 02:18:39 +03:00
AkirabaneandClaude Sonnet 5.5 525c1c9834 Merge origin/main into feat/7255-particle-frustum
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 00:15:44 +01:00
DetimesandClaude Opus 5.5 627864a666 Merge upstream/main: the effect particle cache moves into SyncData
Main moved Hub::effect_meta into SyncData::effect_meta (read by helper
threads since #14506). The per-(effect, ambient) particle cache follows it:
lan/effect_meta.rs keeps ParticleCache and particle_of, SyncData holds the
cache behind a Mutex and Hub::effect_meta delegates as on main. hub.rs
loses the field and module line instead of growing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 23:08:54 +00:00
AkirabaneandClaude Sonnet 5.5 efaac3cdc0 Merge origin/main into feat/7255-particle-frustum
crates/horizon-client-render/src/gfx.rs: this branch moved Frustum into
gfx/view_frustum.rs (kept, with its mod and pub use); main left Frustum as it was
but moved shadow_box into gfx/external.rs, so the old shadow_box beside Frustum
here is dropped.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-12 00:00:00 +01:00
Kacpherek 6c090eb39d Merge commit '3298a6dcd5' into unstick/14590
# Conflicts:
#	crates/horizon-client/src/game/persist.rs
2026-11-11 23:56:32 +01:00
Kacper 4e44044828 Merge branch 'main' into fix/thrown-potion-level-entity 2026-11-11 23:56:20 +01:00
Kacper 0788a51320 Merge branch 'main' into perf/upload-budget-follows-frame 2026-11-11 23:55:46 +01:00
Kacper 59319a8e2d Merge branch 'main' into fix/vex-no-gravity 2026-11-11 23:54:59 +01:00
Kacper 3086bc8910 Merge branch 'main' into fix/end-crystal-saved-fall 2026-11-11 23:54:50 +01:00
Kacper 632b455a88 Merge branch 'main' into fix/raw-entity-flags 2026-11-11 23:52:59 +01:00
Kacper 4339a77eae Merge branch 'main' into fix/piglin-cannot-hunt 2026-11-11 23:52:50 +01:00
Kacpherek 4a33f95d69 Merge commit '3298a6dcd5' into unstick/14973
# Conflicts:
#	crates/horizon-client/src/entity_nbt.rs
2026-11-11 23:52:10 +01:00
Kacper 0ede61c00a Merge branch 'main' into oc-entity-data 2026-11-11 23:51:27 +01:00
Kacper ba53cff558 Merge branch 'main' into fix/windows-open-folder-shell 2026-11-11 23:51:09 +01:00
Kacper f8f3d2e043 Merge branch 'main' into oc-equipment-ids 2026-11-11 23:49:23 +01:00
Kacper 4347efb700 Merge branch 'main' into fix/14454-minecart-shulker 2026-11-11 23:48:50 +01:00
Kacper 43685602fc Merge branch 'main' into up13/lang-dead-keys 2026-11-11 23:47:41 +01:00
DetimesandClaude Opus 5.5 73e29da806 Merge upstream/main into perf-effect-meta
Resolves the conflict with main (new hub modules chunk_batch and far_tests next to effect_meta).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 22:35:24 +00:00
Kacpherek 463855a17c Merge commit '8d44c49cd301632618c5cbe08a792a53b405fbdf' into unstick/14268
# Conflicts:
#	crates/horizon-client-render/src/hud.rs
2026-11-11 23:26:07 +01:00
Mayonesu0andClaude Sonnet 5.5 eb0605533b Resolve the save/reload harness's --binary against the caller's directory
Each server runs with its temporary world as the working directory, so a relative
`--binary target/fast/horizon-client` was looked up under the world and failed even when the
binary existed. Make the path absolute before starting the servers, with a unit test.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-11 23:24:31 +01:00
Kacper e56aceb38a Merge branch 'main' into fix/wololo-visibility-percent 2026-11-11 23:23:09 +01:00
Kacper 1db662da23 Merge branch 'main' into fix/player-rotation-packet-parity 2026-11-11 23:21:29 +01:00
Kacper cf98445e8f Merge branch 'main' into fix/chat-double-click-word 2026-11-11 23:21:11 +01:00
Kacper d83dac2429 Merge branch 'main' into fix-far-detail-resample 2026-11-11 23:20:44 +01:00
Kacper ece1d80195 Merge branch 'main' into up-14641-stack-components 2026-11-11 23:19:42 +01:00
Kacper 858de11740 Merge branch 'main' into fix/jukebox-song-reload 2026-11-11 23:19:00 +01:00
Kacper 3528b8ce41 Merge branch 'main' into split/11535-pending-entity-provenance-20261109 2026-11-11 23:18:34 +01:00
Kacper 2525ab8ff8 Merge branch 'main' into tools/fall-clip-wait-neighbourhood 2026-11-11 23:17:29 +01:00
darkliro a67a4b9f4b Merge remote-tracking branch 'upstream/main' into perf/upload-budget-follows-frame 2026-11-11 22:44:24 +01:00
Kacpherek 8a205c4d53 Merge commit '6cc36c6f3a' into unstick/14758
# Conflicts:
#	crates/horizon-core/src/density/selection.rs
2026-11-11 22:30:33 +01:00
Evrim CicekandClaude Opus 5.5 6980c84dfc parity_hosts: world_test_def_lifecycle runs automatically again
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 00:29:48 +03:00
Kacpherek 6d72da27f6 Merge commit '6cc36c6f3a' into unstick/14150
# Conflicts:
#	crates/horizon-client/src/game/dispenser.rs
2026-11-11 22:29:30 +01:00
Evrim Cicek 18e01a3ba2 Merge remote-tracking branch 'upstream/main' into tests/world-test-lifecycle-forced-chunk 2026-11-12 00:28:49 +03:00
Kacpherek c994a813ec Merge commit '6cc36c6f3a' into unstick/14590
# Conflicts:
#	crates/horizon-client/src/game/persist.rs
2026-11-11 22:26:54 +01:00
Kacpherek ee18d85a3d Merge commit '6cc36c6f3a' into unstick/14973
# Conflicts:
#	crates/horizon-client/src/entity_nbt.rs
2026-11-11 22:26:47 +01:00
Kacpherek 1c7ff0f82d Merge commit '6cc36c6f3a' into unstick/11261
# Conflicts:
#	crates/horizon-client/src/entity_nbt/hanging.rs
2026-11-11 22:26:34 +01:00
Evrim CicekandClaude Opus 5.5 8be0fd72d2 world_test_def_lifecycle reads a chunk only /forceload holds
The step's /execute if loaded read the spot's own chunk. The Java oracle's
player isn't ticked, so its tickets stay on the 5x5 chunks around its
spawn, while Horizon's player loads the chunks around wherever it stands:
once GameTestRunner's batch listener released the forced chunks, spots 56
to 104 were unloaded in Java only (4 of 99 records, #15158). The read is
now of chunk x 11, which only /forceload holds and neither player reaches;
both sides see the release at the same step.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-12 00:25:03 +03:00
Kacpherek 6e6c114701 Merge commit 'a5df8273bb' into unstick/14558
# Conflicts:
#	crates/horizon-client/src/game/commands.rs
2026-11-11 22:11:36 +01:00
Vinícius Moreira c482d207f0 Merge commit 'c8e1eb66199f696d1a6218fbbaeef1863ce5cc00' into HEAD
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 18:08:07 -03:00
Vinícius Moreira 66493ad0a4 Merge commit 'c8e1eb66199f696d1a6218fbbaeef1863ce5cc00' into fix/raw-entity-flags
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 17:57:12 -03:00
Vinícius Moreira c3f130ec76 Merge commit 'c8e1eb66199f696d1a6218fbbaeef1863ce5cc00' into fix/vex-no-gravity
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 17:57:11 -03:00
Vinícius Moreira 03ed9279f2 Merge commit 'c8e1eb66199f696d1a6218fbbaeef1863ce5cc00' into fix/painting-on-ground
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 17:57:08 -03:00
Vinícius Moreira ceb22dff50 Merge commit 'c8e1eb66199f696d1a6218fbbaeef1863ce5cc00' into fix/end-crystal-saved-fall
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 17:57:07 -03:00
rdbtCVSandOpenCode 986616a581 test: cover crafter triggered double decoding
Address Akirabane's small follow-up suggestion on PR #14257: pin floor and saturation when a crafter's triggered value loads from a double NBT tag. No production behavior changes.

Co-Authored-By: OpenCode (GPT 6.1 Sol) <[email protected]>
2026-11-11 20:56:41 +00:00
Kacpherek a4e2314c0b Move set_reduced_detail out of lod.rs so the big file does not grow 2026-11-11 21:55:19 +01:00
Kacpherek 2f763d92f6 Merge commit 'd0f5bccf60' into unstick/14811 2026-11-11 21:54:41 +01:00
Kevin RamirezandClaude Opus 5.5 d025af8ef1 allay_pickup_cooldown back in parity runs; the healing test reads the pickup cooldown where it lives
- allay_pickup_cooldown passes on main now (twice locally with prepared
  resources), so it leaves named_only in parity_hosts.json (#15158).
- allays_heal_on_tenth_ticks_without_enabling_noai_work still set and
  read extra.ints[3], which held ITEM_PICKUP_COOLDOWN_TICKS until it
  moved to AllayState::pickup_cooldown: the test fails on main whenever
  prepared resources are present (CI has none, so it skips). It now
  sets and reads the cooldown through allay::set_pickup_cooldown and
  pickup_cooldown.

Part of #15158

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 14:53:54 -06:00
Kacpherek 4ac7e4ed1c Move the inline atlas sprite lookup out of hud.rs so the big file does not grow 2026-11-11 21:53:16 +01:00
Kacpherek 59f9d5cc79 Merge commit 'd0f5bccf60' into unstick/14268 2026-11-11 21:52:06 +01:00
Kacper 852dc6da3e Merge branch 'main' into fix/wololo-visibility-percent 2026-11-11 21:51:06 +01:00
Kacper 682d70268a Merge branch 'main' into fix/player-rotation-packet-parity 2026-11-11 21:50:24 +01:00
Kacper 601d2e24ad Merge branch 'main' into fix/chat-double-click-word 2026-11-11 21:50:16 +01:00
Kacpherek fdd210261e Revert "Boats: Mth's sine table for steering, dismounts and minecart pushes; lastYd for water entry" (#13737)
Its parity run failed boat_fire (781 of 789 commands): after a boat burns, Horizon leaves an item where vanilla leaves none. The harness does not fail on main without it. Merged by mistake before the author answered; it can come back once boat_fire passes.
2026-11-11 21:47:09 +01:00
Kacpherek fc67e09538 Merge commit 'a5df8273bb' into unstick/14301
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-11 21:46:22 +01:00
Kacpherek 9ccd03e15c Merge commit 'a5df8273bb' into unstick/14687
# Conflicts:
#	crates/horizon-client/src/game/player_equip.rs
#	crates/horizon-items/src/items.rs
2026-11-11 21:43:23 +01:00
Kacpherek b6a22b4d5d Keep the Alt state and the extended preset list out of the big files
game.rs, title.rs and save.rs are over 3000 lines and may not grow: the Alt state lives in
WorldOptions, set from update_modifiers, and WorldPreset::step sits in create_world.rs.
2026-11-11 21:42:49 +01:00
Kacpherek d38f369ade Keep the arrow sound save and load out of entity_nbt.rs
entity_nbt.rs is over 3000 lines and may not grow: the SoundEvent save and load move into
ArrowState methods in arrows.rs.
2026-11-11 21:42:29 +01:00
Kacpherek a45820d34e Merge commit 'a5df8273bb' into unstick/14578
# Conflicts:
#	crates/horizon-client/src/game/jukebox.rs
2026-11-11 21:41:09 +01:00
rdbtCVSandGPT 6.1 Sol b9b53a6b06 Remove committed clippy build log
Address the explicit request in review 5863588800. No gameplay or test code changes.

Co-Authored-By: GPT 6.1 Sol <[email protected]>
2026-11-11 20:29:11 +00:00
rdbtCVSandOpenAI GPT-6.1 Sol 83583196d4 Merge main into sprite metadata fix
Resolve the shared first_json helper conflict by retaining the generic parser while preserving main's metadata behavior and animation regression test.

Co-Authored-By: OpenAI GPT-6.1 Sol <[email protected]>
2026-11-11 20:23:44 +00:00
DetimesandClaude Opus 5.5 b11f2ea604 Merge upstream/main into perf-effect-meta
Brings the branch up to date with main for review.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 20:20:15 +00:00
Evrim CicekandClaude Opus 5.5 80726b9127 desktop: links keep their own opener; a verbatim path gives its plain URI
open_uri on Linux and macOS went through open_folder, which now resolves
the path first, so a link would fail as a missing file: desktop::open_uri
hands it to open / xdg-open as it is. dunce leaves a share (a mapped drive
too) or a path past MAX_PATH as \?\ (UNC); file_uri gave file://%3F/...
for those, which the shell can't open. dunce and open leave horizon-client,
which no longer uses them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 23:07:18 +03:00
LucasandClaude Opus 5.5 b886a382d8 Core shaders: an array sized by a local int constant takes its expression
Vanilla 26.3's oit_sample.glsl sizes an array by a constant declared in
its function (const int targetCount = OIT_COEFF_COUNT / 4;
vec4 coeffSamples[targetCount];), which naga's GLSL front end refuses.
Each such array size takes the constant's expression, from the
innermost scope that declares it. A guarded include pasted twice
declares the same constant twice and still sizes its arrays; two
different expressions for one name in a scope, or more than 256
constants, leave the text as it was.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 21:06:33 +01:00
Evrim CicekandClaude Opus 5.5 2160ff3fe7 Windows: open folders through the shell's file association, not explorer
Blaze3D.openPath hands path.toUri() to SDL_OpenURL, which on Windows is
ShellExecute's open verb, so a folder opens in the default file manager.
The pack folders (packs::open_folder) and the world and backup folders
(world_management::open_folder) started explorer instead. Both now go
through desktop::open_path: a file: URI to ShellExecute on Windows (the
open crate's folder shortcut, SHOpenFolderAndSelectItems, is Explorer's
own), open / xdg-open elsewhere.

Fixes #15259.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 23:00:08 +03:00
Kacpherek 18b0590437 Offer Debug Mode on the world type button while Alt is held
The Create World type button never reached Debug Mode. Vanilla cycles WorldPresetTags.EXTENDED (normal list plus Debug) while Alt is held, and the normal list otherwise.
2026-11-11 20:57:24 +01:00
Kacpherek 14999a6bda Switch a crossbow arrow to the arrow hit sound after its first block
The sound was picked from the weapon on every hit and saved as item.crossbow.hit forever. Vanilla's soundEvent is the crossbow's only until onHitBlock sets entity.arrow.hit.
2026-11-11 20:57:11 +01:00
Kacpherek c52976236b Merge main into pr-14580
# Conflicts:
#	crates/horizon-client/src/game/minecarts.rs
2026-11-11 20:56:50 +01:00
DetimesandClaude Opus 5.5 d72fab3a55 Older clients: the Writer import of step_1_21_6 is test-only
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 19:56:02 +00:00
Kacpherek 8ec11feda8 Merge main into pr-14590
# Conflicts:
#	crates/horizon-client/src/game/last_hurt_by_mob_tests.rs
2026-11-11 20:55:11 +01:00
martipopsandClaude Opus 5.5 3e3ed99fde Merge upstream main into Pack Options on the settings shell
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 14:46:38 -05:00
Kacpherek 56b3fbab8c Merge main into agent/pack-options-shell 2026-11-11 20:42:37 +01:00
Kacpherek 1a44550fc8 Merge main into up13/lang-dead-keys 2026-11-11 20:42:01 +01:00
Kacpherek dfcfa1a0db Merge main into fix/hanging-item-stack-config 2026-11-11 20:41:38 +01:00
Detimes 09fdcaf8db Older clients: entity data in their serializer ids
(cherry picked from commit 159e992cd6, without the local recipe drop)
2026-11-11 19:24:03 +00:00
Detimes 277f388e26 Older clients through 1.21.6: read equipment in the client's ids
1.21.6's step (the saddle slot) read set_equipment, already in the client's item and component ids, as pinned
ids, so the first equipment with a component disconnected every client through 1.21.6 ("NBT at byte 1: unknown
tag type"). It reads and writes the stacks in the client's ids now; a session test sends equipment with
components to every older release.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
(cherry picked from commit 2dc378ce5b05a6dbb8dad635490e0fc86d73d183)
2026-11-11 19:24:03 +00:00
RLC248 1759cc1565 Merge remote-tracking branch 'upstream/main' into fix/thrown-potion-level-entity 2026-11-11 19:55:13 +01:00
Web-mc1 b7414749eb Clamp NBT item count to prevent oversized stacks 2026-11-12 06:35:15 +13:00
Oloion d1d6b41685 ui: avoid heap allocations in design-system label layout 2026-11-11 19:58:16 +03:00
RLC248 ffb455858e Merge remote-tracking branch 'upstream/main' into fix/thrown-potion-level-entity
# Conflicts:
#	crates/horizon-client/src/game/tnt.rs
2026-11-11 17:21:25 +01:00
Nikita Maximilian GrimmandClaude Fable 5.2 ca1c65d957 Shader API 0.2: an entity-only pack may ask for its shadow map and lights
`[shadow]`, `[[lights]]` and `[[particle_lights]]` were refused without a
`[material]` (or, for the shadow, a `[[post]]`), though the entity stage reads
the shadow maps and the coloured lights too. A 0.2 pack with only `[entity]`
had to add a stage it didn't want. The three checks now take `[entity]` as a
stage that reads them; 0.1 keeps its rules, and its two light messages are
reworded with the same meaning.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-11 14:41:12 +01:00
Nikita Maximilian Grimm d580bddaec Merge remote-tracking branch 'origin/main' into shader-api-entity-stage 2026-11-11 14:39:22 +01:00
rdbtCVSandGPT 6.1 Sol caf5e9b7d6 Merge main to pick up the upstream CEM compile fix
Includes main fix 04b53013c8 without unrelated local code edits; preserves the contributor history and translation-only PR diff.

Co-Authored-By: GPT 6.1 Sol <[email protected]>
2026-11-11 11:42:22 +00:00
Ludovic MarieandClaude Opus 5.5 7fd46c83e5 perf: adapt chunk mesh upload budget to frame pace
High-framerate gameplay (e.g. 144Hz - 300+ FPS) suffers from micro-stutters
when chunk mesh uploads are capped by a flat 2 ms time budget, because 2 ms
can represent 30% to 60% of an entire frame interval (which is ~3.3 ms to
~6.9 ms).

This commit introduces dynamic frame-paced upload budgeting:
- Computes an exponentially smoothed frame time.
- Budgets mesh uploads dynamically to at most 25% of recent frame time.
- Enforces a 250 µs floor and scales up to a 2 ms ceiling when a backlog
  of pending uploads accumulates.
- Preserves the higher 6 ms allocation during initial terrain arrival
  (world open or teleportation).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 12:27:15 +01:00
rdbtCVSandGPT 6.1 Sol 2962f1172d Merge main into #11261, preserving hanging stack-config coverage
Resolve the corpus registration conflict without changing any main group or hanging-config operation. Restore the BoatItem.use documentation to place_boat.

Co-Authored-By: GPT 6.1 Sol <[email protected]>
2026-11-11 08:49:19 +00:00
MSedgeMC 2d216e9c78 port_map: the wololo row names the visibility it scales by
The row said "scaled by visibility" while the code used the two extremes of
the invisibility effect; it now names `getVisibilityPercent`, the flag or the
effect, and the 0.07 factor.
2026-11-11 06:30:32 +00:00
MSedgeMC 182cbc1a5c test: a flagged invisible blue sheep is out of wololo range at fourteen
Two evoker wololo casts in a real goal selector, with a blue sheep 14 blocks
away: the visible sheep starts `UseSpell`, the same sheep with `invisible: true`
does not. Without the visibility-scaled range both are picked, `[true, true]`
against `[true, false]`.

The existing five-block test with the invisibility effect still passes: the
effect counts beside the flag.
2026-11-11 06:30:25 +00:00
MSedgeMC ea783f5db0 fix: a wololoed sheep's range scales by its visibility
`Evoker$EvokerWololoSpellGoal` finds its blue sheep with
`TargetingConditions.forNonCombat().range(16)`, and `TargetingConditions.test`
scales that range by `LivingEntity.getVisibilityPercent` with a floor of 2.
Horizon asked `has_effect("invisibility")` and used the two extremes, so a
sheep with the `invisible` entity flag and no effect stayed in range at
sixteen blocks where vanilla's percent is 0.07 and the range 1.12, floored to
2.

`Seen` now carries `invisible` (`Entity.isInvisible`) and answers
`visibility_percent`, the mob half of `getVisibilityPercent`: 1, or
0.7 x armor cover (at least 0.1) while invisible - a mob does not sneak and its
`getArmorCoverPercentage` is 0, so 0.07. The effect counts beside the flag
because vanilla's `updateInvisibilityStatus` copies it into the flag each tick
and Horizon has no port of that yet. The wololo filter uses it.

`Seen.invisible` is the same field #13755 adds for follow-mob goals; whichever
lands second takes the other's line.
2026-11-11 06:29:14 +00:00
MSedgeMC 31bf00a458 Merge remote-tracking branch 'upstream/main' into HEAD 2026-11-11 03:52:55 +00:00
Vinícius Moreira ac68d5ae04 Merge remote-tracking branch 'upstream/main' into fix/end-crystal-saved-fall 2026-11-11 00:03:46 -03:00
Vinícius Moreira b5ae68c8b7 Merge remote-tracking branch 'upstream/main' into fix/crafter-triggered-int 2026-11-11 00:03:46 -03:00
Vinícius MoreiraandClaude Opus 5.5 76a8f27085 Merge main into fix/raw-entity-flags: main compiles again (#15038)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 23:57:45 -03:00
Vinícius MoreiraandClaude Opus 5.5 0ba2a84306 Merge main into fix/vex-no-gravity: main compiles again (#15038)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 23:56:36 -03:00
Vinícius MoreiraandClaude Opus 5.5 40b2f16229 Merge main into fix/painting-on-ground: main compiles again (#15038)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 23:56:02 -03:00
Vinícius MoreiraandClaude Opus 5.5 023a57e557 rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 23:48:53 -03:00
Vinícius MoreiraandClaude Opus 5.5 08fba7506e A block entity's ints load as getIntOr does; the crafter group moves apart
decode_block_entity reads every int through nbt_path::int_value
(NumericTag.intValue: a float or double floored and saturated), so the
crafter's triggered keeps rustfmt's single line and save.rs does not
grow. The crafter group moves to a chunk no other group forces within
five columns.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 22:43:08 -03:00
Vinícius MoreiraandClaude Opus 5.5 a15fb9d167 An end crystal reads its fall with ground_from_nbt; /tp grounds it; powder snow's shape counts
ground_from_nbt on main already reads OnGround and fall_distance, so the
helper this pull request added goes. TeleportCommand.performTeleport
sets onGround. Powder snow's inside shape for a fall over 2.5 is 0.9
tall, so a crystal above it keeps its fall. The deflate is 1.0E-5F.
The group adds both powder snow cases and a teleported crystal.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 22:42:25 -03:00
Vinícius MoreiraandClaude Opus 5.5 947aae2b5b A crafter's screen draws its arrow from the int; a double triggered floors
CrafterScreen asks menu.isPowered(), data slot 9 == 1, not the block
state, so a crafter[triggered=true]{triggered:5} shows the unpowered
arrow. getIntOr reads a double through DoubleTag.intValue, floored and
saturated: -0.5d is -1 and 4294967297d is 2147483647, where the cast
truncated and wrapped.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 22:37:15 -03:00
Vinícius MoreiraandClaude Opus 5.5 b1499e6662 An end crystal carries its own loaded fall; a cobweb resets it
The loaded OnGround and fall_distance now live on the crystal, so a
crystal summoned where a loaded one was killed starts from nothing and
a teleported crystal keeps its own (the position-keyed compound found
neither). EndCrystal.tick's applyEffectsFromBlocks resets the fall in
a cobweb or powder snow (makeStuckInBlock). Crystal::new builds the
fresh crystal its five call sites wrote out; start_time moves beside it
in dragon/crystal.rs, keeping dragon.rs from growing.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 22:35:59 -03:00
RINNECODERandClaude Opus 5.5 adb0766fe6 Merge main: #14430's crate lang files in the key check
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 19:24:39 -06:00
MSedgeMC fcbbd1f556 Merge main; keep both sides' tests and module declarations 2026-11-11 01:02:55 +00:00
Vinícius MoreiraandClaude Opus 5.5 07e165137f The crafter's whole-int test builds its crafter in one expression
clippy's field_reassign_with_default refused the field set after Default::default().

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:59:39 -03:00
Vinícius MoreiraandClaude Opus 5.5 cf0566a27d A leash knot or marker saves its flags as booleans
Entity.load reads NoGravity, Silent, Glowing and the other flags with
getBooleanOr and Entity.saveWithoutId writes each back as 1b only when
true. Horizon saved a leash knot's, a marker's or an eye of ender's raw
compound, keeping bytes like -1b and false flags; other_to_nbt now
normalizes them as the other entities' saves do.

Fixes #13853

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:59:38 -03:00
Vinícius MoreiraandClaude Opus 5.5 bdbf33939c A vex turns its gravity off every tick
Vex.tick calls setNoGravity(true) on every tick, AI or not, so a vex that
ticked once saves NoGravity: 1b. Horizon's vex flew through its own
travel without the flag and left it out of the save.

Fixes #13849

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:59:36 -03:00
Vinícius MoreiraandClaude Opus 5.5 d0314e8f25 A painting keeps its saved OnGround and fall_distance
Entity.load reads OnGround and fall_distance and Entity.saveWithoutId
writes them back. BlockAttachedEntity.tick never moves a painting nor runs
baseTick, so both stay what was loaded. painting_to_nbt wrote OnGround 0b
and fall_distance 0; it now writes the loaded values from the painting's
saved compound.

Fixes #14543

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:59:32 -03:00
Vinícius MoreiraandClaude Opus 5.5 03c750245c An end crystal keeps its saved OnGround and fall_distance
Entity.load reads OnGround and fall_distance and Entity.saveWithoutId
writes them back. EndCrystal.tick never moves the crystal nor runs
baseTick, so both stay what was loaded. Crystal::to_nbt wrote OnGround 0b
and fall_distance 0; it now writes the values from the crystal's loaded
compound.

Fixes #14671

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:59:31 -03:00
Vinícius MoreiraandClaude Opus 5.5 814e31a935 A crafter's triggered int round-trips at 5, -1 and 65537 too
The round trip at 1 passed with the old bool as well; values other than 1 come back
unchanged and untriggered, as vanilla saves and reads them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:57:01 -03:00
Vinícius MoreiraandClaude Opus 5.5 89b756de50 A crafter keeps its triggered int and triggers only at 1
CrafterBlockEntity keeps triggered as the int it read (containerData
slot 9), writes it back and is triggered only when it is 1. Horizon held
a bool read as != 0, so -1 or 5 became triggered and saved as 1. The
field is the raw int now, with is_triggered() for the bool.

Fixes #13851

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 21:57:01 -03:00
DUzzL c9544070f8 Merge remote-tracking branch 'upstream/main' into cf/14590 2026-11-11 00:26:48 +01:00
DUzzL 361923c262 Merge remote-tracking branch 'upstream/main' into cf/14590
# Conflicts:
#	crates/horizon-client/src/game/mob_landing_support_tests.rs
2026-11-11 00:26:25 +01:00
martipopsandClaude Opus 5.5 adbf42ffb9 Merge upstream main (#14379) into Pack Options on the settings shell
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 18:22:03 -05:00
Verm fadace66a0 A goat's horn flags are read as bytes (#14970)
Goat reads HasLeftHorn and HasRightHorn with getBooleanOr(key, true): a
number is true when its byte value is not 0, so an int 256 is a lost
horn. The loader tested the whole number; it now uses flag_or, as every
other boolean there does.
2026-11-10 19:33:20 +00:00
RLC248 7c384cd6ae Merge remote-tracking branch 'upstream/main' into fix/thrown-potion-level-entity 2026-11-10 19:31:50 +01:00
DetimesandClaude Opus 5.5 e61bf50d60 Merge upstream/main into perf-effect-meta
Brings the branch up to date and lays out the new code and tests as
rustfmt wants them, which the verify job checks.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 18:17:50 +00:00
Mayonesu0andClaude Sonnet 5.5 d1190a4dc7 A bare attribute name saves and applies as minecraft:'s; delivery harness covers tool and attribute_modifiers
Review of #14687.

Vanilla reads Attribute.CODEC and Identifier.CODEC with `minecraft:` as the
default namespace and writes them back whole, so `/item replace ... with
iron_pickaxe[attribute_modifiers=[{type:"attack_damage",id:"x",...}]]` saves
`minecraft:attack_damage` / `minecraft:x`. Horizon kept the strings as given:
the wire writer namespaced them, but the host passed the bare name to
`set_modifier_unclamped`, which skips an attribute it cannot find.

- `Items::attribute_modifiers` namespaces the stack's `type` and `id`, so the
  host applies what the client shows.
- The saved form (`item_to_nbt`) namespaces them as vanilla does.
- `test_builtin_component_delivery_parity.py`: a `tool` and an
  `attribute_modifiers` case (with bare names), run against the 26.3 server.
- Tests: a bare name on the host and across the wire, the saved form, and the
  writers' silent-drop path for a tool or modifier they cannot encode.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-10 19:10:54 +01:00
MSedgeMC b968ef5726 Keep entity_nbt.rs at its size: two-line write, no extra comment 2026-11-10 18:00:54 +00:00
MSedgeMC fce0b893f8 Merge remote-tracking branch 'upstream/main' into HEAD 2026-11-10 17:52:57 +00:00
DetimesandClaude Opus 5.5 bcb0d01d9e Test the effect particle cache against the uncached lookup
Every (effect, ambient) pair, known or not, gives the same particle
through the cache as through the plain lookup, and the second pass
over the same pairs makes no registry lookup at all.

Refs #14921

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 17:42:42 +00:00
DetimesandClaude Opus 5.5 6ece267eb9 Memoise effect particle lookups in the hub
effect_meta looked up the particle of every visible effect for every
placed guest on every tick: a linear search over the effect table, a
formatted name and a String-keyed registry lookup. The result depends
only on (effect, ambient), so the hub now keeps it per pair. Output is
unchanged. The function moves out of hub.rs into hub/effect_meta.rs,
which keeps hub.rs from growing.

Refs #14921

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 17:42:39 +00:00
Nikita Maximilian GrimmandClaude Fable 5.2 eb06abefe2 Shader API 0.2: the [entity] stage, checked and not yet drawn
A 0.2 pack lights block terrain and nothing else: mobs, chests, dropped
items and particles keep vanilla's lighting, and no stage lets a pack light
them. This adds the API for that stage, so packs can be written and checked
against it before the game draws it.

- `[entity]` in the manifest and `fn entity(input: EntityInput) -> Surface`:
  the texture, the tint apart from vanilla's shade, the hurt flash, the
  light, a normal, the position and what is drawn (`kind`). It returns the
  material stage's `Surface`, so one function can light both.
- Its resources are the material stage's shadow maps and coloured-light
  grid, at the same bindings, so one bind group can serve both. No block
  texture helpers, `reflection`, `opaque_*` or `set_surface`.
- The reference gives vanilla's own as the stage's function, read from
  `entity_color`: the flash is mixed in vanilla's gamma, before the light.
- `horizon-shader check` takes the stage with the material's limits and
  refuses a wrong signature or a constructed `EntityInput`. The game refuses
  a pack that has it until it draws the stage.

A pack without `[entity]` is unchanged and sees none of the stage's names:
every other stage's prelude and entries are the same text as before, held by
the names lists. 0.1 refuses the key.

Part of #14583 (step 1) and #12989.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-10 18:22:04 +01:00
[email protected]andClaude Sonnet 5.5 5fcd41ad3c Leave the recording's login sea level as it was
A recording is made on a remote connection, where the process-wide table
may still hold the sea level of a world opened earlier.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-10 18:00:36 +01:00
MSedgeMC 7fed2549d7 port_map: EditBox and MultiLineEditBox onClick double clicks 2026-11-10 17:00:33 +00:00
MSedgeMC 86cc476eff test: a double click in the chat box selects the word
Two clicks on the last letter of "hello world": the first places the caret
at the word's end, the second selects world, not the space before it.
2026-11-10 17:00:33 +00:00
MSedgeMC 65bce70f7a fix: double-clicking the chat box selects the word
EditBox.onClick selects the word under the pointer on a double click
(EditBox.selectWord: getWordPosition(-1)..getWordPosition(1)) and places the
caret otherwise; MouseHandler calls a click within 250 ms on the same screen a
double click. Horizon's chat input only ever placed the caret.
2026-11-10 17:00:33 +00:00
malithedeveloperandClaude Opus 5.5 c1b56cea13 Resource packs: a sprite alias never replaces a texture that is there
An alias written over an existing texture changed what every other reader
of that file sees: an unstitched or paletted sprite built from it, another
source's resource, anything that reads the texture as itself. Aliases now
only fill sprite paths that have no texture of their own, which is what
ItemsAdder and Nexo packs rename to; a rename over an existing texture
draws that texture, as before aliases. With that, vanilla's atlases never
list an alias's sprite, so they are no longer read for it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 19:57:46 +03:00
malithedeveloperandClaude Opus 5.5 fac0918973 Resource packs: a renamed sprite leaves a filtered .mcmeta out
A rename whose resource is vanilla's texture copied vanilla's `.mcmeta`
under the sprite even when a pack's filter hid that `.mcmeta`. Vanilla's
`createStackMetadataFinder` stops at a pack that filters the metadata, so
the alias now takes vanilla's `.mcmeta` only where no filter blocks it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 19:17:14 +03:00
Verm cfa85f016f Evoker fangs keep the fall_distance they were loaded with (#14847)
EvokerFangs extends Entity and never moves, so Entity.saveWithoutId
writes the fall_distance Entity.load read. Their save took Motion, the
pitch and OnGround from the loaded compound but wrote fall_distance 0.0;
it now takes that from the compound too.
2026-11-10 16:05:16 +00:00
DUzzL 615735e12c Keep shulkers that are not picked up out of the cart push fallback 2026-11-10 16:57:33 +01:00
SamB440 c46fd6f944 parity: Respond with acknowledgement packet when receiving PlayerRotation packet 2026-11-10 15:55:17 +00:00
[email protected]andClaude Sonnet 5.5 18bb5b3b1d Keep the files over 3000 lines from growing
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-10 16:31:11 +01:00
[email protected]andClaude Sonnet 5.5 dc3fe491e3 Sea level follows the level's generator
Fixes #14835

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-10 16:16:45 +01:00
malithedeveloperandClaude Opus 5.5 d1619f89b3 Resource packs: a renamed sprite keeps a later source's texture
The overlay gave every `single` rename's sprite its resource's file, even
when a later source of the atlas (a plain `single` or a `directory` of a
higher pack) listed that sprite from its own texture again. It now resolves
each atlas's whole source list in order with `atlas_sources::list`
(`SpriteSourceList.list`) over the textures the packs and vanilla leave
visible, and gives a sprite its resource's file only when that final
listing is the rename. Both atlases read the same file, so a sprite the
other atlas lists any other way keeps it. An atlas no pack provides is
vanilla's.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 18:09:48 +03:00
DUzzL 4068a09887 Keep an item frame's saved Motion, OnGround and fall_distance 2026-11-10 16:03:09 +01:00
tarzinio f291526b1f Sample LOD tiles again when Far detail changes 2026-11-10 14:25:13 +01:00
malithedeveloperandClaude Opus 5.5 09cfb0197c Resource packs: a renamed atlas sprite reads its resource's texture
A `single` atlas source with a `sprite` puts its resource's pixels under
another id (SingleFile.run). ItemsAdder and Nexo server packs name their
models' textures only through these renames ("ia:1199" for
minecraft:block/sea_lantern), and every loader reads a model's sprite
from textures/<sprite>.png, which those packs never ship: their models
drew the missing texture or nothing.

The overlay now gives each renamed sprite of the blocks and items
atlases its resource's file and .mcmeta, as SpriteResourceLoader reads
the resource's metadata. A rename over an existing texture replaces it
in the overlay only. Overlay cache version 9 rebuilds cached overlays.

Part of #14485.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 13:39:06 +03:00
MSedgeMC 868ff0f305 Read CannotHunt in the piglin helper and write it on one line
Keeps entity_nbt.rs, over the 3000-line limit, from growing by the read.
2026-11-10 09:31:09 +00:00
Riccardo GuerrieroandClaude Fable 5.2 e8578c2e47 Worldgen: choices sample a branch only where they read it
Vanilla's bulk range choice and interval select sample every branch over the
whole volume and then pick one value per position, and so did the port. In
the Overworld's final density that is the underground caves (cave layer,
cave cheese, 2D spaghetti) on the two thirds of a chunk's 5x49x5 lattice
above the stone, and four or five scales of each spaghetti noise where one
is read.

The noise samplers can already skip the Ys a caller does not read
(sample_needed, a bit per Y per column), but only the lerp asked. The range
choice now asks its out-of-range branch for the positions whose selector is
out of range, the interval select asks each branch for the positions that
select it, and lerp, unary and binary samplers pass a caller's mask on.

Every sampler is still called, in vanilla's order, and a cache still fills
its whole volume (its buffer is read by later scalar queries), so only noise
that nothing reads is skipped. A test spoils every value a noise was not
asked for and checks the result bit for bit against the choices spelled out
per value.

Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-10 09:59:38 +01:00
Skr1zzzzandClaude Opus 5.5 8c9c801232 Keep game/remote.rs from growing: the AddEntity projectile choice moves out
The new-or-reused id check and the choice between the two spawn paths move
into `tracks_remote_entity` and `spawn_added_projectile` in
remote_projectiles.rs, so the AddEntity handler calls one function and
remote.rs ends up shorter than on main (docs/layers.md#file-size).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 11:25:49 +03:00
Skr1zzzzandClaude Opus 5.5 1fd78941bd Client: spawning a falling block or TNT no longer walks the whole list
Each AddEntity made two passes over `falling` with thousands of blocks in
the air: `spawn_remote_projectile` first removed any entity under the same
id (ClientLevel.addEntity's removeEntity), and `remote_motion` then looked
the new block up from the front of the list, where it is last.

The handler now checks whether the id is already tracked before
`spawn_entity` tracks it. Only then are `falling` and `tnts` filtered for
it; the crystals and the small projectile lists are still filtered every
time, since the client can add to those itself. `remote_motion` and
`move_entity` search `falling` and `tnts` from the back.

8,000 falling blocks, 256 AddEntity packets (debug test build):
10.6 -> 0.9 ms.

Part of #13007

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 10:31:31 +03:00
Mayonesu0andClaude Opus 5.5 28584b59bf A stack's own tool and attribute modifiers reach the client and the hit
The server now sends a stack's minecraft:tool and
minecraft:attribute_modifiers (Tool.STREAM_CODEC,
ItemAttributeModifiers.STREAM_CODEC), and the client reads them back as
their codecs save them. Single player's client and LAN guests now predict
mining from the stack's tool and show its own modifiers in the tooltip.

Equipment modifiers (detectEquipmentUpdates, ItemStack.forEachModifier)
come from the stack's ATTRIBUTE_MODIFIERS, not the item type's, so
Player.attack's getAttributeValue(ATTACK_DAMAGE) honours them: +20
attack_damage on an iron pickaxe hits for 21.

Fixes #14641

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-10 05:25:59 +01:00
JustKarkat 6705307882 fix: don't deplete stacked contents when checking recipe craftability
Stacked::try_pick with output=None was a destructive check: it ran the
augmenting-path match and deducted matched items from self. Menu::place_recipe
called it as a pre-check before Menu::place, which then tried to pick again on
the already-depleted stacked contents. With exactly enough ingredients for one
craft (e.g. 3 sugar cane for paper), the second pick failed and nothing was
placed — no ghost, no items moved.

Make try_pick non-destructive when output is None (work on a clone). Only the
actual pick (output=Some) mutates self. This also fixes try_pick_all's binary
search, which called try_pick(mid, None) and depleted stacked before finding
the answer.
2026-11-09 20:56:36 -06:00
JustKarkat c6e670c7d0 fix: allow retry-clicking non-craftable recipes in the recipe book
Clicking a recipe whose ingredients are missing (e.g. paper without sugar
cane) showed the ghost once, but a second click did nothing because
try_place's last_placed guard blocked re-clicking any entry marked
non-craftable. Vanilla always shows the ghost for an uncraftable recipe,
so remove the retry guard. last_placed is still recorded for remote ghost
recipe handling.

Fixes #14616
2026-11-09 20:42:28 -06:00
MSedgeMC b0aeefebe9 port map: the CannotHunt row no longer claims it is unread 2026-11-10 00:55:20 +00:00
martipopsandClaude Opus 5.5 2f8540be63 Graphics: Horizon's own preset row is named Horizon Preset
The General page showed two rows named Preset: Horizon's own preset, which sets the
options below together, and vanilla's options.graphics.preset. Horizon's is now
Horizon Preset (a new en_us entry; other languages fall back to English until
translated), so the two read apart. The group keeps its name. The search finds both
for "preset", and Horizon's alone for "horizon preset"; the shell_choice_step case
looks for the new name.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:48:56 -05:00
RINNECODERandClaude Opus 5.5 7dcca26230 lang: keep the ru_ru check on the layered lookup, as main now adds strings in English first
A ru_ru.json completeness check failed on main's 95 English-only keys (docs/translations.md).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:14:07 -06:00
RINNECODER 1d8865acdf Merge main into #13831 2026-11-09 18:12:52 -06:00
MSedgeMC 47b8e5c51d Merge main: keep the guarded anger read beside CannotHunt 2026-11-10 00:03:41 +00:00
91e62194e8 Jukeboxes keep a finished song stopped after a reload and vibrate when a disc goes in or out
`JukeboxBlockEntity.loadAdditional` -> `JukeboxSongPlayer.setSongWithoutPlaying` brings a song
back only from a saved clock, only under its length, and never starts it (level event 1010 comes
from `play` alone): a record saved without a clock, or with one past its song's end, loads silent
at signal 0. `notifyItemChangedInJukebox` posts `BLOCK_CHANGE` for the block's `has_record` — and
`JukeboxPlayable.tryInsertIntoJukebox` posts a second one with the player as its source, against
the state the click found. `JukeboxBlock` decides both clicks by that state, not by the slot, and
`popOutTheItem` pops nothing from an empty slot.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

Claude-Session: https://claude.ai/code/session_01WZzq8MxShENtiMj2DMbm5G
2026-11-10 00:58:01 +01:00
DUzzL 9094309407 Let rideable minecarts pick up shulkers beside the rail 2026-11-10 00:48:39 +01:00
martipopsandClaude Opus 5.5 4888b73428 Merge upstream main (#13606) into Pack Options on the settings shell
Pack Options joins the shells pad_clicks_step resets, and its shell arms and
open_pack_options move to options_ui/shell_pages.rs, where main put shell and shell_mut.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:10:04 -05:00
DUzzL d6fb844de4 Load the 5x5 neighbourhood in the prepared-data test fixtures that tick entities
Entity ticking waits for every chunk within 2 columns (ChunkMap.prepareEntityTickingChunk), as of #13953. Add Game::load_ticking_neighbourhood for tests and call it from the fixtures of the 51 prepared-data tests that failed since, and correct the item escape test's drag to 0.98F widened to double.
2026-11-09 23:57:19 +01:00
81f336b814 Give the wither's nether star its ten-minute lifetime
WitherBoss.dropCustomDeathLoot spawns the star and then calls
ItemEntity.setExtendedLifetime, which sets age to -6000, so the
age >= 6000 discard takes it at tick 12000 instead of 6000. Horizon
spawned it like any other death drop, at age 0, and lost it after
five minutes.

Fixes #13937.

Co-Authored-By: DeepSeek V4.1 Flash <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

Claude-Session: https://claude.ai/code/session_01WZzq8MxShENtiMj2DMbm5G
2026-11-09 22:48:11 +01:00
voidsip d42af058e8 Preserve TNT transfer state without trusting saved NBT 2026-11-09 14:58:58 -06:00
voidsip b4b9d03ed5 Keep pending entity load context separate from saved NBT 2026-11-09 14:47:59 -06:00
martipopsandClaude Opus 5.5 467d045271 Pack Options on the settings shell
Pack Options (#11486) becomes a screen on the settings shell, as Shaders
is: each Polytone config section is a page, 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 keyboard and controller focus, Left/Right
stepping, the search (an entry's tooltip included), descriptions with
the performance-impact line in the strip, and Undo from a snapshot taken
when the screen opens. Leaving sends the pack's choices only when they
differ from that snapshot, so an Undo sends nothing.

options_ui's special cases for the page go, with Lines::titled and the
shell list's branch for it. foot_button takes the glyph room itself
rather than through a wrapper. A pad_menu_e2e case, pack_options, runs
the fixture pack through RB, Right, Undo, Left and B.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 15:25:04 -05:00
Horizon agent 2b3729188a Merge origin/main (brings #14090's test_git_slim fix) 2026-11-09 21:05:33 +01:00
AkirabaneandClaude Sonnet 5.5 45eb484b85 Particles: cull against the camera frustum pulled back 3 blocks, like vanilla
Vanilla tests every particle's point against the camera frustum moved back
3 blocks (ParticleEngine.extract, QuadParticleGroup, Frustum.pointInFrustum).
Horizon only did it behind the opt-in Particle Culling setting, so by default
ParticleEngine::render built a quad for every live particle.

Frustum::pulled_back moves the camera back along its view direction and
Frustum::contains_point is the point test. ParticleEngine::render_in_view
skips a particle outside that frustum before any sprite, light or quad work;
render_culled applies it too, whatever the setting says. render is unchanged.
game.rs passes the camera's frustum on the default path.

Written from the issue's description of the rule; there is no vanilla oracle.

Fixes #7255

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-09 20:33:25 +01:00
MSedgeMC 0e02985f36 fix: a piglin keeps the guarded anger its brain saved
`PiglinAi` sets `ANGRY_AT` with an expiry when a player breaks a guarded block
near a piglin, and `Brain.Packed` saves every memory with a codec under
`Brain.memories`: the value is the player's UUID and the TTL is the ticks left.
`LivingEntity.readAdditionalSaveData` reads that brain back.

Horizon wrote `minecraft:angry_at` in `mob_to_nbt` but `mob_from_nbt` never read
it: a piglin that a player had angered unloaded with its chunk and came back
with `extra.anger` 0 and no actor UUID, so it stopped attacking and the guarded
event was forgotten.

The load now reads the memory back: a four-int UUID into
`extra.piglin.guarded_angry_at` and the `ttl` into the existing `extra.anger`
counter, with no TTL read as the longest counter there is. The writer moves to
`mobs/piglin.rs` beside it, which also keeps `entity_nbt.rs` from growing.
2026-11-09 19:10:28 +00:00
MSedgeMC 89314c8f13 port_map: the piglin's CannotHunt flag is saved and read
`tools/port_map/game2-004.tsv` now answers `Piglin.addAdditionalSaveData`:
`CannotHunt` is written from the live flag, and `mob_from_nbt` reads it back.
2026-11-09 19:10:28 +00:00
MSedgeMC 0b2072a874 test: a saved CannotHunt reads and writes back
`mob_from_nbt`/`mob_to_nbt` are the pair `Game::load_mob` and `Game::mob_tree_nbt`
go through. `CannotHunt: 1b` loads `cannot_hunt` true and `can_hunt` false, and
the next save writes 1. `0b` and a missing key load false and save 0.

Without the read the flag stays false and the save writes 0: `left: false`,
`right: true` for the loaded flag.
2026-11-09 19:10:28 +00:00
MSedgeMC 8c28931f1d fix: a piglin keeps its saved CannotHunt flag
`Piglin.readAdditionalSaveData` reads `CannotHunt` with
`getBooleanOr("CannotHunt", false)` and `setCannotHunt`, and
`addAdditionalSaveData` always writes it. `AbstractPiglin.canHunt` is false
while the flag is set, and `PiglinAi` asks it before starting a hoglin hunt.

Horizon wrote a hardcoded `CannotHunt: 0` and never read the field, so a
piglin saved with the flag set hunted hoglins again after its chunk reloaded.
The flag now lives in `piglin::Memories`, the save writes it, the load reads
it, and the hunt goal checks `can_hunt`.
2026-11-09 19:10:28 +00:00
JoansitohandClaude Sonnet 5.5 31a4a5ea65 Resolve inline atlas sprites in their named atlas
AtlasGlyphProvider looks the sprite up in the atlas the component names;
the GUI atlas keeps its sprites under gui/sprites/, so boss_bar/*, widget/*,
server_list/* and icon/* drew nothing. Draw the missing sprite when absent.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-09 19:56:25 +01:00
Evrim CicekandClaude Opus 5.5 0dace8ff46 vehicle/mob fall clip: wait for the forced chunk's 2-column neighbourhood
Since #13953 an entity ticks only once every chunk within 2 columns is
loaded (ChunkMap.prepareEntityTickingChunk). Horizon has that
neighbourhood ready a few ticks after vanilla, so these groups, which
waited for the forced chunk alone, read vehicles and mobs that hadn't
moved yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 21:50:30 +03:00
Evrim Cicek 5054ffc2ab Merge branch 'refactor/minecarts-split' into fix/hanging-item-stack-config 2026-11-09 21:03:03 +03:00
MSedgeMC 96a7044c15 Merge remote-tracking branch 'upstream/main' into fix/block-entity-pos-from-tag 2026-11-09 18:00:54 +00:00
RLC248 182994edc8 A predicate's terms may be one holder alone or a tag
HolderSetCodec reads an all_of or any_of terms as a list of holders, one
holder alone (at .terms[0]) or a #tag. The dedicated server's startup check
now follows a lone holder like the list's first element, and refuses a world
whose terms names a predicate tag no pack defines (Unbound tags in registry).
The evaluation reads a lone holder too, so a lone any_of term is true when
its predicate is.

Part of #12711
2026-11-09 18:54:27 +01:00
Evrim Cicek 0a48f1eade Merge remote-tracking branch 'upstream/main' into fix/hanging-item-stack-config 2026-11-09 20:44:56 +03:00
MSedgeMC 9f51db9b40 port_map: BlockEntity.getPosFromTag is a port
The row said a block entity saved in the wrong chunk keeps its saved
x/z; `chunk::block_entity_pos` now moves it into the chunk that saved it,
so the row cites it.
2026-11-09 17:44:04 +00:00
MSedgeMC 301fc5fc05 test: a wrongly chunked block entity is read into its chunk
`chunk::block_entity_pos`'s test pins the arithmetic: (37, 70, -3) in
chunk (0, 0) is (5, 70, 13) after vanilla's `sectionRelative`, an
already-correct position is untouched, and another chunk moves its own
corner.

`a_block_entity_saved_under_another_chunks_coordinates_moves_here`
decodes a chunk whose `block_entities` list names x=37, z=-3 at chunk
(0, 0) and expects the chest at (5, 70, 13). Without the fix it stays at
(37, 70, -3).
2026-11-09 17:44:04 +00:00
MSedgeMC 74db568335 fix: a block entity saved in another chunk moves into the chunk that holds it
`BlockEntity.getPosFromTag` reads the tag's `x`, `y`, `z`, and when they
name another chunk it warns and keeps only the low four bits of `x` and
`z`, so the entity stays in the chunk whose save wrote it. Horizon's
`decode_block_entity` returned the saved coordinates as they were, so a
block entity saved under the wrong chunk's coordinates landed at a
position that chunk may not even hold, instead of where vanilla puts it.

`chunk::block_entity_pos` does the clamp, and the chunk decoder uses it
for every block entity it reads. No line growth in `save.rs` (the size
gate's 3000-line rule).
2026-11-09 17:44:04 +00:00
RLC248 f64da572af A thrown potion or bottle is a level entity
A splash or lingering potion or experience bottle that a player throws
or a dispenser shoots went into a side list that is not part of the
level, so @e, /data get entity, /execute if entity and /kill never found
it. Vanilla adds it with level.addFreshEntity like any entity.

Throws and dispensers now make the same level projectile /summon does
(ProjectileKind::Potion / ExperienceBottle); the player's throw uses
Projectile.shoot_from_rotation (#13201).
2026-11-09 18:22:49 +01:00
Horizon agentandClaude Opus 5.5 fe0a4d80bf Mouse Tweaks: rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:22:34 +01:00
Horizon agentandClaude Opus 5.5 adc454cfc9 Mouse Tweaks and sorting move to game/extras/, one module each (layer plan M5)
A pure move: game/tweaks.rs becomes game/extras/mouse_tweaks.rs, and
the sort buttons and key leave it for game/extras/sorting.rs. Paths,
visibility (pub(in crate::game)) and imports only; game.rs loses its
mod line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:19:15 +01:00
Horizon agent 2cdecbf069 Merge remote-tracking branch 'origin/pr-13893' into layers/extras-tweaks 2026-11-09 18:19:15 +01:00
Evrim Cicek 72dff2d5b7 Merge branch 'refactor/entity-nbt-hanging' into fix/hanging-item-stack-config 2026-11-09 19:24:22 +03:00
Evrim Cicek 194a86eff3 Merge branch 'refactor/entity-nbt-hanging' into fix/hanging-item-stack-config
# Conflicts:
#	crates/horizon-client/src/entity_nbt.rs
2026-11-09 19:24:21 +03:00
Horizon agentandClaude Opus 5.5 321b0c5a98 Lang: the dead-key check reads every crate's sources
A sentence key is alive when any crate names it: the layer split is moving
client code into crates of its own, and the strings move with it. The
horizon. key check keeps the four client crates.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:50:26 +01:00
Horizon agentandClaude Opus 5.5 3089267e7c Dolphin treasure: read the found position without moving it
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:50:01 +01:00
Horizon agentandClaude Opus 5.5 721d5c6fda Merge origin/main
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:50:00 +01:00
Horizon agentandClaude Opus 5.5 895726d381 rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:39:41 +01:00
Horizon agentandClaude Opus 5.5 1f96d244f9 Read a sprite's .mcmeta up to its first value, as vanilla does
ResourceMetadata.fromJsonStream reads one JSON value with Gson and never looks
past it, so packs leave notes after the closing brace. CozyUI+'s highlighted
button ends its .mcmeta with `//` lines: Horizon's strict serde_json read
rejected the file, so the sprite lost its nine slice and animation and drew
as its whole 16-frame strip (#3046).

The nine-slice, GUI animation, texture-flag and atlas sprite readers now share
packs::first_json with pack.mcmeta's reader.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:22:17 +01:00
Horizon agentandClaude Opus 5.5 27979c816b Feeding particles: tadpole slime ball, panda love hearts, dolphin treasure
- Tadpole.feed draws its happy_villager particle on the client too; a tadpole
  is never isBaby, so the client's feed prediction skipped it (#8554).
- Panda.mobInteract's setInLove broadcasts entity event 18, the love hearts
  (#8555).
- DolphinSwimToTreasureGoal.start broadcasts entity event 38 once it finds a
  treasure, and Dolphin.mobInteract answers a #minecraft:fishes item with
  SUCCESS on the client, so the hand swings and the fish isn't eaten (#8567).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:16:35 +01:00
Evrim Cicek 0a11f464a3 Merge remote-tracking branch 'upstream/main' into fix/hanging-item-stack-config
# Conflicts:
#	crates/horizon-client/src/entity_nbt.rs
#	crates/horizon-client/src/game/dispenser.rs
2026-11-09 16:42:23 +03:00
RINNECODERandClaude Opus 5.5 b7bb1d0c53 Game translations: drop 8 keys no code asks for, and check en_us against the code
A sentence key is the English text itself, so rewording a setting's text left
the old sentence, and its translations, in all 87 lang files. Eight of them
are no longer named anywhere in the code: the five old descriptions #13802
lists (FOV, HDR output, view bobbing, the two entity culling modes) and three
nits labels. They are removed from every file.

every_sentence_key_in_en_us_is_one_the_code_names fails on a sentence key
that no client crate names as a string literal, so the next rewording can't
leave one behind. The source walk it shares with
every_horizon_key_the_code_names_is_in_en_us now also reads
horizon-client-input, which asks for the gamepad's "Hotbar: Next Slot".

bundled_horizon_strings_follow_the_language checked ru_ru through
Language::load, whose en_us layer fills every gap, so it could not fail. It
now reads ru_ru.json's own keys.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 05:30:49 -06:00
FryedCheese b4733ffec0 Merge branch 'horizon-rust:main' into main 2026-11-08 23:19:56 +13:00
FryedCheese 1b8e661146 Merge pull request #1 from Web-mc1/studio-screen-bridge
Add Screen::Studio so script windows stop borrowing the chat slot
2026-11-08 21:09:44 +13:00
Web-mc1 95b6b28fcb Add Screen::Studio so Studio windows don't borrow the chat slot 2026-11-08 20:52:29 +13:00
Evrim Cicek 2f07a64084 Merge remote-tracking branch 'upstream/main' into fix/hanging-item-stack-config
# Conflicts:
#	tools/command_exec_corpus.py
2026-11-08 02:38:03 +03:00
Horizon agentandClaude Opus 5.5 bb6e18b94d Merge origin/main into #11261 (main builds again after #11767)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 14:10:29 +01:00
Horizon agentandClaude Opus 5.5 b28069d08e rustfmt spawner.rs (verify's fmt step failed on this hunk)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 14:00:50 +01:00
Horizon agentandClaude Opus 5.5 2f4a142e8b Merge origin/main into #11261 (keep both command_exec corpus groups)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 14:00:39 +01:00
Horizon agentandClaude Opus 5.5 83df38c895 Drop an unreachable return after components()
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-07 09:44:10 +01:00
Evrim Cicek d70f2fdb20 Merge upstream/main: build on #11268's stack config; the item's name loads too
Upstream #11268 configures a placed frame, painting or armor stand through
stack_configured_entity. Keep its placement code, add the item's custom name
there (a painting took none, an armor stand's lost its style), and route
apply_item_stack_config through the same helper.
2026-11-07 02:40:03 +03:00
Evrim CicekandClaude Opus 5.5 d8a86b2454 Dispensed armor stand config, block_pos range, unreadable painting variant
ArmorStandDispenseItemBehavior applies the same stack config with no user
after the dispenser's yaw. BlockAttachedEntity.readAdditionalSaveData keeps
the Pos block for a block_pos 16 blocks or more away, and a painting with an
unreadable variant still loads the rest of its data.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:44:48 +03:00
Evrim CicekandClaude Opus 5.5 d4cfdeab5c A placed painting, item frame or armor stand takes its item's stack config
HangingEntityItem.useOn and ArmorStandItem.useOn apply
EntityType.createDefaultStackConfig: the item's custom name and custom data,
then minecraft:entity_data merged over the entity. The hanging entity's
survives() runs on the configured entity; the stand turns to the player's
yaw, pitch 0, afterwards. The vehicle helper becomes apply_item_stack_config,
and /data merge entity now loads a painting (facing, block, known variant).

Fixes #11242

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-06 19:32:10 +03:00
378 changed files with 11558 additions and 3775 deletions

No files matched your search

+3 -2
View File
@@ -2,8 +2,9 @@
## What and why
<!-- 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". -->
<!-- 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". -->
## Kind
+4 -3
View File
@@ -34,8 +34,9 @@ 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). 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 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
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
@@ -214,7 +215,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`, `tweaks.rs`, `options.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` |
## How `Game` is organised
+5 -2
View File
@@ -144,7 +144,9 @@ 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).
[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.
- **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
@@ -169,7 +171,8 @@ How agents, checks, releases and signed updates keep this safe: [security](docs/
### Large pull requests
500 lines stays the default. A pull request that can't be split below it starts from a spec:
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:
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
+1 -2
View File
@@ -1505,7 +1505,6 @@ dependencies = [
"bytemuck",
"chrono",
"crc32fast",
"dunce",
"flate2",
"fs4",
"gilrs",
@@ -1547,7 +1546,6 @@ dependencies = [
"objc2 0.6.5",
"objc2-app-kit 0.3.2",
"objc2-foundation 0.3.2",
"open",
"png",
"pollster",
"rustix 1.1.5",
@@ -1591,6 +1589,7 @@ dependencies = [
"bytemuck",
"chrono",
"crc32fast",
"dunce",
"flate2",
"fs4",
"getrandom 0.3.4",
+2
View File
@@ -62,6 +62,8 @@ 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
+33 -1
View File
@@ -206,7 +206,7 @@ impl Config {
Ok(file.anticheat)
}
/// Thresholds can't be negative.
/// Thresholds can't be negative, and neither can the timer's milliseconds.
pub fn check(&self) -> Result<(), String> {
for &c in Check::ALL {
let a = self.actions(c);
@@ -220,6 +220,18 @@ 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());
@@ -361,6 +373,26 @@ 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();
+25 -1
View File
@@ -45,6 +45,11 @@ 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;
@@ -53,12 +58,31 @@ mod tests {
owed += per_tick;
while owed >= 1.0 {
owed -= 1.0;
flags += usize::from(b.tick_end(20.0, &c).is_some());
flags += usize::from(b.tick_end(rate, &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();
+65 -16
View File
@@ -952,8 +952,16 @@ mod tests {
(en, seen)
}
#[test]
fn every_horizon_key_the_code_names_is_in_en_us() {
/// 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> {
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();
@@ -964,27 +972,68 @@ 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 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);
}
let mut krates = CLIENT_CRATES.to_vec();
// 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);
let lang_dirs = crate_lang_dirs();
for (name, dir) in &lang_dirs {
en.extend(english(dir));
krates.push(name);
}
assert!(files.len() > 100, "found only {} sources", files.len());
let mut found = 0;
for file in files {
for file in crate_sources(&krates) {
let text = std::fs::read_to_string(&file).unwrap();
for (at, _) in text.match_indices("\"horizon.") {
let rest = &text[at + 1..];
+2
View File
@@ -93,6 +93,8 @@ 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).
@@ -1442,6 +1442,8 @@ 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) => {
+13 -1
View File
@@ -1279,6 +1279,9 @@ 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 {
@@ -1401,6 +1404,7 @@ impl ChatScreen {
auto_suggestions: true,
abilities,
layout: SuggestLayout::CHAT,
last_click: None,
};
s.update_command_info(m, c);
s
@@ -1439,6 +1443,7 @@ impl ChatScreen {
auto_suggestions: true,
abilities: ChatAbilities::new(ChatVisibility::Full),
layout: SuggestLayout::COMMAND_BLOCK,
last_click: None,
};
s.update_command_info(m, c);
s
@@ -1966,8 +1971,15 @@ 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);
self.input.click(m, x, false, double);
return true;
}
false
@@ -305,6 +305,31 @@ 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};
@@ -413,12 +413,20 @@ pub enum NameOrId {
pub struct Crafter {
pub items: [Option<ItemStack>; 9],
pub disabled: [bool; 9],
pub triggered: bool,
/// `containerData` slot 9 as saved (`triggered`): any int, triggered
/// only at 1 ([`Crafter::is_triggered`]).
pub triggered: i32,
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>,
@@ -465,6 +473,9 @@ 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,10 +291,15 @@ impl SceneCollisions<'_, '_> {
}
fn context(&self, bounds: Aabb) -> CollisionContext<'static> {
let y = bounds.min_position().y;
if !self
.subject
.is_some_and(|s| s.lava_walker || s.leather_boots)
{
// 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
}) {
return CollisionContext::position(y);
}
CollisionContext::for_entity(
@@ -3,7 +3,8 @@
//! - 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.
//! initializer gives;
//! - an array declared with a `const int`'s size takes the constant's expression.
/// The longest shader rewritten (vanilla's, includes expanded, are a few KiB).
const MAX_LEN: usize = 64 * 1024;
@@ -17,7 +18,115 @@ pub(super) fn fixups(text: &str) -> String {
if text.len() > MAX_LEN {
return text.to_owned();
}
size_unsized_arrays(&specialize_sampler_params(text))
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"))
}
fn is_ident(c: char) -> bool {
@@ -245,6 +245,72 @@ 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\
+3 -177
View File
@@ -210,6 +210,7 @@ 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;
@@ -12351,133 +12352,6 @@ 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();
@@ -12583,56 +12457,8 @@ fn block_entities_within_reach<'a>(
})
.flatten()
}
/// 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
})
}
}
mod view_frustum;
pub use view_frustum::Frustum;
/// 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.
@@ -0,0 +1,132 @@
//! 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
}
}
}
@@ -0,0 +1,252 @@
//! 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));
}
}
}
+12 -35
View File
@@ -90,6 +90,8 @@ 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,
@@ -98,7 +100,8 @@ pub enum Preset {
Custom,
}
impl Preset {
pub const ALL: [Preset; 5] = [
pub const ALL: [Preset; 6] = [
Preset::FullPerformance,
Preset::Performance,
Preset::Balanced,
Preset::Quality,
@@ -107,6 +110,7 @@ impl Preset {
];
pub fn name(self) -> &'static str {
match self {
Preset::FullPerformance => "full_performance",
Preset::Performance => "performance",
Preset::Balanced => "balanced",
Preset::Quality => "quality",
@@ -116,6 +120,7 @@ impl Preset {
}
pub fn label(self) -> &'static str {
match self {
Preset::FullPerformance => "Full Performance",
Preset::Performance => "Performance",
Preset::Balanced => "Balanced",
Preset::Quality => "Quality",
@@ -773,9 +778,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 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`).
/// 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`).
pub gpu_culling: GpuCullingMode,
/// Skip drawing entities hidden behind opaque terrain, synchronously or asynchronously.
pub entity_culling: EntityCullingMode,
@@ -1280,37 +1285,9 @@ impl Graphics {
}
}
/// 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;
}
#[path = "graphics_preset.rs"]
mod preset;
pub use preset::apply_preset;
#[cfg(test)]
mod tests {
@@ -0,0 +1,169 @@
//! 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;
}
+32 -28
View File
@@ -853,7 +853,7 @@ impl H {
fn label(self, s: &Settings, out: &EffectiveOutput) -> Text {
let g = &s.horizon;
match self {
H::Preset => labelled("Preset", g.preset.label()),
H::Preset => labelled("Horizon Preset", g.preset.label()),
H::LodDistance => match g.lod_distance {
0 => labelled("LOD Distance", "Off"),
n => labelled("LOD Distance", lang::tr("%s chunks", &[&n])),
@@ -1296,7 +1296,6 @@ impl Item {
| H::GraphicsApi
| H::TranslucentBatching
| H::HdrSmoothGradients
| H::GpuCulling
)
| Item::Vanilla(
Opt::GuiScale
@@ -1753,6 +1752,14 @@ 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));
@@ -2225,9 +2232,18 @@ 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.clouds, "false");
assert_eq!(s.horizon.resolution_scale, 100);
assert!(!s.horizon.opaque_ice && s.horizon.cache_chests);
// Any quality change leaves the preset.
Item::Vanilla(Opt::Clouds).cycle(&mut s, false, [854, 480], &NONE);
assert_eq!(s.horizon.preset, Preset::Custom);
@@ -2235,6 +2251,14 @@ 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]
@@ -2249,7 +2273,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::Performance);
assert_eq!(s.horizon.preset, Preset::FullPerformance);
}
#[test]
@@ -2297,14 +2321,6 @@ 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 [
@@ -2333,10 +2349,6 @@ 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
@@ -2530,8 +2542,8 @@ mod tests {
}
}
/// 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.
/// 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.
#[test]
fn gpu_culling_steps_off_on_auto_where_it_is_offered() {
use crate::graphics::GpuCullingOffer;
@@ -2570,7 +2582,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 keeps the preset.
// Where it is, it steps through its three values and leaves the preset.
crate::graphics::offer_gpu_culling(GpuCullingOffer::Offered);
assert_eq!(item.blocked(&s, &NONE), None);
for label in ["Auto", "Off", "On"] {
@@ -2586,18 +2598,10 @@ mod tests {
}
item.cycle(&mut s, true, FB, &NONE);
assert_eq!(s.horizon.gpu_culling, GpuCullingMode::Off);
assert_eq!(s.horizon.preset, Preset::Balanced);
assert_eq!(s.horizon.preset, Preset::Custom);
// 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]
+31 -5
View File
@@ -16,6 +16,7 @@ use model_reducing::reducible_model_sprites;
mod animate;
pub mod cit_glint;
mod gui_sprite;
mod model_reducing;
mod pack_text;
pub mod pictures;
@@ -55,7 +56,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 = crate::packs::first_json(json.as_bytes())?;
let meta: serde_json::Value = crate::packs::first_json(json.as_bytes()).ok()?;
let section = meta.get("texture")?;
let flag = |key| section.get(key).and_then(serde_json::Value::as_bool) == Some(true);
let flags = Self {
@@ -388,7 +389,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 = crate::packs::first_json(mcmeta?.as_bytes())?;
let meta: serde_json::Value = crate::packs::first_json(mcmeta?.as_bytes()).ok()?;
AnimationMetadata::from_json(&meta.get("animation")?.to_string()).ok()
}
/// An animated strip's first frame: the region the mcmeta's frame size picks
@@ -2466,9 +2467,8 @@ impl HudBatch {
);
}
}
InlineObject::Atlas { sprite, .. } => {
let key = sprite.strip_prefix("minecraft:").unwrap_or(sprite);
if let Some(rect) = atlas.sprites.get(key).copied() {
InlineObject::Atlas { .. } => {
if let Some(rect) = atlas.inline_object_sprite(object) {
self.rect_uv(x, y, 8.0, 8.0, rect, tint);
}
}
@@ -3773,6 +3773,32 @@ 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");
@@ -0,0 +1,41 @@
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,14 +39,13 @@ pub fn text_with_backdrop(
background: u32,
) {
if background != 0 {
// 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.
// GuiGraphicsExtractor.textWithBackdrop adds two pixels around the
// text's advance and the font's nine-pixel line height.
out.push(fill(
x - 1,
y - 1,
x + w,
y + 9,
x - 2,
y - 2,
x + w + 2,
y + 11,
multiply(background, color),
));
}
@@ -1491,10 +1490,10 @@ mod boss_bar_room_tests {
mod backdrop_tests {
use super::*;
/// `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.
/// `GuiGraphicsExtractor.textWithBackdrop`: two pixels around the advance
/// and the nine-pixel font line, independently of glyph-background drawing.
#[test]
fn the_backdrop_frames_the_glyphs_by_one_pixel() {
fn the_backdrop_frames_the_text_by_two_pixels() {
let mut out = Vec::new();
text_with_backdrop(
&mut out,
@@ -1508,6 +1507,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), (9, 19, 16, 29));
assert_eq!((*x0, *y0, *x1, *y1), (8, 18, 18, 31));
}
}
+31 -7
View File
@@ -9,6 +9,7 @@ use crate::{
};
pub mod bake;
pub mod cache;
mod detail;
mod kept;
mod mesh;
pub mod packed;
@@ -2387,13 +2388,6 @@ 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
}
@@ -6115,4 +6109,34 @@ 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"
);
}
}
}
@@ -0,0 +1,23 @@
//! 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);
}
}
+34 -46
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>,
/// 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,
/// 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>,
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,10 +3401,6 @@ 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) {
@@ -3786,20 +3782,6 @@ 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 {
@@ -3829,14 +3811,7 @@ impl OptionsUi {
crate::pack_screen::Action::BrowsePick(i) => {
events.push(Event::DownloadPack(i));
}
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::Options(id) => self.open_pack_options(&id),
crate::pack_screen::Action::None => {}
}
return events;
@@ -4074,7 +4049,6 @@ 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 {
@@ -4168,10 +4142,6 @@ 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 {
@@ -4255,10 +4225,6 @@ 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)
@@ -4393,14 +4359,8 @@ impl OptionsUi {
self.can_change_value = false;
match page {
Page::PackOptions => {
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(),
});
}
let screen = std::mem::take(&mut self.pack_options.screen);
events.extend(screen.finished());
}
Page::ShaderOptions | Page::ShaderPacks => {
if s.shader_options.as_ref().is_some_and(|o| o.changed) {
@@ -4960,6 +4920,34 @@ 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,6 +23,7 @@ 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,
}
}
@@ -35,9 +36,20 @@ 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]> {
@@ -53,13 +65,14 @@ impl OptionsUi {
return;
}
// Every shell: the click may have changed the page.
let shells: [&mut dyn shell::Hosted; 6] = [
let shells: [&mut dyn shell::Hosted; 7] = [
&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,45 +1,36 @@
//! 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;
//! 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.
use crate::{
graphics_style as style,
hud::{HudAtlas, HudBatch},
lang,
settings_shell::{self as shell, Columns, Line, Lines},
text::Text,
ui,
settings::Settings,
settings_shell::{self as shell, Group, Output, Row, Sheet, Value},
};
use horizon_polytone::pack::{ConfigKind, ConfigValue, Configs};
/// What a click asks of the options screen.
/// A row: the pack-wide presets, Reset all, or the entry at an index of `ids`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Action {
ButtonClick,
SliderDrag,
/// Done: leave, keeping what changed.
Done,
pub(crate) enum Item {
Presets,
ResetAll,
Entry(u16),
}
/// 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;
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;
/// A translation, or `fallback` where no language has the key.
fn translated(key: &str, fallback: impl FnOnce() -> String) -> String {
@@ -65,9 +56,34 @@ fn readable(path: &str) -> String {
.unwrap_or_default()
}
impl PackOptionsUi {
/// The page opens on `configs`, the selected packs' entries with the player's values.
pub fn open(configs: Configs) -> Self {
/// 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 {
let mut ids: Vec<(String, Option<String>, i64)> = configs
.entries()
.iter()
@@ -96,25 +112,21 @@ impl PackOptionsUi {
(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(),
..Self::default()
revision: 0,
}
}
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)
/// 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(),
})
}
/// The namespace the presets' translations are under: of the first entry with presets.
@@ -166,21 +178,14 @@ impl PackOptionsUi {
None if back => n - 1,
None => 0,
};
let before = self.configs.clone();
self.configs.apply_preset(&presets[next]);
if self.configs != before {
self.changed = true;
}
self.revision += 1;
}
/// 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();
/// 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");
};
let Some(id) = id else {
return lang::get("horizon.pack.options.general");
@@ -192,367 +197,218 @@ impl PackOptionsUi {
translated(&format!("config.{namespace}.section.{id}"), || readable(id))
}
/// 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();
};
/// The tooltip (`config.<namespace>.<name>.tooltip`) and the performance line after it.
fn description(&self, id: &str) -> String {
let (namespace, path) = split(id);
let key = format!("config.{namespace}.{path}.tooltip");
let mut text = if lang::has(&key) {
let tooltip = if lang::has(&key) {
lang::get(&key)
} else {
String::new()
};
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,
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,
}
}
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);
/// 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)),
}
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);
}
let label = Text::literal(lang::get(key));
shell::foot_button(batch, atlas, rect, &label, cursor, (false, 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)))
}
/// 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();
/// 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)),
);
}
if cols.scrolls()
&& self
.scroll
.press((x, y), cols.bar_x(), cols.top, cols.bottom, content)
{
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 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);
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)));
}
self.revision += 1;
}
/// 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);
}
}
}
/// The pointer lets go.
pub fn release(&mut self) {
self.scroll.release();
self.dragging = None;
impl shell::Screen for PackOptionsScreen {
type Page = u16;
type Row = Item;
fn title(&self) -> &'static str {
TITLE
}
/// 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);
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)
}
}
#[cfg(test)]
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);
}
}
mod tests;
@@ -0,0 +1,281 @@
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);
self.search.click(m, x, false, 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);
self.browser_search.click(m, x, false, false);
self.browser_focus = true;
return Some(Action::None);
}
+232 -16
View File
@@ -468,17 +468,20 @@ 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)
first_json(bytes).ok()
}
/// 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))
/// 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)
.into_iter()
.next()?
.ok()
.next()
{
Some(value) => value,
None => Err(serde::de::Error::custom("empty metadata")),
}
}
/// 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.
@@ -827,13 +830,6 @@ 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| {
@@ -882,6 +878,21 @@ 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)]
@@ -1032,6 +1043,123 @@ 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.
@@ -1906,6 +2034,94 @@ 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,7 +13,8 @@ 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).
const VERSION: u32 = 8;
// Version 8 left an atlas `single` source's renamed sprite without its texture file (#14485).
const VERSION: u32 = 9;
#[derive(Default, Serialize, Deserialize)]
pub(super) struct Dependencies {
+119 -105
View File
@@ -1402,100 +1402,8 @@ impl ParticleLightCache {
}
}
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])
}
mod view_cull;
use view_cull::{PARTICLE_FRUSTUM_OFFSET, ParticleSectionFrustumCache, SectionFrustumResult};
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);
@@ -4703,16 +4611,7 @@ impl ParticleEngine {
light_at: &dyn Fn([i32; 3]) -> u8,
out: &mut Vec<Vertex>,
) {
self.render_inner::<false>(
camera,
base,
partial,
0.0,
None,
&mut |_, _| false,
light_at,
out,
);
self.render_in_view(camera, base, partial, None, light_at, out);
}
/// Render particles after rejecting view-frustum misses and any particles
@@ -4730,7 +4629,7 @@ impl ParticleEngine {
out: &mut Vec<Vertex>,
) {
if !culling_enabled {
self.render(camera, base, partial, light_at, out);
self.render_in_view(camera, base, partial, frustum, light_at, out);
return;
}
self.render_inner::<true>(
@@ -4761,10 +4660,16 @@ 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
@@ -5199,6 +5104,115 @@ 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());
@@ -0,0 +1,138 @@
//! 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,11 +864,21 @@ impl TextField {
self.set_highlight(m, pos);
}
/// `onClick`: the cursor where the mouse is (`findClickedPositionInText`).
pub fn click(&mut self, m: &Measure, x: f64, extend: bool) {
/// `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) {
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);
self.move_cursor_to(m, at, extend);
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);
}
}
pub fn contains(&self, x: f64, y: f64) -> bool {
x >= self.x as f64
@@ -222,11 +222,6 @@ 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))
@@ -352,8 +347,7 @@ 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, and a group without a name of its own
/// (`Lines::titled`), in the player's language.
/// draws a setting at its `y`; `page_name` names a page, in the player's language.
pub(crate) fn list<P: Copy, S: Copy>(
batch: &mut HudBatch,
atlas: &HudAtlas,
@@ -386,7 +380,6 @@ 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),
};
@@ -952,22 +945,10 @@ pub(crate) fn dock_note(
}
}
/// Done or Undo at the foot of the page list.
/// 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.
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],
@@ -2414,7 +2395,7 @@ impl<S: Screen + Default> Hosted for Shell<S> {
}
None => 0.0,
};
foot_button_with_room(batch, atlas, rect, &label, cursor, flags, room);
foot_button(batch, atlas, rect, &label, cursor, flags, room);
}
}
fn click(
+11 -17
View File
@@ -93,18 +93,17 @@ pub fn unpack(value: &str, signature: Signature, valid_uris: &[impl AsRef<str>])
signed: signature == Signature::Signed,
..empty.clone()
};
// 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.
// Authlib's MinecraftServicesSessionService validates every URL in
// unpackTextures before returning any textures. A bad cape rejects the skin too.
for (kind, texture) in textures {
let Some(url) = texture.get("url").and_then(|u| u.as_str()) else {
continue;
return empty;
};
let allowed = valid_uris
.iter()
.any(|u| url.starts_with(&u.as_ref().replace("{textureId}", "")));
if !allowed {
continue;
return empty;
}
if kind == "SKIN" {
out.slim = texture
@@ -1388,10 +1387,9 @@ mod tests {
&super::TEXTURE_URIS,
);
assert_eq!(textures.slim, slim && !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());
// 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"));
assert_eq!(parsed.skin.is_some(), !url.contains("evil"));
assert!(std::sync::Arc::ptr_eq(&parsed, &cache.get(&profile)));
}
@@ -1544,18 +1542,14 @@ mod tests {
assert!(t.slim);
assert!(!unpack(wide, Signature::Signed, &TEXTURE_URIS).slim);
}
/// `unpack` keeps each texture independently: a cape from another origin
/// must not drop the skin.
/// Authlib's `MinecraftServicesSessionService` rejects the whole profile in
/// `unpackTextures` when any texture URL is outside the allowed origins.
#[test]
fn unpack_keeps_the_skin_when_another_texture_is_rejected() {
fn unpack_rejects_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.skin.as_deref(),
Some("https://textures.minecraft.net/texture/skin1")
);
assert_eq!(t.cape, None);
assert_eq!(t, super::Textures::default());
}
#[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(serde_json::from_str::<
Ok(text) => Some(crate::packs::first_json::<
BTreeMap<String, Box<serde_json::value::RawValue>>,
>(&text)?),
>(text.as_bytes())?),
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(serde_json::from_str::<
Ok(text) => Some(crate::packs::first_json::<
BTreeMap<String, Box<serde_json::value::RawValue>>,
>(&text)?),
>(text.as_bytes())?),
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.loaded_entities.push(((chunk.x, chunk.z), entities));
world.queue_entity_nbt((chunk.x, chunk.z), entities);
}
self.generated_total += 1;
// A chunk saved with its light needs no light job; its unlit
+23 -1
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) = serde_json::from_str(&text)
let Some(nine_slice) = crate::packs::first_json(text.as_bytes())
.ok()
.as_ref()
.and_then(parse_nine_slice)
@@ -2025,6 +2025,28 @@ 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
+10 -1
View File
@@ -9,6 +9,9 @@ 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;
@@ -81,7 +84,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<horizon_world::nbt::Tag>)>,
pub loaded_entities: Vec<((i32, i32), Vec<PendingEntity>)>,
/// 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`).
@@ -215,6 +218,12 @@ 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,
@@ -0,0 +1,89 @@
//! 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,10 +93,6 @@ 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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "يظهر عندما ينقذ العالم.",
@@ -556,7 +553,6 @@
"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.": "إعادة استخدام الصناديق المستقرة؛ تبقى حركة الغطاء متحركة.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Донъя ҡотҡарғанда күрһәтә.",
@@ -556,7 +553,6 @@
"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.": "Ҡабаттан ҡуллана урынлаштырылған йәшниктәр; ҡапҡас хәрәкәте йәнле ҡала.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Паказвае, калі свет ратуе.",
@@ -556,7 +553,6 @@
"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.": "Паўторна выкарыстоўвае адстойнікі; рух вечка застаецца ажыўленым.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Показва кога светът спасява.",
@@ -556,7 +553,6 @@
"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.": "Повторно използване на утаени кутии; движението на капака остава анимирано.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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ý.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Тӗнче хӑҫан ҫӑлӑннине кӑтартать.",
@@ -556,7 +553,6 @@
"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.": "Ҫирӗплетнӗ ещӗксемпе тепӗр хут усӑ курать; хупӑлча хусканӑвӗ чӗрӗ юлать.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,10 +415,6 @@
"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",
@@ -432,7 +428,6 @@
"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.",
@@ -466,13 +461,11 @@
"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.",
@@ -570,7 +563,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Δείχνει όταν ο κόσμος σώζει.",
@@ -556,7 +553,6 @@
"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.": "Επαναχρησιμοποιεί τα καθιζημένα κουτιά. Η κίνηση του καπακιού παραμένει κινούμενη.",
@@ -620,10 +616,6 @@
"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 όχλοι",
@@ -316,6 +316,7 @@
"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",
@@ -354,6 +355,7 @@
"Unlimited": "Unlimited",
"Auto": "Auto",
"Custom": "Custom",
"Full Performance": "Full Performance",
"Performance": "Performance",
"Balanced": "Balanced",
"Quality": "Quality",
@@ -401,7 +403,6 @@
"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.",
@@ -442,13 +443,11 @@
"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.",
@@ -663,7 +662,6 @@
"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.",
@@ -707,6 +705,9 @@
"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.",
@@ -745,10 +746,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -638,10 +634,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "زمانی نشان می دهد که جهان نجات می دهد.",
@@ -556,7 +553,6 @@
"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.": "از جعبه های ته نشین شده مجدد استفاده می کند. حرکت درب متحرک باقی می ماند.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,9 +309,6 @@
"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",
@@ -325,7 +322,6 @@
"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).",
@@ -358,13 +354,11 @@
"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é.",
@@ -530,7 +524,6 @@
"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",
@@ -704,7 +697,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "מראה מתי העולם מציל.",
@@ -556,7 +553,6 @@
"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.": "עושה שימוש חוזר בקופסאות מיושבות; תנועת המכסה נשארת מונפשת.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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 का आकार।",
@@ -339,13 +338,11 @@
"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.": "दिखाता है कि दुनिया कब सेव होती है।",
@@ -556,7 +553,6 @@
"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.": "स्थिर बॉक्स का पुन उपयोग करता है; ढक्कन की गति एनिमेटेड रहती है।",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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-ը:",
@@ -339,13 +338,11 @@
"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.": "Ցույց է տալիս, երբ աշխարհը փրկում է:",
@@ -556,7 +553,6 @@
"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.": "Վերօգտագործում է նստեցված տուփերը; կափարիչի շարժումը մնում է անիմացիոն:",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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",
@@ -572,7 +568,6 @@
"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.",
@@ -622,9 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -620,10 +616,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +308,6 @@
"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 のサイズ。",
@@ -341,13 +340,11 @@
"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.": "世界が救われるときを示します。",
@@ -556,7 +553,6 @@
"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.": "固定されたボックスを再利用します。蓋の動きはアニメーションのままです。",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "აჩვენებს, როდესაც სამყარო ზოგავს.",
@@ -556,7 +553,6 @@
"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.": "ხელახლა იყენებს დასახლებულ ყუთებს; სახურავის მოძრაობა ანიმაციური რჩება.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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 өлшемі.",
@@ -339,13 +338,11 @@
"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.": "Әлемнің қашан құтқаратынын көрсетеді.",
@@ -556,7 +553,6 @@
"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.": "Тұндырылған қораптарды қайта пайдаланады; қақпақ қозғалысы жанды болып қалады.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "ಜಗತ್ತು ಉಳಿಸಿದಾಗ ತೋರಿಸುತ್ತದೆ.",
@@ -556,7 +553,6 @@
"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.": "ನೆಲೆಗೊಂಡ ಪೆಟ್ಟಿಗೆಗಳನ್ನು ಮರುಬಳಕೆ ಮಾಡುತ್ತದೆ; ಮುಚ್ಚಳದ ಚಲನೆಯು ಅನಿಮೇಟೆಡ್ ಆಗಿರುತ್ತದೆ.",
@@ -621,10 +617,6 @@
"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,7 +308,6 @@
"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의 크기입니다.",
@@ -341,13 +340,11 @@
"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.": "월드가 저장되는 시점을 표시합니다.",
@@ -556,7 +553,6 @@
"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.": "고정된 상자를 재사용하며 뚜껑 움직임은 애니메이션이 유지됩니다.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Дүйнө качан сактаарын көрсөтөт.",
@@ -556,7 +553,6 @@
"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.": "отургузулган кутуларды кайра колдонот; капкак кыймылы жандуу бойдон кала берет.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.",
@@ -556,7 +553,6 @@
"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.",
@@ -621,10 +617,6 @@
"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",
@@ -301,7 +301,6 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "ພູມສັນຖານຫ່າງໄກທີ່ຫຍາບຄາຍໃນໂລກທ້ອງຖິ່ນ. GPUs ປະສົມປະສານຢຸດຢູ່ທີ່ 128 chunks.",
"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.": "Caps frames ຕໍ່ວິນາທີ; ຫມວກປະຫຍັດພະລັງງານແລະຄວາມຮ້ອນ.",
"Waits for the display's refresh: no tearing, a little latency.": "ລໍຖ້າການໂຫຼດຫນ້າຈໍຄືນຂອງຈໍສະແດງຜົນ: ບໍ່ມີ tearing, latency ເລັກນ້ອຍ.",
"Size of menus and the HUD.": "ຂະໜາດຂອງເມນູ ແລະ HUD.",
@@ -339,13 +338,11 @@
"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: lava, ໄຟ ແລະແສງແດດສ່ອງສະຫວ່າງຂຶ້ນ.",
"How frames reach the screen while VSync is off.": "ເຟຣມໄປຮອດໜ້າຈໍແນວໃດໃນຂະນະທີ່ VSync ປິດຢູ່.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "ນອນທີ່ມີປະສິດທິພາບຈົນກ່ວາກອບຕໍ່ໄປ; ສະປິນທີ່ຊັດເຈນ, ເຊັ່ນ 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.": "ສະແດງໃຫ້ເຫັນໃນເວລາທີ່ໂລກຊ່ວຍປະຢັດ.",
@@ -556,7 +553,6 @@
"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 ກວດເບິ່ງ off-thread; ຫນ່ວຍງານຫມາຍຕິກ.",
"Block Entities": "ບລັອກໜ່ວຍງານ",
"Shulker Boxes": "ກ່ອງ Shulker",
"Reuses settled boxes; lid movement stays animated.": "ໃຊ້ຄືນກ່ອງທີ່ຕົກລົງ; ການເຄື່ອນໄຫວຝາປິດຍັງຄົງມີການເຄື່ອນໄຫວ.",
@@ -620,10 +616,6 @@
"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 ຂອງ mob ຫຼັງຈາກໂຫຼດ mob ຈຳນວນນີ້ແລ້ວ. ສູນປິດມັນ.",
"%s mobs": "%s mobs",
@@ -301,7 +301,6 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Grubus tolimas reljefas vietiniuose pasauliuose. Integruoti GPU sustoja ties 128 gabalėliais.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Sumažintas piešimas kur kas grubesnis: greičiau naudojant šį integruotą GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Sumažintas reljefas traukia stambesnį, o GPU – lėtėja.",
"Field of view. Wider shows more terrain at once.": "Matymo laukas. Plačiau vienu metu rodo daugiau reljefo.",
"Caps frames per second; a cap saves power and heat.": "Caps kadrų per sekundę; dangtelis taupo energiją ir šilumą.",
"Waits for the display's refresh: no tearing, a little latency.": "Laukiama ekrano atnaujinimo: be plyšimų, šiek tiek delsos.",
"Size of menus and the HUD.": "Meniu dydis ir HUD.",
@@ -339,13 +338,11 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Išlygina dantytus kraštus. FXAA: minkštesnis. TAA: sklandžiausi, judantys daiktai gali sekti.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Padaro pasaulį mažesnį ir atkuria jį su TAA. Greičiau, švelniau.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Padidina padidinto vaizdo ryškumą. Aukščiau: ryškesni kraštai, daugiau mirgėjimo.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR išvestis HDR ekrane: lava, ugnis ir saulės šviesa šviečia ryškiau.",
"How frames reach the screen while VSync is off.": "Kaip kadrai pasiekia ekraną, kai VSync išjungtas.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efektyvus miegas iki kito kadro; Tikslūs sukimai, kaip vanilė.",
"Fills the screen (borderless).": "Užpildo ekraną (be rėmelių).",
"Brightens dark places.": "Šviesina tamsias vietas.",
"Lowers the frame rate when minimised, or idle too.": "Sumažina kadrų dažnį, kai jis sumažinamas arba veikia tuščiąja eiga.",
"Sways the view while walking.": "Vaikštant vingiuoja vaizdas.",
"Fades newly loaded chunks in.": "Išblukina naujai įkeltus gabalus.",
"Darkens the screen's edges.": "Tamsina ekrano kraštus.",
"Shows when the world saves.": "Rodo, kada pasaulis gelbsti.",
@@ -556,7 +553,6 @@
"horizon.splitscreen.online_only": "Šis serveris veikia prisijungimo režimu: neprisijungę profiliai negali prie jo prisijungti, kiekvienam žaidėjui reikia savo Minecraft paskyros.",
"horizon.splitscreen.own_account": "Šiam serveriui reikia kiekvieno žaidėjo savo Minecraft paskyros",
"horizon.splitscreen.local_only": "Kiti žaidėjai prie šio serverio gali prisijungti tik su savo Minecraft paskyra: neprisijungę profiliai žaidžia jūsų pasaulyje, LAN arba jūsų vietiniame tinkle esančiame serveryje.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Slepia modelius už nepermatomų blokų. Async tikrina ne giją; subjektai pažymi.",
"Block Entities": "Blokuoti subjektus",
"Shulker Boxes": "Šulkerio dėžės",
"Reuses settled boxes; lid movement stays animated.": "Pakartotinai naudoja nusistovėjusias dėžes; dangtelio judėjimas išlieka animuotas.",
@@ -621,10 +617,6 @@
"horizon.agent.session_opened": "Šiam seansui atidarė programą, kuri pradėjo žaidimą.",
"horizon.agent.socket": "Lizdas: %s (nukopijuokite išsamią informaciją apie visą jo kelią)",
"horizon.agent.local_only": "Tik vietinis: agentai šiame kompiuteryje, niekada tinkle.",
"%s nits": "%s nitai",
"Auto (%s nits)": "Automatinis (%s nitai)",
"%.2f nits": "%.2f nitai",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Slepia modelius už nepermatomų blokų. Subjektai atnaujinami. Išjungti su pasirinktiniais paketais.",
"Entity Culling Precheck": "Esybių atmetimo išankstinė patikra",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Vykdo padarų AABB išankstinę patikrą po tiek įkeltų padarų. Nulis ją išjungia.",
"%s mobs": "%s padarų",
@@ -301,7 +301,6 @@
"Coarse distant terrain in local worlds. Integrated GPUs stop at 128 chunks.": "Rupjš attāls reljefs vietējās pasaulēs. Integrētie GPU apstājas pie 128 gabaliem.",
"Reduced draws far terrain coarser: faster on this integrated GPU.": "Samazināts zīmējums ir rupjāks: ātrāk ar šo integrēto GPU.",
"Reduced draws far terrain coarser, for GPUs it slows down.": "Samazinātā reljefs ir rupjāks, GPU gadījumā tas palēninās.",
"Field of view. Wider shows more terrain at once.": "Skata lauks. Plašāks vienlaikus parāda vairāk reljefa.",
"Caps frames per second; a cap saves power and heat.": "Caps kadri sekundē; vāciņš ietaupa enerģiju un siltumu.",
"Waits for the display's refresh: no tearing, a little latency.": "Gaida displeja atsvaidzināšanu: nav plīsumu, neliels latentums.",
"Size of menus and the HUD.": "Izvēlņu lielums un HUD.",
@@ -339,13 +338,11 @@
"Smooths jagged edges. FXAA: softer. TAA: smoothest, moving things may trail.": "Izlīdzina robainās malas. FXAA: mīkstāks. TAA: vienmērīgākās, kustīgās lietas var izsekot.",
"Renders the world smaller and rebuilds it with TAA. Faster, softer.": "Padara pasauli mazāku un atjauno to ar TAA. Ātrāk, maigāk.",
"Sharpens the upscaled picture. Higher: crisper edges, more shimmer.": "Padara asāku mērogoto attēlu. Augstāk: asākas malas, vairāk mirgoņa.",
"HDR output on an HDR display: lava, fire and sunlight shine brighter.": "HDR izvade HDR displejā: lava, uguns un saules gaisma spīd spožāk.",
"How frames reach the screen while VSync is off.": "Kā kadri sasniedz ekrānu, kamēr VSync ir izslēgts.",
"Efficient sleeps until the next frame; Precise spins, like vanilla.": "Efektīva gulēšana līdz nākamajam kadram; Precīzi griezieni, piemēram, vaniļa.",
"Fills the screen (borderless).": "Aizpilda ekrānu (bez malām).",
"Brightens dark places.": "Izgaismo tumšās vietas.",
"Lowers the frame rate when minimised, or idle too.": "Samazina kadru nomaiņas ātrumu, ja tas ir samazināts līdz minimumam vai arī darbojas dīkstāvē.",
"Sways the view while walking.": "Ejot izgroza skatu.",
"Fades newly loaded chunks in.": "Izbalē tikko ielādētos gabalus.",
"Darkens the screen's edges.": "Padara tumšākas ekrāna malas.",
"Shows when the world saves.": "Parāda, kad pasaule glābj.",
@@ -556,7 +553,6 @@
"horizon.splitscreen.online_only": "Šis serveris ir tiešsaistes režīmā: bezsaistes profili tam nevar pievienoties, katram spēlētājam vajadzīgs savs Minecraft konts.",
"horizon.splitscreen.own_account": "Šim serverim vajadzīgs katra spēlētāja savs Minecraft konts",
"horizon.splitscreen.local_only": "Citi spēlētāji šim serverim var pievienoties tikai ar savu Minecraft kontu: bezsaistes profili spēlē jūsu pasaulē, LAN tīklā vai serverī jūsu vietējā tīklā.",
"Hides models behind opaque blocks. Async checks off-thread; entities tick.": "Slēpj modeļus aiz necaurspīdīgiem blokiem. Async pārbauda ārpus pavediena; entītijas atzīmē.",
"Block Entities": "Bloķēt entītijas",
"Shulker Boxes": "Šulkera kastes",
"Reuses settled boxes; lid movement stays animated.": "Atkārtoti izmanto nosēdinātās kastes; vāka kustība paliek animēta.",
@@ -621,10 +617,6 @@
"horizon.agent.session_opened": "Šai sesijai atvēra programma, kas sāka spēli.",
"horizon.agent.socket": "Socket: %s (kopējiet informāciju, lai iegūtu pilnu ceļu)",
"horizon.agent.local_only": "Tikai lokāli: aģenti šajā datorā, nekad tīkls.",
"%s nits": "%s nits",
"Auto (%s nits)": "Automātiski (%s nits)",
"%.2f nits": "%.2f nits",
"Hides models behind opaque blocks. Entities update. Off with custom packs.": "Slēpj modeļus aiz necaurspīdīgiem blokiem. Entītiju atjaunināšana. Izslēgts ar pielāgotiem iepakojumiem.",
"Entity Culling Precheck": "Entītiju izkaušanas priekšpārbaude",
"Runs the mob AABB precheck after this many loaded mobs. Zero disables it.": "Palaides mobu AABB priekšpārbaudi pēc šāda daudzuma ielādētu mobu. Nulle to atslēdz.",
"%s mobs": "%s mobi",
@@ -301,7 +301,6 @@
"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.",
@@ -339,13 +338,11 @@
"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.": "Покажува кога светот спасува.",
@@ -556,7 +553,6 @@
"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.": "Повторно употребува населени кутии; движењето на капакот останува анимирано.",
@@ -621,10 +617,6 @@
"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 суштества",
@@ -301,7 +301,6 @@
"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-ийн хэмжээ.",
@@ -339,13 +338,11 @@
"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.": "Дэлхий хэзээ аварч байгааг харуулна.",
@@ -556,7 +553,6 @@
"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.": "Суурилуулсан хайрцгийг дахин ашигладаг; тагны хөдөлгөөн хөдөлгөөнтэй хэвээр байна.",
@@ -621,10 +617,6 @@
"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 амьтан",
Loaded 100 of 378 files, more files were not shown because too many files have changed in this diff. Show more