Compare commits

...
Author SHA1 Message Date
Horizon agentandClaude Opus 5.5 498d9bebcf Add GOVERNANCE.md: the council, theme groups and how roles are earned
The governance the founder adopted on 2026-11-09 as his last decision as
head of the project: a council of equals deciding by 24-hour polls, theme
groups with leads, the selection filter, moderation and appeals, the 18+
rule for roles of trust, the agents, and the account handover path.
README and CONTRIBUTING link to it with one line each.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 21:21:45 +01:00
Ludovic Marie f0cb1e42c0 Merge pull request #14156 from horizon-rust/layers/studio-gather
🤖 Agent: the verify failure was the two rustc-compiled fixtures (test_compute_fov_hook, test_world_input_capture) still modelling game.studio_freecam/studio_replay; they now carry the Studio struct game.rs reads, and both pass on this head.
2026-11-09 21:06:48 +01:00
Ludovic Marie 38174db59b Merge pull request #14170 from MSedgeMC/port_map/barrier-pickup-rule
🤖 Agent: Sim::pickup_block already gates a waterlogged barrier on the breaker being creative, as BarrierBlock.pickupBlock does.
2026-11-09 20:59:57 +01:00
Ludovic Marie 093f5efda8 Merge pull request #14001 from horizon-rust/layers/input-feedback
🤖 Agent: gameplay now asks controllers only through input_move, input_holds, input_look and input_feedback in play_input.rs, which still call the same pad functions, so the pad modules can later answer through a registered input source.
2026-11-09 20:59:12 +01:00
Ludovic Marie b444a6b64f Merge pull request #14171 from MSedgeMC/worldlane/chest-opener-rechecks
🤖 Agent: same rows as #14128 without the stray worldgen change: Sim::tick_block's chest arm is recheckOpen, scheduled every 5 ticks from count_opener.
2026-11-09 20:59:03 +01:00
Ludovic Marie e8d192f2ac Merge pull request #14218 from horizon-rust/layers/containers-spec
🤖 Agent: docs only: adds the Look and container-screen API specs to docs/layers.md under Platform registries, following #14217's look::update.
2026-11-09 20:58:59 +01:00
Ludovic Marie 6ad39aa412 Merge pull request #14127 from horizon-rust/fix/offline-names-dev-only
🤖 Agent: the game now plays only as the selected account (else the first), which must own the game itself (launch_for_game); old accounts.json/settings.json load and drop offline, offline_selected, looks, skins/ and dev_offline on the next save, covered by files_from_launchers_with_offline_names_load_and_lose_them_on_save.
2026-11-09 20:58:55 +01:00
Ludovic Marie 6342ce83b2 Merge pull request #14002 from MrCloudy2/fix/bounced-projectile-tick-order
🤖 Agent: a bounced arrow goes back by join number through JoinList::put_back (unit-tested), so it keeps its EntityTickList place; moved out of creatures.rs, which may not grow.
2026-11-09 20:58:51 +01:00
Ludovic Marie 595421d8ee Merge pull request #14018 from MSedgeMC/fix/stonecutter-result-components
🤖 Agent: a stonecutting result with a components patch goes through SmithingResult's template create, so a pack's custom-named result keeps its name; plain results stay on the cheap path.
2026-11-09 20:51:44 +01:00
Ludovic Marie 7169886142 Merge pull request #14122 from MSedgeMC/fix/anvil-selection-colour
🤖 Agent: AnvilScreen.init's setInvertHighlightedTextColor(false) on the rename box; moved apart from #14094's EditBox lines so both merge in either order.
2026-11-09 20:48:53 +01:00
Ludovic Marie cdcac3463e Merge pull request #14123 from Mik00000/perf/async-audio-raycasts
🤖 Agent: bee sounds no longer rescan every mob per bee each tick and the sound engine takes one lock per channel update; silent one-frame/empty sounds stop again (agent fix 23ca4a8).
2026-11-09 20:45:15 +01:00
Ludovic Marie e71c626484 Merge pull request #14097 from vnsmoreira/packs/polytone-expr-fast
🤖 Agent: the fast path only takes one-expression programs whose kind is known and is checked bit for bit against the interpreter; 468 lines after the timing test moved to #14185. Queue AFTER 14089.
2026-11-09 20:45:10 +01:00
Ludovic Marie 194ede9376 Merge pull request #14077 from DUzzL/fix/13935-iron-golem
🤖 Agent: OfferFlowerGoal's (6,2,6) box plus forNonCombat().range(6) with sight, isBrightOutside's fixed-time check, the golem's own random for the repair pitch; the defence sight test the body named is now in the diff (agent fix 4643ea9).
2026-11-09 20:45:06 +01:00
Ludovic Marie 12578352dc Merge pull request #14203 from Evan-lhm/rt/ray-query-opt-in
🤖 Agent: EXPERIMENTAL_RAY_QUERY is requested only with HORIZON_RAY_TRACING=1 in a horizon-extras build; without it the device request is main's.
2026-11-09 20:41:33 +01:00
Ludovic Marie 11ebc3f199 Merge pull request #13960 from horizon-rust/layers/packs-emissive
🤖 Agent: the emissive suffix is read once per pack load through PackFormats::emissive_suffix; atlas building only compares a stored string per sprite as before. layer plan M6 step 3.
2026-11-09 20:41:27 +01:00
Ludovic Marie bc08885276 Merge pull request #14142 from MSedgeMC/fix/shulker-face-bytes
🤖 Agent: AttachFace wraps through from3DDataValue and Peek/Color stay raw bytes; texture() reads the colour signed, so -1 draws white as DyeColor.byId's ZERO strategy does.
2026-11-09 20:37:15 +01:00
Ludovic Marie bc7b8889de Merge pull request #14126 from Joansitoh/fix/9965-warden-save
🤖 Agent: the LAN owner's warden tracker now goes into g.saved before playerdata::store rewrites player_extra from it, so warning level and cooldown survive a save; with_warden keeps lan.rs (over 3000 lines) from growing.
2026-11-09 20:37:11 +01:00
Ludovic Marie 7180a52bf2 Merge pull request #14014 from oloion/fix/elytra-wall-sound-repeat
🤖 Agent: handleFallFlyingCollisions now compares lastSpeed (before updateFallFlyingMovement) with the delta Entity.move leaves, collided axes zeroed, so a glider pressed on a wall stops replaying the crash sound.
2026-11-09 20:37:05 +01:00
Ludovic Marie 8e37c4a4b7 Merge pull request #14215 from DUzzL/fix/14176-lod-mesh-samples
🤖 Agent: bring_back now calls sync_sample for a returning kept tile, so check_mesh_samples sees it.
2026-11-09 20:32:42 +01:00
Ludovic Marie 94ba80f90d Merge pull request #14074 from DUzzL/fix/14034-glass-data-move
🤖 Agent: the glass About card now builds location_row (Move…, confirm, retry/default), and the row keeps the Open button beside Move (agent fix eb3157d; needs the launcher job green: no local launcher build).
2026-11-09 20:32:38 +01:00
Ludovic Marie 238fc99add Merge pull request #14129 from NikitaMGrimm/hdr-windows-calibrate
🤖 Agent: only os_reported (Windows) sets peak_guessed, so Wayland and macOS keep their labels; main merged, the docs paragraph re-applied on main's text, and main's ui_nits test given the field.
2026-11-09 20:32:33 +01:00
Ludovic Marie ac96d3fa35 Merge pull request #13959 from horizon-rust/layers/packs-colors
🤖 Agent: pack colours (OptiFine color.properties, Polytone colors) are now read through pack_hooks::PackFormats once per pack load; the engine keeps a plain PackColors table, so per-block tint lookups stay table reads. layer plan M6 step 2. Merging main moved its new Polytone damage-bar colours behind PackFormats::item_bars, test moved with them.
2026-11-09 20:26:44 +01:00
Horizon agentandClaude Opus 5.5 4881a0862f Container screens spec: container_key gets the hovered slot, as the other inputs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:59:40 +01:00
Horizon agentandClaude Opus 5.5 1498fdecd3 Tests: fixtures read Studio's state from game.studio
test_compute_fov_hook and test_world_input_capture paste fov.rs and the
pointer-capture methods into a fixture Game; those now read
self.studio.{freecam,replay,rmb_down}, so the fixture carries a Studio.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:55:14 +01:00
Horizon agentandClaude Opus 5.5 e859476293 test_world_input_capture: the move read is input_move now
tick_remote_level asks the input source (input_move) instead of pad_move, so
the order check (load completes, then the player moves) looks for that call
(verify run 42649031940).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:45:27 +01:00
Horizon agentandClaude Opus 5.5 89235891ce Container screens spec: the API as implemented (&mut reads, spread, Equipment, every menu's slots)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:38:19 +01:00
Horizon agentandClaude Opus 5.5 2081a0dd95 Merge main into #14127; be.json is main's translation minus the offline-name keys
Main retranslated 252 Belarusian launcher strings; this PR removes the 28
offline-name keys. be.json is main's file with those 28 keys taken out (7 of
them were among the retranslated ones); every lang file parses and none keeps
a removed key.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:35:38 +01:00
Evan-lhm 3f1a50ccb2 Merge remote-tracking branch 'origin/main' into rt/ray-query-opt-in
# Conflicts:
#	crates/horizon-client/Cargo.toml
2026-11-09 19:25:47 +01:00
Horizon agentandClaude Opus 5.5 8534f12db0 Look spec: update, each crate its own fields
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:25:12 +01:00
Horizon agentandClaude Opus 5.5 7e95a1f57f stations tests: keep the registration-order doc on its own test
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:23:37 +01:00
Horizon agentandClaude Opus 5.5 e0e4c5e9db docs/layers.md: spec of the look and the container screen API (layer plan M5)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:22:25 +01:00
Horizon agent 3dcfd7276b Merge remote-tracking branch 'rv3n/14142' into rv3-fix-14142 2026-11-09 19:21:20 +01:00
Horizon agentandClaude Opus 5.5 bfbf06a439 Fall flying wall hit: compare the speed before updateFallFlyingMovement
LivingEntity.travelFallFlying takes lastSpeed before the glide update, as
move_h does; the post-update speed left move_h unused (verify failed).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:19:28 +01:00
Evan-lhmandClaude Opus 5.5 75071c8b9b gfx.rs may not grow: ray_query is declared beside its one user
Its `mod` line moves from gfx.rs (over 3000 lines, docs/layers.md#file-size) into
surface_setup.rs, the device request that reads it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:18:37 +01:00
DUzzL 971f341977 Keep lod.rs from growing 2026-11-09 19:17:51 +01:00
Evan-lhmandClaude Opus 5.5 63a6a92bef Ray tracing on request is a Horizon extra (#13780)
As ludovic111 asked on #13780: asking the device for ray queries, and the log line
saying why it is on or off, happen only in a `horizon-extras` build
(horizon-client's feature now enables horizon-client-render's). A plain build
requests the device it requested before, whatever HORIZON_RAY_TRACING says
(`only_an_extras_build_asks_for_ray_tracing`, run with and without the feature).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:07:35 +01:00
Evan-lhmandClaude Opus 5.5 cf93d0dd3a Renderer: ask for hardware ray queries only with HORIZON_RAY_TRACING=1 (#13780)
Step 1 of #13780 (carrying on the #1180 spike): the device requests wgpu's
EXPERIMENTAL_RAY_QUERY when the variable is set and the adapter has it, and
logs why it stays off otherwise. Nothing draws with it yet; without the
variable the device opens exactly as before. The unsafe opt-in lives in
horizon-hdr, which already holds the GPU calls the game crates can't make.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:03:49 +01:00
MSedgeMC 2e9f807458 Merge remote-tracking branch 'upstream/main' into fix/stonecutter-result-components 2026-11-09 18:01:23 +00:00
DUzzL 21aabee4c0 Sync far-terrain mesh samples when kept tiles return 2026-11-09 19:00:58 +01:00
MSedgeMC 7be13f1e9a Merge upstream/main 2026-11-09 18:00:20 +00:00
Horizon agentandClaude Opus 5.5 ff83eccf6a AttachFace: unsigned_abs on the remainder, as clippy asks, within the line
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:59:17 +01:00
MSedgeMC 8d7ca30ea4 Merge remote-tracking branch 'upstream/main' into fix/stonecutter-result-components 2026-11-09 17:58:10 +00:00
Horizon agentandClaude Opus 5.5 e39ec11e59 Merge branch 'layers/packs-colors' into layers/packs-emissive
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:56:37 +01:00
Horizon agentandClaude Opus 5.5 b5f396461e Merge origin/main into layers/packs-colors
Main's Polytone item bar colours (#fb354374e3) move behind the new
PackFormats::item_bars hook (glue pack_formats/item_bars.rs, test moved with
them), and environment.horizon_height joins the engine's Environment.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:55:39 +01:00
Horizon agentandClaude Opus 5.5 e963d24058 Give main's new UI-nits test its peak_guessed field
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:54:18 +01:00
Horizon agentandClaude Opus 5.5 3eec96a8b1 Format the shulker load and its test; abs() keeps the line within entity_nbt.rs's size
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:54:15 +01:00
Horizon agentandClaude Opus 5.5 249e8db13c Keep lan.rs from growing: with_warden takes the tracker and gives the guest back
lan.rs is over 3000 lines and may not grow (tools/check_file_size.py): the
tracker now goes in on the line that picks the owner's guest, and the
comment moves to playerdata::with_warden.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:53:53 +01:00
Horizon agentandClaude Opus 5.5 6bb4c0eda9 Put a bounced projectile back through JoinList::put_back
creatures.rs is over 3000 lines and may not grow (verify's file-size check):
the join-order insertion moves to join_seq.rs, with a unit test.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:53:40 +01:00
Horizon agentandClaude Opus 5.5 2f06f532e5 rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:52:52 +01:00
MSedgeMC 092dee299b Merge remote-tracking branch 'upstream/main' into fix/stonecutter-result-components 2026-11-09 17:52:13 +00:00
Horizon agentandClaude Opus 5.5 23ca4a855a audio: silent short sounds stop again; drop the unused camera_epoch
- A channel of one frame or none was skipped before the mixing loop, so it
  never stopped and kept its channel; the inaudible fast path also computed
  (frames - 1) in usize, which underflows for an empty sound. Both now stop
  it, as the loop does; a step of 0 no longer stops a sound the loop keeps.
- Mixer::camera_epoch was written and never read.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:46:45 +01:00
MSedgeMC 16172da6b7 port_map: the chest and ender chest recheckOpen rows are ports
`Sim::tick_block`'s chest arm is `ChestBlock.tick`/`EnderChestBlock.tick`:
it recounts the openers through `recheck_container_openers`
(`ContainerOpenersCounter.recheckOpeners`), broadcasts the lid event and
re-schedules the five-tick tick while anyone has the container open. The
rows still said only the copper golems' openers were rechecked.
2026-11-09 17:46:19 +00:00
Horizon agentandClaude Opus 5.5 5720b15eff ui: the highlight flag and its test sit apart from #14094's
#14094 adds EditBox::centered beside text_color and a test at the end of
ui.rs's tests; this PR's field, initialiser and test touched the same lines.
Moved further down so both merge in either order. No behaviour change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:45:49 +01:00
Horizon agentandClaude Opus 5.5 2e754b1297 Polytone: the ticker timing test moves to its own PR; field() last
Keeps this PR under the project's 500-line limit (519 -> 468): the ignored
custom_ticker_cost timing test follows in a separate PR. Ctx's field() moves
to the end of its Host impl, so this merges cleanly beside #14089, which
changes the impl's own line.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:45:18 +01:00
MSedgeMC 70c8d7089d port_map: the barrier pickup row's creative rule is checked
`Sim::pickup_block` returns false for a waterlogged barrier unless the
breaker is creative, which is `BarrierBlock.pickupBlock`'s gate; the row
said the rule was not there.
2026-11-09 17:45:14 +00:00
Horizon agentandClaude Opus 5.5 eb3157d251 Launcher: the Data folder row keeps its Open button beside Move
The glass About card's row had Open; building location_row there dropped
it. location_row's action is now Open and Move side by side (only the
glass page builds it: the old settings page is unreachable).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:44:54 +01:00
Horizon agentandClaude Opus 5.5 4643ea9357 Iron golem: the defence goal sees the hating villager too
DefendVillageTargetGoal.canUse finds the villagers through attackTargeting
(forCombat().range(64)), which tests the golem's line of sight to each: a
villager behind a wall no longer sets the golem on the player. The PR body
named this change but the commit missed it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:44:12 +01:00
Horizon agent 8a9bd15a3d Merge remote-tracking branch 'origin/main' into rv3-fix-14129
# Conflicts:
#	docs/graphics.md
2026-11-09 18:43:16 +01:00
Horizon agentandClaude Opus 5.5 a40f3d82c1 A shulker with a negative colour byte draws white, as DyeColor.byId does
Shulker.getColor treats the byte as signed: 16 and above are undyed, and a
negative id reaches DyeColor.byId, whose OutOfBoundsStrategy.ZERO gives
white. Keeping the raw byte (255 for -1) sent it to the undyed texture.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:42:45 +01:00
Horizon agentandClaude Opus 5.5 93e0536aca Studio: its state in one struct, game/studio.rs's Studio (layer plan M6)
Game's ten studio_* fields and last_replay_tick become one field, studio:
studio::Studio. Pure gather: every access is renamed, nothing else changes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:29:54 +01:00
MSedgeMC 59d958c09e port_map: the shulker's save reads wrap and narrow like vanilla
`tools/port_map/game2-002.tsv` said `Shulker.readAdditionalSaveData` reads
`AttachFace`, `Peek` and `Color`; the row now names the codec's wrapping and
the two raw bytes the port keeps.
2026-11-09 17:22:12 +00:00
MSedgeMC 1a2015e305 test: a shulker's saved face and lid bytes
`mob_from_nbt` is what `Game::load_mob` goes through. A shulker with
`AttachFace: 7b`, `Peek: -1b` and `Color: -1b` loads with `variant3 == 1`
(`abs(7 % 6)` is up), `counter == -1` and `color == 255`.

Without the coercion they load clamped: `left: 5`, `right: 1` for the face,
`left: 0`, `right: -1` for the peek and `left: 16`, `right: 255` for the
colour.
2026-11-09 17:22:12 +00:00
MSedgeMC 197172ef3c fix: a shulker reads its saved face and lid bytes as vanilla does
`Shulker.readAdditionalSaveData` reads three fields with different rules:

- `AttachFace` is `Direction.LEGACY_ID_CODEC`, whose `from3DDataValue` wraps
  the byte through `abs(id % 6)`;
- `Peek` is `getByteOr("Peek", 0)`, a raw byte put straight on the synched
  data;
- `Color` is `getByteOr("Color", 16)`, a raw byte too.

Horizon clamped all three to the setters' ranges (`0..=5`, `0..=100`,
`0..=16`): an `AttachFace` of 7 became east (5) instead of up (1), a negative
`Peek` became 0 instead of the byte vanilla stores, and a negative `Color`
became 0 instead of 255.

The load now wraps the face and narrows `Peek` and `Color` to bytes, exactly
as the codec and `getByteOr` do.
2026-11-09 17:22:12 +00:00
JoansitohandClaude Sonnet 5.5 9d6d292348 Keep the owner's warden spawn tracker through a save
store_owner wrote the tracker into level.player_extra, then playerdata::store
replaced that with the guest's loaded snapshot, losing the warning level and
cooldown. Put the tracker into the owner guest's saved compound first.

Part of #9965

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-09 18:18:08 +01:00
Horizon agentandClaude Opus 5.5 1e789800af launcher: remove offline names; play only as an account that owns the game
The project decided that Horizon plays only with a Microsoft account that
owns Minecraft: Java Edition. The launcher loses, in every build:

- the hidden Developer options section (seven clicks on the sidebar
  version) and Settings::dev_offline;
- offline names: adding, selecting and playing as one, the game's made-up
  name as a player, their skins and capes (skins.rs, skin_page.rs), the
  quick switch's and Settings > Account's offline entries, and the CLI's
  `account offline`, `account forget-offline` and `account skin`;
- the `--name` and HORIZON_OFFLINE_SKIN* it gave the game for them.

The game plays as the selected account (else the first), and
account::launch_for_game requires that account to own the game itself:
another account's ownership no longer lets it start under a name of its
own. With no network, its last answer still stands, as before.

Files from older launchers still load: accounts.json's `offline`,
`offline_selected` and `looks` and settings.json's `dev_offline` are
ignored on read and gone from the next save, which also deletes the old
names' skin and cape files.

The 28 strings only these used leave the 86 lang files and the
lang_review copies.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:18:05 +01:00
MSedgeMC 74e0245c47 port_map: EditBox.setInvertHighlightedTextColor 2026-11-09 17:17:21 +00:00
MSedgeMC e5eacec45c test: the anvil's selection keeps its colour
The box reports its own inversion off; a default box inverts; the selection
it would draw is the value.
2026-11-09 17:17:15 +00:00
Mik00000andClaude Opus 5.5 cf23e5001a perf(audio): optimize sound attenuation, spatial math, and batch channel updates
- Early-out for stationary listener in Audio::set_listener (bypasses mutex lock contention completely when camera does not move, ~5.25 ns vs ~36 ns)
- Eliminate redundant distance sqrt in stereo_gains: projections onto orthonormal basis preserve Euclidean distance, so reuse d.length()
- Replace asin in elevation with sqrt(1 - u^2) using identity cos(asin(u)) = sqrt(1 - u^2), avoiding inverse trig entirely
- Single-camera fast path in mix to avoid splitscreen camera search loop in normal single-player / multiplayer mode
- Distance squared early-out for linear attenuation (bypasses basis projections and stereo gains for inaudible sounds outside attenuation radius)
- Fast sample skipping for silent / zero-gain audio frames without decoding interpolation
- Batch channel parameter updates via Backend::update_channel, reducing 3 mutex lock acquisitions per ticking instance to 1
- Batch stopped query via Backend::filter_stopped, replacing N individual channel mutex locks per tick with a single query pass
- Avoid O(N*M) entity loop in Game::start_mob_sounds by collecting bee indices in initial filter pass

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:16:52 +02:00
MSedgeMC 0e9233b230 fix: the anvil's selected name keeps its colour
AnvilScreen sets setInvertHighlightedTextColor(false) on its rename box, so a
selection leaves the white text alone instead of painting it black on the
highlight. EditBox always inverted it.
2026-11-09 17:16:42 +00:00
Nikita Maximilian GrimmandClaude Opus 5.5 aa741b3570 HDR settings: on Windows, the HDR page asks to calibrate
On Windows, Auto takes the display's peak from DXGI's MaxLuminance, which is
mostly the display's EDID figure and often runs high. The HDR page still said
the display was already set up ("Calibrate Anyway..."), though calibration's
Peak step works there, since PQ passes through unchanged.

Now the Windows reading marks its peak as a guess (`Reported::peak_guessed`),
and the page's Calibrate row reads "Calibrate..." and says the reported peak is
often too high, while Peak Brightness and Paper White stay on Auto. Auto still
uses the reported values, which beat the 1000-nit default. Once the player has
calibrated or set either value, the row offers "Use Automatic Setup" as before.
There the Peak Brightness row no longer says it is set up for the display:
its Auto is the guess. Paper White, the player's own slider, still does.
Compositor reports (Wayland) and macOS, which reports no nits, are unchanged.

The setup decision moves next to `Reported` (`Graphics::hdr_setup`), out of
graphics_ui.rs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:47:16 +01:00
Vinícius MoreiraandClaude Opus 5.5 3b03b98836 Polytone: expression fields answered without their names
The fast path resolves the methods without arguments expressions read most (age, life,
custom, x, y, z, temperature, downfall) when the program compiles; a host may answer them by
that Field (Host::field) instead of comparing names, and one that doesn't, or a case it
doesn't cover, goes through the name as before, with the same value. The particles' host
answers a particle's own fields, the colormaps' block host its position and biome climate.
The equivalence test now also runs a host that answers fields.

Custom particle tick (custom_ticker_cost, release): 376 ns before, 344 ns now.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 13:42:26 -03:00
Vinícius MoreiraandClaude Opus 5.5 4e4767bbfe Polytone: a numeric fast path for expressions
A Polytone expression ran through the interpreter's Values and Results: about 263 ns for a
firefly's alpha that costs 7 ns written in Rust. An expression of one statement whose every
part is a number (constants, arithmetic, comparisons of numbers, math functions, ternaries,
and root.method(...) calls) now compiles a second time into a tree of f64s. It answers
exactly what the interpreter would: the result's kind (number, boolean, or a method's own
value at the top), method arguments as the interpreter passes them, Value::truthy for
methods in conditions; anything that could tell them apart (strings, == on a method's
value, locals, game functions) stays in the interpreter. A test runs a corpus of
expressions through both and compares every value and every host call.

Custom particle tick (custom_ticker_cost, release): 715 ns before, 376 ns now. A section's
colormap tints (colormap_tint_cost): 178 µs before, 135 µs now, same colours.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 13:42:26 -03:00
Vinícius MoreiraandClaude Opus 5.5 a2d34c7dbd Polytone: a timing test for custom particle tickers
custom_ticker_cost (ignored) ticks a firefly-like custom particle (five expressions with
sines and a named custom) and prints the time a tick takes, about 0.7 µs in release.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 13:42:26 -03:00
DUzzL e42acfc7ea Give the iron golem's poppy offer vanilla's range, sight and daylight gate, sight-test villagers in the defence goal, draw the repair pitch from the golem 2026-11-09 17:37:02 +01:00
Horizon agent 9fd16efb45 Merge branch 'layers/packs-colors' into layers/packs-emissive 2026-11-09 17:34:46 +01:00
Horizon agent 34b5df1397 Merge branch 'layers/packs-sky' into layers/packs-colors
# Conflicts:
#	crates/horizon-client-render/src/lib.rs
#	crates/horizon-client/src/client_lib.rs
2026-11-09 17:34:35 +01:00
DUzzL 72c6784172 Launcher: give the glass Settings Data folder row the Move button 2026-11-09 17:21:46 +01:00
MSedgeMC f0c1ec9d84 A stonecutter result keeps its components
StonecuttingRecipe.assemble creates the result from ItemStackTemplate, so a
result's components (a data pack's custom name, damage, ...) belong on the
output. Horizon built the result from its id and count only.

Test: a stonecutting recipe whose stone result names it "Cut Stone" yields a
named stone.
2026-11-09 15:59:33 +00:00
Horizon agentandClaude Opus 5.5 755b7800c1 Input source: what gameplay tells the pad goes through engine methods too
input_keyboard_used, input_made_pointer_event, input_player_replaced,
input_takes_stack_drop and input_hud_begin replace gameplay's direct writes to
the pad's state.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:51:53 +01:00
MrCloudy2andClaude Opus 5.5 30149bfb41 Harness: an arrow bouncing off a wind charge keeps its place in the tick order
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:47:59 +01:00
Ludovic Marie 93ecc8d0c1 Merge branch 'layers/packs-colors' into layers/packs-emissive 2026-11-09 16:46:39 +01:00
Horizon agentandClaude Opus 5.5 230b167744 Keep PackColors::entity_shadows a method, as the shadow ownership check reads it
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:46:36 +01:00
Ludovic MarieandClaude Opus 5.5 0031c67d04 rustfmt explosion.rs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:46:14 +01:00
MrCloudy2andClaude Opus 5.5 2726614191 A projectile put back after its hit keeps its place in the tick order
An arrow that bounces off an entity (deflect REVERSE) never leaves the level
in vanilla, so it keeps its place in EntityTickList. Horizon's projectile
pass drops it and finish_arrow_hit adds it again with add_projectile, which
appended it behind every projectile already waiting: those then ticked
before it. add_projectile now puts a projectile that has already joined back
at its join position; a new one still goes last.

Found with the Orbital Skybender: the arrow that reads each digit missed
every other wind charge, so only half the digits were read.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:41:23 +01:00
Horizon agentandClaude Opus 5.5 2e45a0750d rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:27:26 +01:00
Horizon agent 8ad2c758ad Merge branch 'layers/packs-colors' into layers/packs-emissive 2026-11-09 16:27:26 +01:00
Horizon agentandClaude Opus 5.5 c71978372d rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:27:24 +01:00
Ludovic MarieandClaude Opus 5.5 5152376c4b input_feedback: commands already have a feedback
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:24:14 +01:00
Horizon agentandClaude Opus 5.5 8f331a10f5 Input source: gameplay asks controllers through engine methods (layer plan M6)
Gameplay reads the analog move vector, held mappings and the view turn, and
reports what the player may feel (Feedback), through input_move, input_holds,
input_look and feedback in play_input.rs. Only these four bodies name the pad
modules, which answer today; Feedback is an engine type the pad maps to Rumble.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:15:28 +01:00
Horizon agentandClaude Opus 5.5 cbba6ead3a Emissive overlays' suffix through the pack-format hook
layer plan M6 (pack formats), step 3: the terrain's emissive overlays take
the pack's suffix from pack_hooks (OptiFine's emissive.properties, _e by
default); with no pack formats installed a pack has none. atlas_sources
checks a texture path stays in the pack root itself.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 15:39:02 +01:00
Horizon agentandClaude Opus 5.5 2a44a86383 Pack colours through the engine's pack-format hook
layer plan M6 (pack formats), step 2: the colours a pack replaces (dyes,
sheep, redstone, effects, the experience number, entity shadows, the
effect fogs) are an engine table (pack_palette::PackColors) that
Polytone's colors.json fills through pack_hooks; the polytone_colors
re-export goes away.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 15:37:31 +01:00
Oloion e0b91d71bf Compare pre- and post-collision delta movement in fall flying
LivingEntity.handleFallFlyingCollisions in vanilla 26.3 compares the
horizontal movement vector passed to move() with the delta movement left
after move() (where restitution zeroes out colliding axes), not the
position delta travelled vs initial velocity.

Using post-move velocity prevents the crash sound from repeating on
subsequent ticks while pressed against a wall, while still playing the
single impact sound in both survival and creative mode.

Fixes #12304
2026-11-09 16:41:16 +03:00
199 changed files with 3171 additions and 4983 deletions

No files matched your search

+2
View File
@@ -198,3 +198,5 @@ new pushes, we add it again.
[Discord](https://discord.gg/playhorizon) for questions and ideas, [issues](https://github.com/horizon-rust/horizon/issues)
for bugs. To take something on, `/claim` its issue ([above](#claim-before-you-start)).
How Horizon is run, and how people join the Team or lead a group: [GOVERNANCE.md](GOVERNANCE.md).
+483
View File
@@ -0,0 +1,483 @@
# Horizon governance
> Adopted 2026-11-09 by the founder as his last decision as head of the project. It takes effect when he
> announces that he is stepping down. From then on only the council changes it, by a 2/3 poll (section 15).
Horizon has no boss. A **council of equals** decides by polls. **Theme groups** do the work in their areas, each
with a **lead**. The **Horizon Team** reviews and merges code. **Moderators** keep the Discord server and the
official server safe. Every role of trust is earned with work the project can measure, and it ends when that work
stops.
## Contents
1. [Principles](#1-principles)
2. [The levels at a glance](#2-the-levels-at-a-glance)
3. [Each level in detail](#3-each-level-in-detail)
4. [The council and its polls](#4-the-council-and-its-polls)
5. [The selection filter](#5-the-selection-filter)
6. [Theme groups](#6-theme-groups)
7. [Moderation and appeals](#7-moderation-and-appeals)
8. [Conflicts and hard cases](#8-conflicts-and-hard-cases)
9. [The age rule (18+)](#9-the-age-rule-18)
10. [The agents](#10-the-agents)
11. [Accounts and the handover path](#11-accounts-and-the-handover-path)
12. [Money](#12-money)
13. [Transparency](#13-transparency)
14. [Rules that are never voted on](#14-rules-that-are-never-voted-on)
15. [Changing this document](#15-changing-this-document)
## 1. Principles
- **Equals.** Every council member has one vote. Nobody, the founder included, stands above the others.
- **The founder.** Ludovic keeps the title of **Founder**: his role stays at the top of the member list and he is
credited as Horizon's founder everywhere. The title is symbolic. It carries no extra vote or power: on the council
he counts exactly like every other member.
- **Evidence, not popularity.** You get a role by doing the work first. Kira measures that work: merged pull
requests, reviews, triage, support answers and days active. A vote then confirms it.
- **Small, clear powers.** Each role can do a short, written list of things. Anything else goes to the council.
- **Roles are on loan.** Every role has a 30-day probation and an inactivity rule. Stepping down for inactivity is
not a sanction, and you can come back.
- **Public by default.** Polls, results and rules are public. Only matters about a person stay private, and even then
the result is published.
- **18+ for roles of trust** (section 9).
- **Mojang's and Microsoft's rules come first.** They are never put to a vote (section 14).
## 2. The levels at a glance
From the most open level to the most trusted. A person can hold several levels at once: a group lead can also be on
the Horizon Team, for example.
| Level | What it can do | How you get in | How you leave | 18+ |
| --- | --- | --- | --- | --- |
| **Member** | Play, chat, report bugs, suggest ideas, open issues and pull requests, pick group roles | Join the Discord server or the GitHub repo | Leave, or get banned | No |
| **Contributor** (⛏️ Iron, 🥇 Gold, 💎 Diamond, 🟪 Netherite ranks) | Write in #contributors; `/claim` issues; nominate people for group lead (if active in that group) | One merged pull request in a public horizon-rust repo, linked with `/link-github` and `/verify-github`. Ranks come from merged pull requests: 10, 40, 100 and 200 | Contributor status and ranks stay | No |
| **Group member** | Read and write in the group's channel; get the group's pings; take part in the group's advisory poll on its lead | Pick the group's role in Channels & Roles, or with `/groups` | Remove the role | No |
| **🤝 Support** | Answer and close posts in #horizon-support | `/apply`; vote of the mods and the Team (as today) | Resign, 30 days inactive, or removed by the Chief of Mods or the council | No |
| **🛡️ Moderator** | Time out, delete messages, manage threads, quarantine. No bans | `/apply`, then the selection filter; mods' vote; the council may object within 24 h | Resign, 30 days inactive, suspended by the Chief of Mods, removed by a council poll (simple majority) | **Yes** |
| **🛡️ Chief of Mods** | A moderator's powers, plus bans; leads the mods; suspends a mod at once pending the council | Council poll (simple majority), from the mods with at least 30 days | Resign, 30 days inactive, council poll (simple majority) | **Yes** |
| **🧭 Group lead** | Decides inside the group's topic (section 6); manages the group's channel; triage on the group's GitHub issues | Nomination, the filter, a 24 h public discussion with an advisory group poll, then a council poll (simple majority); 30 days probation | Resign, 30 days inactive (automatic), council poll (simple majority); confirmed again every 6 months | **Yes** |
| **🌌 Horizon Team** | Review and merge pull requests (GitHub `horizon-team`, write access); `/nightly` and triage commands (trusted reviewers); #horizon-team | Nomination, the filter, a 24 h public discussion, then a council poll (2/3); 30 days probation | Resign, 60 days without a merge or review (automatic), council poll (2/3, without the person) | **Yes** |
| **🏛️ Council** | Decides everything else by poll (section 4); bans; emergency actions by any 2 members | Nominated by a council member, the filter, a 24 h public discussion, then a council poll (2/3); 30 days probation | Resign, inactivity (section 5.5), council poll (2/3, without the person) | **Yes** |
**The account holder** isn't a level. The founder (Ludovic) still holds the project's accounts (GitHub organisation
owner, Discord server owner, the Microsoft app approved by Mojang, the domains, Railway, money). He carries out the
council's decisions on them and hands them over step by step (section 11). As a council member he has one vote,
like everyone else.
## 3. Each level in detail
### Member
Anyone in the Discord server or on GitHub. Members follow the server rules and Horizon's
[contributing guide](CONTRIBUTING.md). They can propose anything: an idea in #horizon-ideas, a bug in #horizon-bugs,
an issue or a pull request on GitHub, or a request for a council poll (any council member can pick it up).
### Contributor
- **Discord:** the 🛠️ Contributor role writes in #contributors and in the threads of #polls-and-decisions. A rank
role (⛏️ Iron at 10 merged pull requests, 🥇 Gold at 40, 💎 Diamond at 100, 🟪 Netherite at 200, counted over every
public horizon-rust repo) shows how much has been merged. Ranks only go up.
- **GitHub:** no repository role. Anyone can `/claim` and `/unclaim` their own issues.
- **Alone:** their own work.
### Group member
Each theme group (section 6) has a role that anyone can pick and drop. It opens the group's channel and receives the
group's pings. Picking a role grants no power. A group member counts as **active in the group** when Kira has seen at
least one counted action in the group's area (section 5.1) in the last 60 days. Only active group members can
nominate a lead or vote in the group's advisory poll.
### 🤝 Support
Unchanged: Support members help players in #horizon-support. They answer every post there and mark posts solved.
The role carries no permission, so it has no age rule. They join through `/apply`, and the mods and the Team vote.
### 🛡️ Moderators and the Chief of Mods
- **Discord:** time out members, delete messages, manage threads and nicknames, read the audit log, quarantine
through Kira, and see the staff channels. **Moderators don't ban.** Bans are done by council members and the Chief of
Mods. Kira's automatic actions (the honeypot, clear scams, illegal images) stay as they are.
- **Official server:** server operators (ops) are moderators in game. They need the 18+ rule and are confirmed the
same way (section 6, Server and SMP).
- **Alone:** a timeout, a deleted message, a quarantine, with a reason in the mod case.
- **The Chief of Mods** is the first contact for moderation questions. They organise the mods, can ban, and can take a
moderator's role away at once when there is a problem. The council confirms or reverses that within 72 hours.
### 🧭 Group leads
Section 6 says what a lead decides alone and what goes to the council.
- **Discord:** in their group's channel only, delete messages, manage and pin threads, and ping the group role. The
🧭 lead role carries no server-wide permission.
- **GitHub:** triage on the issues and pull requests that carry their group's label (`/label`, `/unlabel`, `/close`,
`/reopen`, `/unclaim`), from a list of group leads that grants no repository role. Leads merge only if they are on
the Horizon Team too.
### 🌌 Horizon Team
The Horizon Team **merges pull requests**. Its rules are in [the release flow](docs/release-flow.md): read the whole
diff, never merge your own pull request, and use `needs-proof` for anything risky.
- **GitHub:** member of the `horizon-team` team (write access to the Horizon repos), on the trusted reviewers list
(`/nightly` and triage commands).
- **Discord:** the 🌌 Horizon Team role, #horizon-team, and writing in #contributors and the read-only channels.
Moderation permissions belong to the moderators and the council: a Team member moderates only if they also hold
one of those roles.
- **During the 30-day probation:** they merge only ordinary pull requests. They don't merge `needs-proof` pull
requests, don't approve files that CODEOWNERS guards, and don't use `/nightly`.
### 🏛️ Council
- **Discord:** the 🏛️ Council role: the moderators' permissions plus ban and mention @everyone; #council (private);
starting polls in #polls-and-decisions.
- **GitHub:** the `council` team. Over time it takes over the founder's CODEOWNERS review and his owner powers in the
release tools (section 11).
- **Alone (any one member):** start a poll; pick up a member's request for a poll; do anything their other roles
allow.
- **Any two members together:** an emergency action (section 4.6).
- **Everything else** is decided by poll.
## 4. The council and its polls
### 4.1 Founding council
kacpherek, levzzz5154, rdbtCVS, Online5277, dezer-x and Ludovic: six members, one vote each. The founding members
don't go through the filter or a probation. They do make the 18+ declaration (section 9). The council has at most
**9** members. It adds a seat only when a 2/3 poll says it needs one.
### 4.2 How a poll works
| Rule | Value |
| --- | --- |
| Who starts one | Any council member, with `/poll` (Kira). Anyone else asks a council member to start it |
| Where | #polls-and-decisions, in public. Polls about a person (removal, appeals, the age rule) run in #council, and only their result is public |
| How long | 24 hours. It closes early only if every council member has voted |
| Ballot | Yes, No or Abstain. You can change it until the poll closes |
| Quorum | At least half of the council votes (Abstain counts). With 6 members, 3 votes |
| Simple majority | More Yes than No |
| Two-thirds | Yes is at least 2/3 of the Yes and No votes, **and at least 3 Yes votes** |
| Tie | Nothing changes |
| No quorum | Nothing changes. Kira reminds the members who haven't voted 12 hours and 2 hours before the end |
| About yourself | You don't vote, and you don't count in the council's size for that poll |
| Asking again | A poll that failed can't be asked again for 7 days, unless two members agree that new facts justify it |
### 4.3 Which threshold applies
| Simple majority | Two-thirds |
| --- | --- |
| Day-to-day project decisions: direction, priorities, settling disputes between groups, a public statement | Adding council members and Horizon Team members |
| Group leads and co-leads: appointing, removing, confirming every 6 months | Removing a council member or a Team member (without the person concerned) |
| Moderators, the Chief of Mods, Support: confirming, removing | Rules: this document, the server rules, the contributing policy, the licence |
| Ending a probation early | Money (section 12) |
| Confirming an emergency action | Account handover steps (section 11) |
| Second-level moderation appeals | Waiving part of the selection filter (section 5.4) |
| Bringing back someone who stepped down for inactivity, within 6 months | Changing the council's size |
**When in doubt, two-thirds.** Any council member can say a poll needs 2/3, and Kira then counts it at 2/3.
### 4.4 Discussion
Polls that add someone to the council, the Team or a lead post start with a **24-hour public discussion** (section
5.3). Other polls are discussed in their own thread while they run. A member who wants more time votes No and says
why. A failed poll can come back after 7 days.
### 4.5 Conflicts of interest
A member doesn't vote on a poll about themselves: their own role, their own removal, an appeal of their own
moderation action, or money paid to them. They say so in the poll's thread and Kira leaves them out of the count.
### 4.6 Emergencies
For **security** (a leaked secret, a malicious pull request or mod, a hijacked account), **Mojang or Microsoft** (a
request from them, a risk to the approved sign-in) or **legal** matters (a takedown, the law), **any two council
members act at once**. They may:
- pause releases and the Nightly;
- take a mod down from the registry;
- remove someone's roles or access for now;
- lock or hide channels and content;
- ask the account holder to rotate a secret or a key.
They record it with `/emergency` in Kira, and both of them confirm it there. Kira opens a council poll at once
(simple majority) to confirm it. If the poll doesn't pass, the action is undone where it can be. An emergency never
adds members, changes rules or spends money.
### 4.7 Removing a council member
A 2/3 poll of the other members, in #council. The person concerned doesn't vote and doesn't count in the quorum.
Only the result is published, never the reasons. Other ways to leave: resigning, inactivity (section 5.5), or a
false age declaration (section 9).
### 4.8 When the council drops below a quorum
- **Fewer than 5 members:** Kira opens nominations for the council at once. The council fills seats within 30 days.
- **Fewer than 3 members, or fewer than 3 who voted in the last 30 days:** an **interim council** forms. It counts the
remaining council members, the Horizon Team and the group leads past probation. Its only task is adding council
members, by its own 2/3 poll with a quorum of half. Any two of its members can take emergency actions. All other
decisions wait. The Team keeps merging and the leads keep leading.
- **Nobody left:** the Team and the group leads form the interim council in the same way.
## 5. The selection filter
Nobody becomes a lead, a Team member or a council member just because they are well liked or talk a lot. Kira
measures the work, and only people above a floor can be nominated. The council then decides among them.
### 5.1 What Kira measures
| Signal | What counts | Source |
| --- | --- | --- |
| **Merged pull requests** | Pull requests merged in a public horizon-rust repo. For Modding, also in the mod API's fork (arismoko/horizon). Counted overall, and per group by label or by files touched | GitHub search, as the ranks are counted today |
| **Reviews** | Others' pull requests you reviewed: approved, asked for changes, or left a review with comments. One per pull request | GitHub search `reviewed-by:` and Kira's GitHub webhook |
| **Triage** | Triage commands run (`/label`, `/close`, duplicates), issues labelled or closed, bug posts routed on Discord | The triage workflow's comments and Kira's webhook |
| **Support answers** | #horizon-support posts you answered that ended solved | Kira's support feature |
| **Active days** | Distinct days with any of the above, or with messages in #contributors or a group's channel. Chat elsewhere doesn't count | Kira |
| **Tenure** | Days since your first counted contribution (since you joined the server, for moderators) | GitHub, Discord |
| **Clean record** | No timeout, quarantine or ban in the last 90 days | Kira's mod cases |
| **Verified GitHub** | `/verify-github` done | Kira |
| **18+ declaration** | Made (section 9) | Kira |
Kira turns these into an **evidence card**: the person's numbers, overall and in the group's area, for the last 60
days and in total. Anyone can see their own card with `/evidence`. A nomination shows the card publicly.
### 5.2 The floors
A nomination is refused below these floors.
| Role | Floor |
| --- | --- |
| **Group lead** | Verified GitHub; tenure of 30 days or more; **in the group's area: 8 or more merged pull requests, or 20 or more reviews** (Translations: 5 or more merged translation pull requests; Server and SMP: 8 pull requests, or 30 days as an official server operator with activity); 15 or more active days in the last 60; clean record; 18+ |
| **Moderator** | In the server for 30 days or more; Kira level 10 or more; 15 or more active days in the last 60; clean record; 18+ |
| **Chief of Mods** | Moderator for 30 days or more, past probation; 18+ |
| **Horizon Team** | 🥇 Gold rank (40 merged pull requests); 20 or more reviews of others' pull requests; tenure of 30 days or more; 20 or more active days in the last 60; clean record; verified GitHub; 18+ |
| **Council** | Horizon Team member, group lead or Chief of Mods for 60 days or more, past probation; 20 or more active days in the last 60; clean record; 18+ |
The numbers are checked again once a year (section 15). They should stay reachable for people who really work on
Horizon and out of reach for people who don't.
### 5.3 The path to a role
1. **Nomination.** Run `/nominate member: role: [group:]` in Kira.
- A **group lead** can be nominated by an active member of that group or by a council member. A self-nomination
needs a second from another active group member or a council member.
- A **Team member** can be nominated by a council or Team member. Someone can also nominate themselves with
`/apply`, if a council or Team member sponsors them.
- A **council member** can only be nominated by a council member.
- **Moderators** apply with `/apply`.
2. **The filter.** Kira checks the floor and the 18+ declaration. Below the floor, Kira refuses and says which line
is short.
3. **Public discussion, 24 hours.** Kira posts the nomination and the evidence card in a thread of
#polls-and-decisions. Contributors and the council can comment. For a lead, Kira also runs an **advisory poll** in
the group's channel for the same 24 hours. Only active group members vote in it, and the council sees the result.
4. **Council poll, 24 hours.** Simple majority for a lead, 2/3 for the Team and the council. For moderators, the mods'
vote replaces this step, and any two council members can object within 24 hours; the council then decides by poll.
5. **Probation, 30 days.** The role is held in full, except for the Team limits in section 3. At day 25, Kira asks the
council in #council whether anything is wrong. Probation ends by itself at day 30, unless a council poll (simple
majority) ended it earlier.
### 5.4 Exceptions
Some valuable people don't show up in the numbers, such as a designer for the website. The council can **waive the
tenure or the area floors** by a 2/3 poll that says why. The age rule and the clean record are never waived.
### 5.5 Inactivity
Kira checks every day. It warns the person in a DM and in #council, then posts the step-down in
#polls-and-decisions with neutral wording ("stepped down: inactive"), and removes the Discord role. The account
holder or an org owner removes GitHub access when the Team role ends.
| Role | What counts as activity | Warning | Steps down |
| --- | --- | --- | --- |
| Group lead | A counted action in the group's area, or messages in the group's channel | Day 21 | Day 30 |
| Horizon Team | A merge or a review | Day 45 | Day 60 |
| Moderator, Chief of Mods | A moderation action, or messages in the staff channels | Day 21 | Day 30 |
| Support | An answer in #horizon-support | Day 21 | Day 30 |
| Council | A vote in a poll. At 30 days with no vote, while at least 2 polls were held | Day 23 | Day 30, or 45 days with no counted activity at all |
- **Away.** Anyone can announce an absence with `/away` for up to 45 days, once every 6 months. Away days don't
count. A lead names someone from the group to cover for them.
- **Coming back.** Within 6 months: a simple-majority poll, with no new probation. After 6 months: the normal path.
### 5.6 Terms
- **Group leads** are confirmed every 6 months by a simple-majority poll. If someone else in the group passes the
floor and is nominated, both go on the same poll.
- **Council and Team** have no fixed term. They stay as long as they are active and keep the council's trust. Removal
is always possible (section 4.7).
## 6. Theme groups
### 6.1 The groups
| Group | Covers | GitHub | Discord |
| --- | --- | --- | --- |
| **Modding** | The mod API, native and content mods, mixins, the mod registry, `cargo horizon-mod` | The mod API lives in Ari's fork **arismoko/horizon**. Its owner runs that repo by their own rules; the council governs only what is Horizon's: horizon-rust/horizon-mods, horizon-mixins, horizon-native-mod-template, the registry. Label `mods` | The 🧩 MODDING category (#modding, #horizon-modding-team); roles 🧩 Modder (picked) and 🧩 Horizon Modding Team (the lead gives it) |
| **Shaders and rendering** | The renderer, shaders, shader packs, OptiFine and Polytone pack formats | Label `rendering`; `crates/horizon-client-render` (gfx), `*.wgsl`, `horizon-shaders`, `horizon-shader-api`, `horizon-optifine`, `horizon-polytone` | #shaders-rendering |
| **Performance** | Frame rate, memory, server tick, benchmarks | Label `perf`; `horizon-bench`, the benchmark tools | #performance |
| **Launcher** | The launcher: installs, updates, instances, its pages | Label `launcher`; `launcher/` | #launcher |
| **Server and SMP** | Dedicated server, hosting, the anticheat, multiplayer, and the official SMP | Labels `server`, `multiplayer`; `horizon-server*`, `horizon-anticheat`, `lan/`, `dedicated*`; horizon-rust/horizon-server | #server-smp (plus #join-server, #server-chat) |
| **Translations** | The game's and the launcher's languages | Label `roadmap:languages`; `launcher/lang/`, `crates/horizon-client/assets/horizon/lang/` | #translations and the 🌍 language channels |
| **Website** | playhorizon.dev | horizon-rust/horizon-site; label `website`. The site's design stays as it is unless the council decides otherwise | #website |
| **Vanilla accuracy** | Parity with vanilla 26.3: harnesses, oracles, the port ledger | Labels `parity`, `parity-regression`, `full-parity`; `tools/test_*_parity.py`, the Java oracles | #vanilla-accuracy |
| **UI** | The game's menus, HUD, settings, controller navigation, the design system | Labels `ui`, `accessibility`; `title/`, `settings_shell.rs`, `hud*`, `ui.rs`, `docs/design-system.md`, `horizon-theme`. The launcher's look is shared with Launcher | #ui |
A pull request can belong to two groups. Both leads can comment, and the Team merges as usual. If the leads disagree,
the council decides.
### 6.2 Leads per group
- **One lead per group.** A group with 8 or more active members may also have **one co-lead**, chosen the same way.
- A person leads **at most two groups**. Council members may lead a group, though a lead from outside the council is
preferred: it spreads the work.
### 6.3 What a lead decides alone
Inside their group's topic, and within this document, the contributing guide, the vanilla-first rule, the layers and
the design system:
- the group's priorities and the order of its roadmap items;
- which issues are `good first issue`, and triage of the group's issues;
- technical and design direction inside the area, when vanilla behaviour and the default look don't change;
- accepting or declining an idea or a proposal in the area. Any two active group members or one council member can
take that decision to the council;
- how the group organises itself (threads, meetings, the channel's rules on top of the server's);
- asking the Team for reviews, adding `needs-proof`, and nominating people.
### 6.4 What goes to the council
- the rules, money, accounts and secrets;
- who is on the council, the Team or the mods;
- anything that changes vanilla behaviour or turns a Horizon-only feature on by default;
- breaking a public promise: the mod API, server compatibility, save and file formats;
- disputes between groups;
- anything involving Mojang, Microsoft or the law;
- speaking for the whole project outside the group's topic.
### 6.5 A group without a lead
The work goes on. The Team reviews and merges, and Kira still routes the group's issues and questions to its
channel. Until a lead is chosen, any council member may take a lead's decision for that group and says so in the
channel. Kira pins a "lead wanted" note with the floor. **No lead is better than a lead who doesn't do the work:**
nobody is appointed just to fill the seat.
## 7. Moderation and appeals
- **The server rules** are in #rules. Moderators enforce them, the Chief of Mods leads the mods, and the council can
change the rules (2/3).
- **Every action has a mod case**: who acted, what they did, and why. Kira keeps the cases.
- **First appeal:** within 14 days, through #appeal (for a quarantine) or mod mail. A moderator who wasn't involved,
or the Chief of Mods, answers within 72 hours.
- **Second appeal:** for bans, timeouts over 24 hours and quarantines, a council poll in #council (simple majority).
Members who were involved don't vote. The answer is final for 90 days.
- **Not appealable here:** actions that Discord's rules or the law require. Those are reported where the law says.
- **Removing a moderator:** the Chief of Mods can suspend a moderator at once, and the council decides within 72 hours
(simple majority). The council removes the Chief of Mods the same way.
- **Staff are moderated like everyone.** When a council member is involved, the council decides without them.
## 8. Conflicts and hard cases
| Case | What happens |
| --- | --- |
| Two groups disagree | The leads talk first. If they still disagree, the council decides (simple majority) |
| A lead's decision is contested | Any two active group members or one council member can bring it to the council |
| A Team member merges against the rules | Any council member can revert the merge. The council can remove the member (2/3) |
| A council member breaks the rules | The council decides without them. Removal takes 2/3 (section 4.7) |
| Someone holds a role and is under 18 | Section 9 |
| The council can't reach quorum | Section 4.8 |
| The founder and the council disagree about one of his own accounts | Until a step of section 11 hands it over, the account stays his. He carries out the council's decisions on project matters, or he says publicly that he won't |
## 9. The age rule (18+)
**Who must be 18 or older:** members of the council and the Horizon Team, trusted reviewers, group leads and
co-leads, the Chief of Mods and the moderators, official server operators, and anyone with admin rights anywhere in
the project: Discord (Administrator, Manage Roles, Manage Channels, ban), GitHub (write, admin, organisation),
server panels, Railway, or Kira's admin side. The same goes for anyone who holds a project secret.
**Who doesn't have to be:** members, contributors (with any rank), group members and 🤝 Support. Contributors under
18 are welcome and valued. They just can't hold the roles above.
**How it's checked, without collecting ID:**
- **A declaration.** Before taking such a role, and once at the start for everyone who holds one, the person presses
a button in Kira: "I confirm that I am 18 or older. I understand that a false declaration removes all my roles of
trust." Kira keeps only the Discord account, the date and the wording's version. It never stores a birth date, an
ID, a photo, or any outside age-checking service's result.
- **No declaration, no role.** At the start, current role holders have 7 days to make it. Until they do, their role is
paused.
- **When there's doubt** (the person says they are younger, or there is a credible private report), one council
member asks the person privately. If the doubt remains, any council member pauses the role, and the council decides
within 72 hours in #council.
- **A false declaration** removes every role of trust at once, and the person can't hold one for 12 months.
- **Privacy.** Age is never discussed in public. A role that ends for this reason ends with the same neutral line as
any other step-down.
## 10. The agents
Horizon uses AI agents: the founder's orchestrator, which runs coding agents, and Kira, the Discord bot.
- **They obey council decisions only:** a passed poll recorded by Kira, a recorded emergency action of two council
members, and the standing rules in this document and the project's docs.
- **The only exception is the founder's own things:** his spending, his machines (they run CI and the vanilla tests),
his personal accounts and his time. On those, his word decides. This list should get shorter over time (section 11).
- **Role work isn't a decision.** A lead asking Kira to route issues, or a Team member asking an agent to prove a pull
request, is that person using their role. The agents help, within the role's powers.
- **They check the source.** An agent acts on a decision only when it finds it in Kira's decisions log
(section 13). A message saying "the council decided", or a screenshot, is not enough.
- **They post as agents.** Everything an agent posts says it comes from an agent, and states decisions as the
project's.
## 11. Accounts and the handover path
Today the founder holds every account. The aim is for him to hold fewer, in an order that never leaves the project
unable to act, and never puts an account that is tied to a person into anyone else's hands.
| Account | Today | Can it be shared? | Plan |
| --- | --- | --- | --- |
| **GitHub organisation** (horizon-rust) | One owner (the founder) | Yes: an organisation can have several owners | **Step 1:** a second owner from the council, chosen by a 2/3 poll in the council's first week, with two-factor authentication on. **Step 2:** a `council` team; CODEOWNERS reviews and the release tools' owner powers (`paused`, `/nightly remove`) move from the founder to that team |
| **Discord server** | Owned by the founder | Partly: a server has exactly one owner; powers can be given through roles | **Step 1:** the 🏛️ Council role gets moderation and ban permissions; Kira applies the outcomes of passed polls, so nobody needs Manage Roles; two-factor authentication becomes required for moderation. Ownership itself stays with the founder until a legal entity exists |
| **Kira** (bot application, Railway service) | The founder's Discord developer account and Railway | The bot: yes (a Discord developer team). Railway: adding members may need a paid plan | **Step 1:** a Discord developer team with two council members. Railway members once the council decides on money |
| **Official server** (hosting panel) | The founder's account | Yes: panel sub-users | **Step 1:** sub-users for the Server and SMP lead and for one council member |
| **Domains** (playhorizon.dev and the others) | The founder's registrar account | Not without moving it | Auto-renewal on, registered for several years ahead. They move only to a legal entity, if one is created |
| **The Microsoft app approved by Mojang** (sign-in) | The founder's Azure app registration; Mojang approved it after his application | **No.** The approval was given on his application. Moving the app or adding owners would change who Mojang deals with, and we have found no documented way to transfer an approval | **Never moves** without Mojang's written agreement. The only change considered: a legal entity, if one is created, and only if Mojang agrees |
| **Signing** (Apple developer certificate, release signing keys) | The founder's | The Apple certificate is in his legal name: no | The Apple certificate never moves. Release keys stay in GitHub's protected environments, and the council team approves their use from step 2 |
| **Money** (sponsorship, donations) | Personal accounts of the founder | Through a fiscal host | Section 12 |
| **The founder's machines, AI accounts and password vault** | His | No | His own things: they never move. The project should depend on them less over time |
**Order:** first the safety nets that remove a single point of failure (a second organisation owner, the bot's
developer team, panel sub-users). Then the day-to-day powers (CODEOWNERS and release tools to the council team). Last,
whatever needs a legal entity: domains, money, and with Mojang's agreement the sign-in app. Each step is a 2/3 poll,
and the founder carries it out.
## 12. Money
*Placeholder: the options (Open Collective and others) are being researched.*
- The council approves every expense by a **2/3 poll**.
- **Every income and every expense is public.**
- Nobody votes on money paid to themselves.
## 13. Transparency
- **#polls-and-decisions:** every poll and every result, posted by Kira, and the 24-hour discussions of nominations.
For polls that aren't about a person, each member's vote is shown once the poll closes.
- **The decisions log:** Kira keeps an append-only record of every poll, emergency action, appointment and
step-down, with its date and result. It is public and machine-readable, so the agents can check a decision there.
- **This document** lives in horizon-rust/horizon as `GOVERNANCE.md`. A short summary is pinned in #rules and in
#polls-and-decisions.
- **Who holds which role:** the people page of playhorizon.dev's hub shows the council, the Team, the group leads,
the Chief of Mods, the moderators and Support.
- **#council** is private for discussion and for polls about people. Everything the council decides is published.
## 14. Rules that are never voted on
These are Horizon's conditions for existing, not choices. No poll can change them:
- Playing needs a **Microsoft account that owns Minecraft: Java Edition**. There is no play without one.
- **No Mojang files** in Horizon's repos or downloads. Players' own copies stay on their own machines.
- **No gambling**, in any form, including with in-game currency.
- **Mojang's and Microsoft's terms and Usage Guidelines** apply to everything Horizon does.
- **The law**, and the terms of service of Discord and GitHub.
## 15. Changing this document
A 2/3 council poll, then a pull request that a Team member merges. The council reviews the floors' numbers
(section 5.2) once a year, or sooner if they turn out wrong.
+2
View File
@@ -135,6 +135,8 @@ python3 tools/pr_ready.py
It runs rustfmt, clippy, the touched crates' tests, the Python tests, the public-tree check and the vanilla harnesses your change affects. Never commit game files, decompiled source or prepared resources.
How Horizon is run (the council, theme groups and their leads, the Horizon Team, moderation): [GOVERNANCE.md](GOVERNANCE.md).
## Project status
**Player-visible gaps: 0 open** of the 833 the [port ledger](tools/port_ledger.py) found, reading every vanilla 26.3 method against Horizon's code: vanilla behaviour a player would notice that Horizon doesn't have yet. By area: Animals [0](https://github.com/horizon-rust/horizon/issues/3512); Monsters and bosses [0](https://github.com/horizon-rust/horizon/issues/3513); Entities, projectiles, vehicles and decorations [0](https://github.com/horizon-rust/horizon/issues/3514); Items, enchantments and inventories [0](https://github.com/horizon-rust/horizon/issues/3515); Blocks, redstone and fluids [0](https://github.com/horizon-rust/horizon/issues/3516); World, world generation and saves [0](https://github.com/horizon-rust/horizon/issues/3517); Screens, HUD and client packets [0](https://github.com/horizon-rust/horizon/issues/3518); Entity and block rendering, models [0](https://github.com/horizon-rust/horizon/issues/3519); Server and players on the server [0](https://github.com/horizon-rust/horizon/issues/3520); Mob AI, villagers and raids [0](https://github.com/horizon-rust/horizon/issues/3521). This number goes down as gaps close (`tools/parity_gaps.py`); the table below says what the harnesses compare.
@@ -1441,6 +1441,16 @@ pub enum Rumble {
},
Totem,
}
impl From<crate::input_source::Feedback> for Rumble {
fn from(event: crate::input_source::Feedback) -> Self {
use crate::input_source::Feedback;
match event {
Feedback::BlockBroken => Rumble::BlockBroken,
Feedback::Explosion { distance, radius } => Rumble::Explosion { distance, radius },
Feedback::Totem => Rumble::Totem,
}
}
}
/// A vibration: the heavy (low-frequency) and light motors, 0..1, and how
/// long it lasts.
#[derive(Clone, Copy, Debug, PartialEq)]
@@ -0,0 +1,15 @@
//! The engine's side of the input source (docs/layers.md, "Controllers, splitscreen, replays and
//! UI pages"): what gameplay tells a device beyond the keyboard and mouse. Gameplay names these
//! types, never a controller's; the controller code answers.
/// Something that happened to the player that a device may let them feel (a controller's
/// vibration). The device decides how, or whether.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Feedback {
/// The player broke a block.
BlockBroken,
/// An explosion this far away (blocks) with this power.
Explosion { distance: f64, radius: f32 },
/// A totem of undying saved the player.
Totem,
}
+1
View File
@@ -9,6 +9,7 @@ pub mod gamepad;
pub mod gameplay_guide;
pub mod held;
pub mod input;
pub mod input_source;
pub mod interaction_input;
pub mod key_names;
pub mod keybinds;
+4
View File
@@ -76,6 +76,10 @@ wgpu = { version = "30.0.1", default-features = false, features = ["gles"] }
audio = ["dep:cpal"]
# Helpers horizon-client's tests build their fixtures with.
test-support = []
# horizon-client's `horizon-extras`: asking the device for hardware ray tracing on request
# (`gfx/ray_query.rs`, `HORIZON_RAY_TRACING=1`). Without it the device is requested as without
# the variable.
horizon-extras = []
[lints]
workspace = true
@@ -0,0 +1,158 @@
//! Audio occlusion, attenuation and mixing benchmark.
//! Run with: `cargo run --profile fast -p horizon-client-render --example audio_bench`
use horizon_client_render::{
audio::Audio,
sound_engine::{MobSound, SoundInstance, Sounds, TickContext},
};
use std::{path::Path, time::Instant};
fn main() {
println!("=== Horizon Audio Attenuation & Mixing Benchmark ===");
let mut audio = Audio::silent(Path::new("/nonexistent"));
audio.engine.loaded = true;
audio.backend_live_for_bench();
audio.record_heard = false;
// Register a sound event with attenuation distance 16
audio.engine.registry.add_file(
"minecraft",
br#"{"bench.loop":{"attenuation_distance":16,"sounds":[{"name":"bench/loop","stream":false}]}}"#,
&|_, _| true,
);
// Insert 1 second of audio into cache (48000 mono samples)
let samples: Vec<f32> = (0..48_000)
.map(|i| ((i as f32) * 440.0 * 2.0 * std::f32::consts::PI / 48000.0).sin() * 0.5)
.collect();
audio.insert_cached_sound("minecraft:bench/loop", samples, 48_000, 1);
// 1. Benchmark set_listener (called every client render frame)
let listener_iterations = 200_000;
let start = Instant::now();
for i in 0..listener_iterations {
let angle = (i as f32) * 0.01;
audio.set_listener(
[
100.0 + (angle.cos() as f64) * 5.0,
64.0,
200.0 + (angle.sin() as f64) * 5.0,
],
angle,
0.0,
);
}
let listener_elapsed = start.elapsed();
println!(
"1. set_listener moving (render frame): {:?} for {} calls ({:.2} ns/call)",
listener_elapsed,
listener_iterations,
(listener_elapsed.as_nanos() as f64) / (listener_iterations as f64)
);
// 1b. Benchmark set_listener stationary (lock elimination early-out)
let stationary_iterations = 200_000;
let start = Instant::now();
for _ in 0..stationary_iterations {
audio.set_listener([100.0, 64.0, 200.0], 0.0, 0.0);
}
let stationary_elapsed = start.elapsed();
println!(
"1b. set_listener stationary (lock early-out): {:?} for {} calls ({:.2} ns/call)",
stationary_elapsed,
stationary_iterations,
(stationary_elapsed.as_nanos() as f64) / (stationary_iterations as f64)
);
// 2. Play 128 sounds in the world at various distances from listener at [100.0, 64.0, 200.0]
// 64 sounds within attenuation distance (<16 blocks)
// 64 sounds outside attenuation distance (>16 blocks)
for i in 0..128 {
let dist = if i < 64 {
(i as f64) * 0.24 // 0 to 15.1 blocks (audible)
} else {
17.0 + ((i - 64) as f64) * 1.5 // 17 to 111.5 blocks (out of attenuation range)
};
let pos = [100.0 + dist, 64.0, 200.0];
let instance = SoundInstance::new(
"minecraft:bench.loop",
crate_sound_source(i),
1.0,
1.0,
horizon_core::random::LegacyRandom::new(i as i64),
true, // looping
0,
horizon_client_render::sound_engine::Attenuation::Linear,
pos,
false,
);
audio.play_instance(instance, false);
}
// 3. Benchmark mix_buffer (5000 buffers of 1024 stereo frames @ 48kHz = ~106 seconds of audio mixing)
let mut buffer = vec![0.0f32; 1024 * 2];
let mix_iterations = 5_000;
let start = Instant::now();
for _ in 0..mix_iterations {
audio.mix_buffer(&mut buffer, 2, 48_000);
}
let mix_elapsed = start.elapsed();
println!(
"2. mix_buffer (128 active channels, 1024 stereo frames): {:?} for {} buffers ({:.2} µs/buffer)",
mix_elapsed,
mix_iterations,
(mix_elapsed.as_micros() as f64) / (mix_iterations as f64)
);
// 4. Benchmark SoundEngine::tick with ticking mob sounds
let mut mobs = Vec::new();
for i in 0..64 {
mobs.push(MobSound {
id: 2000 + i,
position: [100.0 + (i as f64) * 0.5, 64.0, 200.0 + (i as f64) * 0.5],
speed: 0.25,
baby: false,
angry: i % 2 == 0,
silent: false,
attack_scale: 0.5,
sniffer_digging: false,
});
}
let tick_ctx = TickContext {
player_underwater: false,
player_removed: false,
vehicle: None,
carts: Vec::new(),
mobs: mobs.clone(),
frozen: false,
player_position: [100.0, 64.0, 200.0],
player_speed_sqr: 0.1,
player_fall_flying: false,
ridden: None,
camera_position: [100.0, 64.0, 200.0],
};
let tick_iterations = 10_000;
let start = Instant::now();
for _ in 0..tick_iterations {
audio.tick(false, &tick_ctx);
}
let tick_elapsed = start.elapsed();
println!(
"3. SoundEngine::tick (64 channels + ticking): {:?} for {} ticks ({:.2} µs/tick)",
tick_elapsed,
tick_iterations,
(tick_elapsed.as_micros() as f64) / (tick_iterations as f64)
);
}
fn crate_sound_source(i: u32) -> usize {
match i % 6 {
0 => 0, // master
1 => 1, // music
2 => 2, // records
3 => 3, // weather
4 => 4, // blocks
_ => 5, // hostile
}
}
+2 -2
View File
@@ -382,8 +382,8 @@ impl RenderAssets {
};
// After the connected tiles: a tile identical to a block shares its layer, and the
// overlays skip shared layers.
if draws {
emissive = crate::native_emissive::load_optifine(root, &mut sprites);
if draws && let Some(suffix) = crate::pack_hooks::formats().emissive_suffix(root) {
emissive = crate::native_emissive::load_overlays(root, &suffix, &mut sprites);
}
sprites.save_disk_cache();
if draws {
@@ -233,11 +233,11 @@ pub fn texture_path(root: &Path, texture: &str, directory: &str) -> PathBuf {
}
let (namespace, path) = texture.split_once(':').unwrap_or(("minecraft", texture));
let rel = format!("assets/{namespace}/{directory}/{path}.png");
root.join(if horizon_optifine::paths::valid(&rel) {
&rel
} else {
NOWHERE
})
// No `.`, `..` or empty segment, and no `\` (a separator on Windows, where `..\..` climbs).
let stays = rel
.split('/')
.all(|segment| !matches!(segment, "" | "." | "..") && !segment.contains('\\'));
root.join(if stays { &rel } else { NOWHERE })
}
/// `SpriteSourceList.list`: every sprite id of the atlas and its origin.
+167 -53
View File
@@ -478,6 +478,7 @@ pub struct Audio {
pub record_heard: bool,
pub listener: [f64; 3],
pub listener_yaw: f32,
pub listener_pitch: f32,
pub master: f32,
/// Seeds of positional plays (the client level random's `nextLong`).
random: LegacyRandom,
@@ -722,6 +723,29 @@ impl Backend for MixerBackend {
fn set_unmuffled(&mut self, channel: ChannelId, unmuffled: bool) {
self.with(channel, |c| c.unmuffled = unmuffled);
}
fn update_channel(&mut self, channel: ChannelId, volume: f32, pitch: f32, position: [f64; 3]) {
if let Ok(mut m) = self.mixer.lock()
&& let Some(c) = m.channels.get_mut(&channel)
{
c.gain = volume;
c.pitch = pitch;
c.at = [position[0] as f32, position[1] as f32, position[2] as f32];
}
}
fn filter_stopped(&mut self, live: &[(u64, ChannelId)], stopped: &mut Vec<u64>) {
if let Ok(m) = self.mixer.lock() {
for &(h, c) in live {
if m.channels
.get(&c)
.is_none_or(|ch| ch.state == State::Stopped)
{
stopped.push(h);
}
}
} else {
stopped.extend(live.iter().map(|&(h, _)| h));
}
}
/// `getCompleteBuffer` (cached, else decoded on the decoder thread) or
/// `getStream` (decoded on a thread of its own), then attach and
/// `alSourcePlay`. A sound that cannot load leaves its source initial,
@@ -822,18 +846,24 @@ impl Backend for MixerBackend {
/// pinned client's) rendered through `ALC_SOFT_loopback` within 1e-5.
fn stereo_gains(right: f32, up: f32, forward: f32) -> [f32; 2] {
let length = (right * right + up * up + forward * forward).sqrt();
stereo_gains_with_length(right, up, forward, length)
}
#[inline]
fn stereo_gains_with_length(right: f32, up: f32, forward: f32, length: f32) -> [f32; 2] {
if length <= f32::EPSILON {
return stereo_gains(0.0, 0.0, 1.0);
return stereo_gains_with_length(0.0, 0.0, 1.0, 1.0);
}
let elevation = (up / length).clamp(-1.0, 1.0).asin();
let u = (up / length).clamp(-1.0, 1.0);
let cos_elev = (1.0 - u * u).max(0.0).sqrt();
let mut azimuth = right.atan2(forward);
if azimuth.abs() < std::f32::consts::FRAC_PI_2 {
azimuth = (azimuth.abs() * 1.5)
.min(std::f32::consts::FRAC_PI_2)
.copysign(azimuth);
}
let side = azimuth.sin() * elevation.cos();
let front = azimuth.cos() * elevation.cos() * 0.095_660_8;
let (sin_az, cos_az) = azimuth.sin_cos();
let side = sin_az * cos_elev;
let front = cos_az * cos_elev * 0.095_660_8;
[0.5 - 0.5 * side + front, 0.5 + 0.5 * side + front]
}
/// The gain OpenAL applies for distance (`AL_LINEAR_DISTANCE` with reference
@@ -853,16 +883,10 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
// and OpenAL's right = forward x up.
let basis = |yaw: f32, pitch: f32| {
let (yaw, pitch) = (f64::from(yaw.to_radians()), f64::from(pitch.to_radians()));
let forward = [
-yaw.sin() * pitch.cos(),
-pitch.sin(),
yaw.cos() * pitch.cos(),
];
let up = [
-yaw.sin() * pitch.sin(),
pitch.cos(),
yaw.cos() * pitch.sin(),
];
let (yaw_sin, yaw_cos) = yaw.sin_cos();
let (pitch_sin, pitch_cos) = pitch.sin_cos();
let forward = [-yaw_sin * pitch_cos, -pitch_sin, yaw_cos * pitch_cos];
let up = [-yaw_sin * pitch_sin, pitch_cos, yaw_cos * pitch_sin];
let right = [
forward[1] * up[2] - forward[2] * up[1],
forward[2] * up[0] - forward[0] * up[2],
@@ -896,7 +920,7 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
// Gains and pans per source for this buffer.
let mut voices = std::mem::take(&mut mixer.voices);
voices.clear();
for (id, c) in &mixer.channels {
for (id, c) in &mut mixer.channels {
let Some((_, source_rate, source_channels)) = &c.samples else {
continue;
};
@@ -907,6 +931,7 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
if c.state != State::Playing {
continue;
}
let at = [f64::from(c.at[0]), f64::from(c.at[1]), f64::from(c.at[2])];
let away = |listener: [f64; 3]| {
[
@@ -915,45 +940,56 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
at[2] - listener[2],
]
};
let length = |d: [f64; 3]| d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
// The nearest camera hears it (one camera but in splitscreen).
let camera = mixer
.cameras
.iter()
.filter(|camera| c.relative || camera.2 == c.world)
.min_by(|a, b| length(away(a.0)).total_cmp(&length(away(b.0))))
.map(|camera| (camera.0, camera.1));
// Unheard sources still advance: returning to a world must not resume stale sounds.
let length_sq = |d: [f64; 3]| d[0] * d[0] + d[1] * d[1] + d[2] * d[2];
let camera = if !shared {
let cam = &mixer.cameras[0];
if c.relative || cam.2 == c.world {
Some((cam.0, cam.1))
} else {
None
}
} else {
mixer
.cameras
.iter()
.filter(|camera| c.relative || camera.2 == c.world)
.min_by(|a, b| length_sq(away(a.0)).total_cmp(&length_sq(away(b.0))))
.map(|camera| (camera.0, camera.1))
};
let (listener, (forward, up, right)) = camera.unwrap_or(([0.0; 3], basis(0.0, 0.0)));
let d = if c.relative { at } else { away(listener) };
let distance = (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]).sqrt() as f32;
let gain = if camera.is_some() {
c.gain.clamp(0.0, 1.0)
* if direct {
1.0
} else {
distance_gain(c.linear, distance)
let d_sqr = length_sq(d);
let (gain, [left, right]) = if camera.is_none() {
(0.0, [0.0, 0.0])
} else if direct {
let gain = c.gain.clamp(0.0, 1.0);
(gain, [gain, gain])
} else {
let mut zero = false;
if let Some(max) = c.linear {
let max_d = max as f64;
if max <= 0.0 || (!c.relative && d_sqr >= max_d * max_d) {
zero = true;
}
} else {
0.0
};
let [left, right] = if direct {
[gain, gain]
} else {
// Relative sources are already in OpenAL's listener space (-Z ahead).
let [mut left, mut right] = if c.relative {
stereo_gains(d[0] as f32, d[1] as f32, -d[2] as f32)
} else {
stereo_gains(dot(d, right), dot(d, up), dot(d, forward))
};
if shared {
// Several players on the speakers: half the stereo width, as left and right are
// nobody's in particular.
let middle = (left + right) / 2.0;
left = middle + (left - middle) / 2.0;
right = middle + (right - middle) / 2.0;
}
[left * gain, right * gain]
if zero {
(0.0, [0.0, 0.0])
} else {
let distance = d_sqr.sqrt() as f32;
let gain = c.gain.clamp(0.0, 1.0) * distance_gain(c.linear, distance);
let [mut left, mut right] = if c.relative {
stereo_gains_with_length(d[0] as f32, d[1] as f32, -d[2] as f32, distance)
} else {
stereo_gains_with_length(dot(d, right), dot(d, up), dot(d, forward), distance)
};
if shared {
let middle = (left + right) * 0.5;
left = middle + (left - middle) * 0.5;
right = middle + (right - middle) * 0.5;
}
(gain, [left * gain, right * gain])
}
};
let step = f64::from(*source_rate) / f64::from(rate) * f64::from(c.pitch.max(0.0));
voices.push((*id, [left, right, gain], step));
@@ -974,6 +1010,40 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
};
let source_channels = source_channels as usize;
let frames = samples.len() / source_channels;
let inaudible = if channels >= 2 {
left == 0.0 && right == 0.0
} else {
gain == 0.0
};
if inaudible {
let buffer_frames = data.len() / channels;
// As the loop below: a sound of one frame or none stops, looping or not.
if !c.looping || frames <= 1 {
// `frames` may be 0: no `frames - 1` in usize. A step of 0 never
// reaches the end, as in the loop below.
let needed = frames as f64 - 1.0 - c.position;
if needed <= 0.0 {
c.state = State::Stopped;
} else if step > 0.0 {
let steps_to_stop = needed / step;
if (buffer_frames as f64) >= steps_to_stop {
c.state = State::Stopped;
} else {
c.position += step * (buffer_frames as f64);
}
}
} else {
for _ in 0..buffer_frames {
let i = c.position as usize;
if i + 1 >= frames {
c.position = 0.0;
}
c.position += step;
}
}
continue;
}
let out: &mut [f32] = if muffling && !c.unmuffled {
&mut bus
} else {
@@ -992,8 +1062,8 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
}
let t = (c.position - i as f64) as f32;
if source_channels > 1 {
let l = samples[i * 2] * (1.0 - t) + samples[(i + 1) * 2] * t;
let r = samples[i * 2 + 1] * (1.0 - t) + samples[(i + 1) * 2 + 1] * t;
let l = samples[i * 2] + (samples[(i + 1) * 2] - samples[i * 2]) * t;
let r = samples[i * 2 + 1] + (samples[(i + 1) * 2 + 1] - samples[i * 2 + 1]) * t;
if channels >= 2 {
frame[0] += l * left;
frame[1] += r * right;
@@ -1001,7 +1071,7 @@ fn mix(mixer: &mut Mixer, data: &mut [f32], channels: usize, rate: u32) {
frame[0] += (l + r) * 0.5 * gain;
}
} else {
let s = samples[i] * (1.0 - t) + samples[i + 1] * t;
let s = samples[i] + (samples[i + 1] - samples[i]) * t;
if channels >= 2 {
frame[0] += s * left;
frame[1] += s * right;
@@ -1412,6 +1482,7 @@ impl Audio {
record_heard: false,
listener: [0.0; 3],
listener_yaw: 0.0,
listener_pitch: 0.0,
master: 1.0,
random: crate::random_source::create(),
source_override: None,
@@ -1535,8 +1606,12 @@ impl Audio {
/// `SoundManager.updateSource`: the camera position and rotation
/// (`Listener.setTransform` takes its forward and up vectors).
pub fn set_listener(&mut self, position: [f64; 3], yaw: f32, pitch: f32) {
if self.listener == position && self.listener_yaw == yaw && self.listener_pitch == pitch {
return;
}
self.listener = position;
self.listener_yaw = yaw;
self.listener_pitch = pitch;
if let Ok(mut m) = self.backend.mixer.lock() {
if self.backend.owner == 0 {
m.listener = position;
@@ -1576,6 +1651,7 @@ impl Audio {
record_heard: false,
listener: [0.0; 3],
listener_yaw: 0.0,
listener_pitch: 0.0,
master: self.master,
random: crate::random_source::create(),
source_override: None,
@@ -2109,6 +2185,25 @@ impl Audio {
})
.collect()
}
/// Mixes one buffer of audio into `data` (channels: 1 or 2, rate in Hz).
pub fn mix_buffer(&mut self, data: &mut [f32], channels: usize, rate: u32) {
if let Ok(mut m) = self.backend.mixer.lock() {
mix(&mut m, data, channels, rate);
}
}
#[doc(hidden)]
pub fn insert_cached_sound(&mut self, key: &str, samples: Vec<f32>, rate: u32, channels: u16) {
if let Ok(mut c) = self.backend.cache.lock() {
c.insert(
key.to_owned(),
Some((std::sync::Arc::new(samples), rate, channels)),
);
}
}
#[doc(hidden)]
pub fn backend_live_for_bench(&mut self) {
self.backend.live = true;
}
}
impl Sounds for Audio {
fn engine(&mut self) -> &mut SoundEngine {
@@ -2613,6 +2708,25 @@ mod tests {
assert_eq!(data, [0.0; 4], "returning must not resume the old one-shot");
}
/// A sound of one frame or none, heard or not, looping or not, stops at its first
/// buffer as the mixing loop stops it: none stays playing (and holds its channel).
#[test]
fn sounds_too_short_to_mix_stop_even_unheard() {
for (samples, looping) in [(vec![], false), (vec![1.0], false), (vec![1.0], true)] {
let mut mixer = Mixer::default();
let mut source = channel(samples.clone(), None, [0.0; 3], looping);
source.gain = 0.0;
mixer.channels.insert(1, source);
let mut data = [0.0; 4];
mix(&mut mixer, &mut data, 2, 48_000);
assert_eq!(
mixer.channels[&1].state,
State::Stopped,
"{samples:?} {looping}"
);
}
}
#[test]
fn variants_of_one_sound_are_the_same_sound() {
assert_eq!(
@@ -569,6 +569,25 @@ pub(crate) fn polytone_noise() -> &'static horizon_core::noise::SimplexNoise {
}
impl horizon_polytone::expr::Host for BlockHost<'_> {
fn field(
&mut self,
root: horizon_polytone::expr::Root,
field: horizon_polytone::expr::Field,
) -> Option<horizon_polytone::expr::Value> {
use horizon_polytone::expr::Field as F;
if root != horizon_polytone::expr::Root::Object {
return None;
}
Some(horizon_polytone::expr::Value::Num(match field {
F::X => f64::from(self.at[0]),
F::Y => f64::from(self.at[1]),
F::Z => f64::from(self.at[2]),
F::Temperature => f64::from(self.biome.temperature),
F::Downfall => f64::from(self.biome.downfall),
_ => return None,
}))
}
fn root(&mut self, root: horizon_polytone::expr::Root) -> horizon_polytone::expr::Value {
use horizon_polytone::expr::Root;
horizon_polytone::expr::Value::Object(match root {
+4 -4
View File
@@ -231,8 +231,8 @@ pub struct FogInputs<'a> {
/// `GameRenderer.nightVisionScale` while Night Vision is on without
/// Darkness, else 0 (`FogRenderer.computeFogColor`'s brightenFactor).
pub night_vision: f32,
/// The packs' Polytone `environment` fog settings.
pub environment: horizon_polytone::colors::Environment,
/// The packs' `environment` fog settings (Polytone's).
pub environment: crate::pack_palette::Environment,
}
/// `FogRenderer.setupFog` + `computeFogColor`.
@@ -581,7 +581,7 @@ mod tests {
let tables = FogTables {
water_fog_end: vec![1.0],
};
let environment = horizon_polytone::colors::Environment {
let environment = crate::pack_palette::Environment {
powder_snow_fog: Some(0xFF0000),
blindness_fog_distance: 40.0,
water_fog_brightening: 0.0,
@@ -613,7 +613,7 @@ mod tests {
}
fn inputs_with<'a>(
input: &FogInputs<'a>,
environment: horizon_polytone::colors::Environment,
environment: crate::pack_palette::Environment,
) -> FogInputs<'a> {
FogInputs {
environment,
+8 -5
View File
@@ -13664,6 +13664,7 @@ mod tests {
Some(Reported {
paper_white: 240,
peak: 998,
peak_guessed: true,
})
);
assert_eq!(
@@ -13671,6 +13672,7 @@ mod tests {
Some(Reported {
paper_white: 480,
peak: 480,
peak_guessed: true,
})
);
// White above the calibrated peak (a Samsung QD-OLED's 380, the slider at 456).
@@ -13679,6 +13681,7 @@ mod tests {
Some(Reported {
paper_white: 456,
peak: 456,
peak_guessed: true,
})
);
assert_eq!(os_reported(&info(Some(1000.0), None)), None);
@@ -15369,11 +15372,9 @@ fn log_os_reported(reported: Option<crate::graphics::Reported>) {
None => "Horizon renderer: the system doesn't report the display's luminance".into(),
});
}
/// What the OS reports in absolute nits (Windows: DXGI's `MaxLuminance` and the SDR
/// white level the brightness slider sets), which is HDR output's scale there: SDR
/// white is Paper White, the display's peak is Peak Brightness. Both are kept within
/// the settings' ranges. The OS's figures often come from the display's EDID and may
/// run optimistic; the player's own value always wins.
/// What the OS reports in absolute nits, HDR output's scale (Windows: DXGI's SDR white level,
/// the brightness slider's, as Paper White, and its `MaxLuminance`, mostly the display's EDID
/// guess, as Peak Brightness), kept within the settings' ranges. The player's values win.
fn os_reported(info: &wgpu::DisplayHdrInfo) -> Option<crate::graphics::Reported> {
let luminance = info.luminance?;
let usable = |n: f32| n.is_finite() && n > 0.0;
@@ -15385,6 +15386,7 @@ fn os_reported(info: &wgpu::DisplayHdrInfo) -> Option<crate::graphics::Reported>
// Windows' SDR brightness slider can set white above the reported peak (480 against
// a calibrated 380): the highlights then stay at white instead of dropping below it.
peak: (peak.round() as u32).clamp(200, 10_000).max(paper_white),
peak_guessed: true,
})
}
@@ -15420,6 +15422,7 @@ fn reported(l: horizon_hdr::wayland::Luminances) -> crate::graphics::Reported {
crate::graphics::Reported {
paper_white: 203,
peak: peak.clamp(200, 10_000),
peak_guessed: false,
}
}
@@ -300,6 +300,7 @@ pub(crate) mod tests {
luminance: Some(Reported {
paper_white: 400,
peak: 1000,
peak_guessed: false,
}),
hdr: system,
},
@@ -650,6 +651,7 @@ pub(crate) mod tests {
window_reading.luminance = Some(Reported {
paper_white: 300,
peak: 800,
peak_guessed: false,
});
assert_eq!(window_output(window_reading).nits[..2], [300.0, 800.0]);
assert_eq!(
@@ -549,6 +549,7 @@ mod tests {
reading.luminance = Some(Reported {
paper_white: 250,
peak: 600,
peak_guessed: false,
});
// 150 nits under the reported paper white of 250: 0.6 of it.
settings.hdr_ui_nits = 150;
@@ -584,6 +585,7 @@ mod tests {
reading.luminance = Some(Reported {
paper_white,
peak: 1000,
peak_guessed: false,
});
let next = candidate(&settings, caps, reading, &published);
let again = commit(&mut swapchain, &published, next, caps, &mut rejected);
@@ -729,6 +731,7 @@ mod tests {
luminance: (hdr == Some(true)).then_some(Reported {
paper_white: 300,
peak: 800,
peak_guessed: false,
}),
hdr,
};
@@ -0,0 +1,79 @@
//! Hardware ray queries, only on request (#13780, after the #1180 spike): `HORIZON_RAY_TRACING=1`
//! at startup asks the device for wgpu's `EXPERIMENTAL_RAY_QUERY` when the GPU has it. Nothing
//! draws with it yet. Without the variable, and in a build without `horizon-extras` (a Horizon
//! extra, docs/layers.md), the device is opened exactly as before.
/// The ray query feature.
const RAY_QUERY: wgpu::Features = wgpu::Features::EXPERIMENTAL_RAY_QUERY;
/// Whether the player asked for ray tracing (the device needs the feature from its creation).
fn requested() -> bool {
asked(std::env::var("HORIZON_RAY_TRACING").ok().as_deref())
}
/// Whether `HORIZON_RAY_TRACING` set to `var` asks for ray tracing: only in a `horizon-extras`
/// build.
fn asked(var: Option<&str>) -> bool {
cfg!(feature = "horizon-extras") && var == Some("1")
}
/// The features to request on `adapter`: ray queries, when asked for and offered.
pub(super) fn features(adapter: &wgpu::Adapter) -> wgpu::Features {
let features = pick(requested(), adapter.features());
if requested() {
let info = adapter.get_info();
if features.is_empty() {
log::warn!(
"Horizon renderer: ray tracing asked for, but {} on {:?} has no hardware ray \
queries; it stays off",
info.name,
info.backend
);
} else {
log::info!(
"Horizon renderer: ray queries on ({} on {:?})",
info.name,
info.backend
);
}
}
features
}
fn pick(requested: bool, offered: wgpu::Features) -> wgpu::Features {
if requested {
offered & RAY_QUERY
} else {
wgpu::Features::empty()
}
}
/// The device's opt-in to `features`' experimental ones.
pub(super) fn experimental(features: wgpu::Features) -> wgpu::ExperimentalFeatures {
if features.contains(RAY_QUERY) {
horizon_hdr::experimental_features()
} else {
wgpu::ExperimentalFeatures::disabled()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn only_an_extras_build_asks_for_ray_tracing() {
assert_eq!(asked(Some("1")), cfg!(feature = "horizon-extras"));
assert!(!asked(None));
assert!(!asked(Some("0")));
}
#[test]
fn ray_queries_only_when_asked_and_offered() {
let all = wgpu::Features::all();
assert_eq!(pick(true, all), RAY_QUERY);
assert!(pick(false, all).is_empty());
assert!(pick(true, all - RAY_QUERY).is_empty());
assert!(!experimental(wgpu::Features::empty()).is_enabled());
}
}
@@ -5,6 +5,9 @@ use super::{
Renderer, check_layers, cull, describe_adapter, is_software, oit, startup_step, surface_format,
timing,
};
// Ray tracing on request, which the device needs from its creation (gfx.rs may not grow).
#[path = "ray_query.rs"]
mod ray_query;
use std::sync::Arc;
use winit::window::Window;
@@ -134,6 +137,7 @@ pub(super) async fn open_adapter(
let features = timing::GpuTimer::features(adapter)
| cull::Cull::features(adapter)
| oit::features(adapter)
| ray_query::features(adapter)
| (adapter.features()
& (wgpu::Features::INDIRECT_FIRST_INSTANCE
| wgpu::Features::MULTI_DRAW_INDIRECT_COUNT
@@ -166,6 +170,7 @@ pub(super) async fn open_adapter(
// with the larger blocks a few small buffers kept whole blocks the arena's pages had
// left, and over half the video memory reserved was unused (1,344 MiB for 500).
memory_hints: wgpu::MemoryHints::MemoryUsage,
experimental_features: ray_query::experimental(features),
..Default::default()
};
#[cfg(not(target_os = "macos"))]
@@ -30,6 +30,22 @@ fn marker_driver(text: &str) -> &str {
pub struct Reported {
pub paper_white: u32,
pub peak: u32,
/// The peak is the display's own claim (DXGI's `MaxLuminance`, mostly its EDID figure),
/// which often runs high: Auto still uses it, but the HDR page asks to calibrate.
pub peak_guessed: bool,
}
/// Whether HDR is set up for the display, and whether the player kept the system's setup.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HdrSetup {
/// The system says nothing: the player calibrates.
Unknown,
/// The system says, but only guesses the peak: the player calibrates.
Guessed,
/// Peak Brightness and Paper White follow the system.
Automatic,
/// The system said, and the player changed them anyway.
Changed,
}
/// The top of Peak Brightness's scale: `peak_nits_at(PEAK_STEPS)` is PQ's 10 000 nits.
@@ -1207,6 +1223,15 @@ impl Graphics {
n => n,
}
}
/// How HDR is set up for the display the system `reported`.
pub fn hdr_setup(&self, reported: Option<Reported>) -> HdrSetup {
match reported {
None => HdrSetup::Unknown,
Some(_) if self.hdr_peak != 0 || self.hdr_paper_white != 0 => HdrSetup::Changed,
Some(r) if r.peak_guessed => HdrSetup::Guessed,
Some(_) => HdrSetup::Automatic,
}
}
/// The black level, in nits. Not the system's: files from before saved 0 for that
/// (Auto), and a reported black would lift every display's shadows by default.
pub fn black_level_nits(&self) -> f32 {
@@ -1320,6 +1345,7 @@ mod tests {
let reported = Some(Reported {
paper_white: 300,
peak: 1000,
peak_guessed: false,
});
assert_eq!(g.ui_nits(reported), 300);
g.hdr_paper_white = 120;
@@ -1328,6 +1354,33 @@ mod tests {
assert_eq!((g.ui_nits(None), g.ui_nits(reported)), (400, 400));
}
#[test]
fn hdr_setup_asks_to_calibrate_where_the_peak_is_guessed() {
let wayland = Reported {
paper_white: 203,
peak: 1015,
peak_guessed: false,
};
let windows = Reported {
paper_white: 400,
peak: 1000,
peak_guessed: true,
};
let mut g = Graphics::default();
assert_eq!(g.hdr_setup(None), HdrSetup::Unknown);
assert_eq!(g.hdr_setup(Some(wayland)), HdrSetup::Automatic);
assert_eq!(g.hdr_setup(Some(windows)), HdrSetup::Guessed);
// Auto still takes the guess, over the 1000-nit default.
assert_eq!(g.peak_nits(Some(windows)), 1000);
assert_eq!(g.paper_white_nits(Some(windows)), 400);
for (peak, paper_white) in [(800, 0), (0, 240)] {
(g.hdr_peak, g.hdr_paper_white) = (peak, paper_white);
assert_eq!(g.hdr_setup(Some(windows)), HdrSetup::Changed);
assert_eq!(g.hdr_setup(Some(wayland)), HdrSetup::Changed);
assert_eq!(g.hdr_setup(None), HdrSetup::Unknown);
}
}
#[test]
fn hdr_modes_keep_boolean_files_and_round_trip_auto() {
assert_eq!(Graphics::parse("").hdr, HdrMode::Off);
+11 -23
View File
@@ -8,7 +8,8 @@ use crate::{
gfx::EffectiveOutput,
graphics::{
EntityCullingMode, FarDetail, FrameGeneration, GpuCullingMode, GraphicsApi, HdrMode,
LeafCullingMode, Overlay, Pacing, ParticleCullingMode, PresentMode, Preset, Upscaling,
HdrSetup as Setup, LeafCullingMode, Overlay, Pacing, ParticleCullingMode, PresentMode,
Preset, Upscaling,
},
graphics_style::Cost,
lang,
@@ -675,28 +676,9 @@ const LOD_STEPS: [u32; 24] = [
crate::lod::MAX_CHUNKS,
];
/// Whether the system set HDR up for the display, and whether the player kept it.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Setup {
/// The system says nothing: the player calibrates.
Unknown,
/// Peak Brightness and Paper White follow the system.
Automatic,
/// The system said, and the player changed them anyway.
Changed,
}
/// `out`: the output of the renderer the settings are shown for, with what its display reports.
fn setup(s: &Settings, out: &EffectiveOutput) -> Setup {
setup_of(&s.horizon, out.reported.is_some())
}
fn setup_of(g: &crate::graphics::Graphics, reported: bool) -> Setup {
if !reported {
Setup::Unknown
} else if g.hdr_peak == 0 && g.hdr_paper_white == 0 {
Setup::Automatic
} else {
Setup::Changed
}
s.horizon.hdr_setup(out.reported)
}
/// What the HDR page says while HDR output is held back on this window's graphics driver
/// (`EffectiveOutput::held`): picking a mode tries again (`H::cycle`).
@@ -714,13 +696,19 @@ fn description(
(Item::Horizon(H::HdrCalibrate), Setup::Unknown) => {
"Your display didn't say how bright it gets: calibrate to set it up."
}
(Item::Horizon(H::HdrCalibrate), Setup::Guessed) => {
"Your display's reported peak is often too high: calibrate to set it up."
}
(Item::Horizon(H::HdrCalibrate), Setup::Automatic) => {
"Already set up for your display. Only calibrate if HDR looks wrong."
}
(Item::Horizon(H::HdrCalibrate), Setup::Changed) => {
"Puts Peak Brightness and Paper White back to your display's setup."
}
(Item::Horizon(H::HdrPeak | H::HdrPaperWhite), Setup::Automatic | Setup::Changed) => {
// A guessed peak's Auto is what calibration replaced; paper white is the player's own.
(Item::Horizon(h @ (H::HdrPeak | H::HdrPaperWhite)), Setup::Automatic | Setup::Changed)
if h == H::HdrPaperWhite || out.reported.is_some_and(|r| !r.peak_guessed) =>
{
"Set up for your display. Leave on Auto unless it looks wrong."
}
(Item::Horizon(H::GpuCulling), _) if s.horizon.gpu_culling == GpuCullingMode::Auto => {
@@ -944,7 +932,7 @@ impl H {
H::FrameGeneration => labelled("Frame Generation", g.frame_generation.label()),
H::Hdr => labelled("HDR", g.hdr.label()),
H::HdrCalibrate => Text::literal(lang::get(match setup(s, out) {
Setup::Unknown => "Calibrate...",
Setup::Unknown | Setup::Guessed => "Calibrate...",
Setup::Automatic => "Calibrate Anyway...",
Setup::Changed => "Use Automatic Setup",
})),
@@ -120,14 +120,86 @@ fn auto_levels_and_setup_read_their_own_renderers_report() {
assert_eq!(label(H::HdrCalibrate, &silent), "Calibrate...");
}
/// The setup rows' label and description for each kind of report: none, a compositor's
/// (Wayland), and Windows', whose peak is the display's own guess.
#[test]
fn hdr_setup_follows_what_the_system_reported() {
let mut g = crate::graphics::Graphics::default();
assert_eq!(setup_of(&g, false), Setup::Unknown);
assert_eq!(setup_of(&g, true), Setup::Automatic);
g.hdr_paper_white = 80;
assert_eq!(setup_of(&g, true), Setup::Changed);
assert_eq!(setup_of(&g, false), Setup::Unknown);
fn the_setup_rows_ask_to_calibrate_unless_the_system_set_the_display_up() {
let trusted = offering(true, Some(true));
let mut guessed = trusted;
guessed.reported = guessed.reported.map(|r| crate::graphics::Reported {
peak_guessed: true,
..r
});
let rows = |s: &Settings, out: &EffectiveOutput| {
[H::HdrCalibrate, H::HdrPeak, H::HdrPaperWhite].map(|h| {
let item = Item::Horizon(h);
(item.label(s, out).plain(), description(item, s, out, "-"))
})
};
let calibrate = "Calibrate...";
let set_up = "Set up for your display. Leave on Auto unless it looks wrong.";
let mut s = Settings::default();
s.horizon.hdr = HdrMode::On;
let none = (
calibrate.into(),
"Your display didn't say how bright it gets: calibrate to set it up.",
);
assert_eq!(
rows(&s, &NONE),
[
none.clone(),
("Peak Brightness: Auto (1000)".into(), "-"),
("Paper White: Auto (203)".into(), "-"),
]
);
assert_eq!(
rows(&s, &guessed),
[
(
calibrate.into(),
"Your display's reported peak is often too high: calibrate to set it up."
),
("Peak Brightness: Auto (1000)".into(), "-"),
("Paper White: Auto (400)".into(), "-"),
]
);
assert_eq!(
rows(&s, &trusted),
[
(
"Calibrate Anyway...".into(),
"Already set up for your display. Only calibrate if HDR looks wrong."
),
("Peak Brightness: Auto (1000)".into(), set_up),
("Paper White: Auto (400)".into(), set_up),
]
);
// Calibrated or set by hand, either report offers its automatic setup back.
s.horizon.hdr_peak = 800;
// Peak's Auto stays a guess on Windows: only Paper White is said to be set up there.
let changed = |peak| {
[
(
"Use Automatic Setup".into(),
"Puts Peak Brightness and Paper White back to your display's setup.",
),
("Peak Brightness: 800".into(), peak),
("Paper White: Auto (400)".into(), set_up),
]
};
assert_eq!(rows(&s, &guessed), changed("-"));
assert_eq!(rows(&s, &trusted), changed(set_up));
assert_eq!(rows(&s, &NONE)[0], none);
let mut ui = ui();
ui.screen.output = guessed;
let at = |[x, y, ..]: [f32; 4]| (x + 8.0, y + 4.0);
let calibrate = row(&mut ui, &s, Item::Horizon(H::HdrCalibrate));
assert_eq!(press(&mut ui, &mut s, at(calibrate)), [CLICK, CHANGED]);
assert_eq!((s.horizon.hdr_peak, s.horizon.hdr_paper_white), (0, 0));
assert_eq!(
press(&mut ui, &mut s, at(calibrate)),
[CLICK, Output::Push(OptionsPage::HdrCalibration)]
);
}
/// UI Brightness reads as Paper White does, in nits apart from it: Auto shows the paper white
-1
View File
@@ -67,7 +67,6 @@ mod jei_sprites;
pub mod jigsaw_block;
pub mod keypad;
pub mod terrain_model;
pub use horizon_polytone::colors as polytone_colors;
pub use horizon_polytone::creative_tabs as polytone_creative_tabs;
pub use horizon_world::json_folder;
pub mod level_loading;
+2 -2
View File
@@ -2593,8 +2593,7 @@ impl Lod {
self.returned_at = std::time::Instant::now();
let nodes = &self.plan.nodes;
self.mesh_samples.retain(|key| nodes.contains(key));
// Queued tiles the view left are not sampled (a running one is
// dropped when it finishes, `finish_sample`).
// Queued tiles the view left are not sampled; a running one is dropped (`finish_sample`).
drop_queued_samples(&self.shared, &mut self.pending, |key| {
self.plan.nodes.contains(key)
});
@@ -2680,6 +2679,7 @@ impl Lod {
}
if let Some((columns, mask)) = self.kept.take(&key) {
self.ready.insert(key, columns);
self.sync_sample(key);
if let Some(mask) = mask {
self.detail_masks.insert(key, mask);
}
@@ -1,6 +1,7 @@
//! Optional, texture-matched overlays drawn full bright over their base texture in the same
//! terrain fragment: native mods' (`<ns>:emissive/...`) and OptiFine's emissive block textures
//! (`block/stone_e.png` beside `block/stone.png`). No extra draw calls or world light changes.
//! terrain fragment: native mods' (`<ns>:emissive/...`) and a pack's emissive block textures
//! (OptiFine's `block/stone_e.png` beside `block/stone.png`, the suffix from the pack formats,
//! [`crate::pack_hooks`]). No extra draw calls or world light changes.
use crate::sprites::Sprites;
use std::{collections::BTreeMap, path::Path};
@@ -35,14 +36,12 @@ fn tile_file(name: &str) -> Option<&str> {
name.strip_suffix(".png")
}
/// OptiFine's emissive overlays of the block sprites already loaded (what the terrain draws;
/// items draw from the HUD atlas): for each
/// `<ns>:block/<name>`, or connected-texture tile `assets/<ns>/.../<name>.png`, whose
/// `<name><suffix>.png` sits beside it, the overlay is loaded too and paired with it, blocks
/// first, then tiles, each by name, at most [`MAX`] - [`NATIVE`] (native mods keep their share of
/// the table). A pack without such files adds nothing.
pub fn load_optifine(root: &Path, sprites: &mut Sprites) -> Vec<(String, String)> {
let suffix = horizon_optifine::emissive::suffix(root);
/// A pack's emissive overlays of the block sprites already loaded (what the terrain draws;
/// items draw from the HUD atlas): for each `<ns>:block/<name>`, or connected-texture tile
/// `assets/<ns>/.../<name>.png`, whose `<name><suffix>.png` sits beside it, the overlay is loaded
/// too and paired with it, blocks first, then tiles, each by name, at most [`MAX`] - [`NATIVE`]
/// (native mods keep their share of the table). A pack without such files adds nothing.
pub fn load_overlays(root: &Path, suffix: &str, sprites: &mut Sprites) -> Vec<(String, String)> {
// Blocks with identical pixels share a layer (and the shader pairs by layer): a shared
// base would glow on every block that shares it, so it gets no overlay.
let mut sharing: BTreeMap<u32, usize> = BTreeMap::new();
@@ -56,8 +55,8 @@ pub fn load_optifine(root: &Path, sprites: &mut Sprites) -> Vec<(String, String)
sharing[layer] == 1
&& (name
.split_once(':')
.is_some_and(|(_, p)| p.starts_with("block/") && !p.ends_with(&suffix))
|| tile_file(name).is_some_and(|stem| !stem.ends_with(&suffix)))
.is_some_and(|(_, p)| p.starts_with("block/") && !p.ends_with(suffix))
|| tile_file(name).is_some_and(|stem| !stem.ends_with(suffix)))
})
.map(|(name, _)| name.clone())
.collect();
@@ -110,7 +109,7 @@ pub fn load_optifine(root: &Path, sprites: &mut Sprites) -> Vec<(String, String)
pub const CUTOUT: u32 = 1 << 31;
/// The frame's overlay table: native mods' pairs (at most [`NATIVE`] requested), then the packs'
/// OptiFine pairs flagged [`CUTOUT`] (at most [`MAX`] - [`NATIVE`], as [`load_optifine`] loads),
/// OptiFine pairs flagged [`CUTOUT`] (at most [`MAX`] - [`NATIVE`], as [`load_overlays`] loads),
/// one per base layer with native mods' first, sorted by base layer for the shader's early exit.
pub fn table<'a>(
layers: &BTreeMap<String, u32>,
@@ -204,7 +203,7 @@ mod tests {
// Items draw from the HUD atlas, not the terrain: no pair.
sprites.insert(&root, "minecraft:item/stick").unwrap();
// glowstone isn't loaded: its overlay pairs with nothing.
let pairs = load_optifine(&root, &mut sprites);
let pairs = load_overlays(&root, "_e", &mut sprites);
assert_eq!(
pairs,
[(
@@ -215,9 +214,6 @@ mod tests {
assert!(sprites.layers.contains_key("minecraft:block/stone_e"));
assert!(!sprites.layers.contains_key("minecraft:block/granite_e"));
// The pack's own suffix.
let props = root.join("assets/minecraft/optifine/emissive.properties");
std::fs::create_dir_all(props.parent().unwrap()).unwrap();
std::fs::write(&props, "suffix.emissive=_glow").unwrap();
// Connected-texture tiles pair with the overlay beside them.
let tiles = root.join("assets/minecraft/optifine/ctm/lamp");
png(&tiles.join("0.png"), 230);
@@ -234,7 +230,7 @@ mod tests {
.insert_file(&root, &format!("assets/minecraft/optifine/{tile}.png"))
.unwrap();
}
let pairs = load_optifine(&root, &mut sprites);
let pairs = load_overlays(&root, "_glow", &mut sprites);
assert_eq!(
pairs,
// Blocks first, then tiles.
@@ -0,0 +1,67 @@
//! Polytone's custom colours (`horizon_polytone::colors`, `colors.json` or `color.properties`)
//! as the engine's pack colours ([`crate::pack_palette::PackColors`]).
use std::path::Path;
use horizon_polytone::colors::PackColors;
use crate::block_entity_render::DYES;
use crate::pack_palette::{self, Environment};
/// The colours of every namespace's file under the pack overlay at `root`.
pub fn read(root: &Path) -> pack_palette::PackColors {
let colors = PackColors::read(root);
let by_dye = |f: &dyn Fn(&str) -> Option<u32>| std::array::from_fn(|i| f(DYES[i].0));
let env = colors.env;
pack_palette::PackColors {
dye_diffuse: by_dye(&|name| colors.dye(name, "diffuse")),
dye_text: by_dye(&|name| colors.dye(name, "text")),
sheep: by_dye(&|name| colors.sheep(name)),
redstone: std::array::from_fn(|i| colors.redstone(i as u8)),
effects: colors.effects(),
entity_shadows: colors.entity_shadows(),
xp_bar: colors.xp_bar(),
env: Environment {
powder_snow_fog: env.powder_snow_fog,
blindness_fog_distance: env.blindness_fog_distance,
darkness_fog_distance: env.darkness_fog_distance,
boss_fog_distance: env.boss_fog_distance,
water_fog_brightening: env.water_fog_brightening,
water_fog_brightening_time: env.water_fog_brightening_time,
horizon_height: env.horizon_height,
},
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::pack_palette::{diffuse, redstone, sheep_wool, text};
#[test]
fn a_pack_recolours_only_what_it_names() {
// Dyes no other test draws: the table is process-wide.
let dir = std::env::temp_dir().join(format!("pack-dyes-{}", std::process::id()));
let polytone = dir.join("assets/obs/polytone");
std::fs::create_dir_all(&polytone).unwrap();
std::fs::write(
polytone.join("colors.json"),
r#"{"dye": {"cyan": {"diffuse": "00ff00", "text": "0000ff"}}, "sheep": {"pink": "2040ff"}, "redstone": {"7": "0x123456"}}"#,
)
.unwrap();
crate::pack_palette::set(&read(&dir));
let (cyan, pink, purple) = (9, 6, 10);
assert_eq!(diffuse(cyan), 0x00ff00);
assert_eq!(text(cyan), 0x0000ff);
assert_eq!(sheep_wool(pink as u8), 0x2040ff);
// Wool reads vanilla's dye, not the pack's diffuse: 75% of 0x169C9C.
assert_eq!(sheep_wool(cyan as u8), 0x107575);
assert_eq!(diffuse(purple), 0x8932B8);
assert_eq!(text(purple), 0xA020F0);
assert_eq!((redstone(7), redstone(15)), (Some(0x123456), None));
crate::pack_palette::set(&Default::default());
assert_eq!(redstone(7), None);
assert_eq!(diffuse(cyan), 0x169C9C);
assert_eq!(sheep_wool(pink as u8), 0xB6687F);
std::fs::remove_dir_all(&dir).ok();
}
}
@@ -0,0 +1,146 @@
//! Polytone's item modifiers' durability bar colours, on the engine's
//! [`crate::pack_palette::ItemBars`].
use std::path::Path;
use std::sync::Arc;
/// An item modifier's `bar_color` of the `damage` type: a row of colours picked by the stack's
/// damage, the first pixel undamaged, the last at full damage (measured on the real mod).
struct DamageBar {
targets: horizon_polytone::Targets,
row: Vec<u32>,
}
/// The packs' damage bars, the last read first.
struct Bars(Vec<DamageBar>);
impl crate::pack_palette::ItemBars for Bars {
fn color(&self, item: &str, damage: f32) -> Option<u32> {
let bar = self
.0
.iter()
.rev()
.find(|b| b.targets.matches(item, |_| false))?;
let last = (bar.row.len() - 1) as f32;
Some(bar.row[(damage.clamp(0.0, 1.0) * last).round() as usize])
}
}
/// Reads the packs' item modifiers' durability bar colours under a pack overlay root: an
/// `<item>_bar.png` alone, or a json whose `bar_color` is `damage` with its `<name>_bar.png` (or
/// `<name>.png`) beside it. Colormap ids and inline colormaps aren't read. `None` without any.
pub fn read(root: &Path) -> Option<Arc<dyn crate::pack_palette::ItemBars>> {
let mut bars = Vec::new();
for namespace in std::fs::read_dir(root.join("assets"))
.into_iter()
.flatten()
.flatten()
{
let base = namespace.path().join("polytone/item_modifiers");
let mut stack = vec![base.clone()];
while let Some(dir) = stack.pop() {
for entry in std::fs::read_dir(&dir).into_iter().flatten().flatten() {
let path = entry.path();
if path.is_dir() {
stack.push(path);
} else if let Some(bar) = item_bar(root, &base, &path) {
bars.push(bar);
}
}
}
}
(!bars.is_empty()).then(|| Arc::new(Bars(bars)) as _)
}
fn item_bar(root: &Path, base: &Path, path: &Path) -> Option<DamageBar> {
let name = path.file_name()?.to_str()?;
let row = |png: &Path| {
let (width, _, rgba) = crate::sprites::read_rgba(png).ok()?;
let row: Vec<u32> = rgba[..width as usize * 4]
.as_chunks::<4>()
.0
.iter()
.map(|p| u32::from(p[0]) << 16 | u32::from(p[1]) << 8 | u32::from(p[2]))
.collect();
(!row.is_empty()).then_some(row)
};
if let Some(stem) = name.strip_suffix("_bar.png") {
// A json of the same name owns its png.
if path.with_file_name(format!("{stem}.json")).exists() {
return None;
}
let relative = path.parent()?.strip_prefix(base).ok()?.join(stem);
let namespace = base.parent()?.parent()?.file_name()?.to_str()?;
let id = format!("{namespace}:{}", relative.to_str()?.replace('\\', "/"));
let targets = horizon_polytone::Targets::parse(None, Some(&id)).ok()?;
return Some(DamageBar {
targets,
row: row(path)?,
});
}
let stem = name.strip_suffix(".json")?;
let json: serde_json::Value = horizon_world::json_file::read(path).ok()?;
if json.get("bar_color")?.as_str()? != "damage" {
return None;
}
let png = [format!("{stem}_bar.png"), format!("{stem}.png")]
.into_iter()
.map(|png| path.with_file_name(png))
.find(|png| png.exists())?;
let relative = path.strip_prefix(root).unwrap_or(path).to_string_lossy();
let implicit = horizon_polytone::implicit_id(&relative, "item_modifiers");
let targets =
horizon_polytone::Targets::parse(json.get("targets"), implicit.as_deref()).ok()?;
Some(DamageBar {
targets,
row: row(&png)?,
})
}
#[cfg(test)]
mod tests {
use super::*;
fn png_row(path: &Path, pixels: &[[u8; 3]]) {
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
let file = std::fs::File::create(path).unwrap();
let mut encoder = png::Encoder::new(file, pixels.len() as u32, 1);
encoder.set_color(png::ColorType::Rgba);
let data: Vec<u8> = pixels
.iter()
.flat_map(|p| [p[0], p[1], p[2], 255])
.collect();
encoder
.write_header()
.unwrap()
.write_image_data(&data)
.unwrap();
}
#[test]
fn a_damage_bar_picks_its_pixel_by_the_stacks_damage() {
let dir = std::env::temp_dir().join(format!("pack-bars-{}", std::process::id()));
let modifiers = dir.join("assets/minecraft/polytone/item_modifiers");
let rgby = [[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0]];
png_row(&modifiers.join("diamond_pickaxe_bar.png"), &rgby);
std::fs::write(
modifiers.join("tools.json"),
r#"{"targets": ["minecraft:iron_axe"], "bar_color": "damage"}"#,
)
.unwrap();
png_row(&modifiers.join("tools_bar.png"), &[[1, 2, 3], [4, 5, 6]]);
let bars = read(&dir).unwrap();
// The real mod: damage 200 of 1561 shows the first pixel, 1400 the last.
assert_eq!(
bars.color("minecraft:diamond_pickaxe", 200.0 / 1561.0),
Some(0xFF0000)
);
assert_eq!(
bars.color("minecraft:diamond_pickaxe", 1400.0 / 1561.0),
Some(0xFFFF00)
);
assert_eq!(bars.color("minecraft:iron_axe", 0.9), Some(0x040506));
assert_eq!(bars.color("minecraft:diamond_shovel", 0.5), None);
assert!(read(&dir.join("none")).is_none());
std::fs::remove_dir_all(&dir).ok();
}
}
@@ -3,7 +3,9 @@
//! crate until the platform's executable installs it: it uses only the crate's public API, so it
//! moves to a platform crate unchanged, and nothing else in the crate names it.
mod colors;
mod custom_sky;
mod item_bars;
use std::path::Path;
use std::sync::Arc;
@@ -14,10 +16,22 @@ use crate::pack_hooks::PackFormats;
pub struct Formats;
impl PackFormats for Formats {
fn colors(&self, root: &Path) -> Option<crate::pack_palette::PackColors> {
Some(colors::read(root))
}
fn emissive_suffix(&self, root: &Path) -> Option<String> {
Some(horizon_optifine::emissive::suffix(root))
}
fn custom_sky(&self, root: &Path) -> Option<Arc<dyn crate::custom_sky::SkyLayers>> {
let sky = custom_sky::CustomSky::load(root);
(!sky.is_empty()).then(|| Arc::new(sky) as _)
}
fn item_bars(&self, root: &Path) -> Option<Arc<dyn crate::pack_palette::ItemBars>> {
item_bars::read(root)
}
}
/// Installs these formats ([`crate::pack_hooks::install`]); the game does at startup.
@@ -10,10 +10,26 @@ use std::sync::{Arc, OnceLock};
/// What the pack formats beyond vanilla's add to a pack. Each method reads one overlay of a pack
/// (its folder at `root`); the default is "nothing in this format".
pub trait PackFormats: Send + Sync {
/// The colours the overlay replaces where vanilla hardcodes them.
fn colors(&self, _root: &Path) -> Option<crate::pack_palette::PackColors> {
None
}
/// The name ending of the overlay's emissive textures (`stone_e.png` beside `stone.png`),
/// if its format has them.
fn emissive_suffix(&self, _root: &Path) -> Option<String> {
None
}
/// The sky layers the overlay draws over the vanilla sky, if it has any.
fn custom_sky(&self, _root: &Path) -> Option<Arc<dyn crate::custom_sky::SkyLayers>> {
None
}
/// The durability bar colours the overlay sets by item, if any.
fn item_bars(&self, _root: &Path) -> Option<Arc<dyn crate::pack_palette::ItemBars>> {
None
}
}
/// No format beyond vanilla's.
+113 -184
View File
@@ -1,14 +1,87 @@
//! Polytone's dye, sheep and redstone colours (`dye.<name>.diffuse|text`, `sheep.<name>`,
//! `redstone.<power>`), for drawing only: the pack recolours collars, tropical fish, banners, wool,
//! sign text and redstone wire and dust, while gameplay (crafting, item data, the beacon) keeps
//! vanilla's `DyeColor`. Lock-free: the draw paths and the mesher's workers read it per face.
//! The colours a pack replaces where vanilla hardcodes them (Polytone's `colors.json`, read by the
//! platform's pack formats, [`crate::pack_hooks`]): dye, sheep and redstone colours, for drawing
//! only (the pack recolours collars, tropical fish, banners, wool, sign text and redstone wire and
//! dust, while gameplay keeps vanilla's `DyeColor`), mob effect colours, the experience number's,
//! entity shadows, the effect fogs' settings and durability bar colours. Lock-free: the draw paths
//! and the mesher's workers read the dye, sheep and redstone tables per face.
use std::path::Path;
use std::sync::RwLock;
use std::sync::atomic::{AtomicU64, Ordering::Relaxed};
use std::sync::{Arc, RwLock};
use crate::block_entity_render::DYES;
use crate::signs::DYE_TEXT;
use horizon_polytone::colors::PackColors;
/// The fog settings vanilla hardcodes, as the packs set them (vanilla's by default).
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Environment {
/// The fog colour inside powder snow (RGB).
pub powder_snow_fog: Option<u32>,
/// The fog ends of Blindness (5), Darkness (15) and bosses that add world fog (96).
pub blindness_fog_distance: f32,
pub darkness_fog_distance: f32,
pub boss_fog_distance: f32,
/// How much the underwater fog colour washes out (1 vanilla, 0 none).
pub water_fog_brightening: f32,
/// The ticks under water it takes (vanilla's 600).
pub water_fog_brightening_time: f32,
/// Below it the sky draws its dark disc (vanilla's 63; flat worlds keep their floor).
pub horizon_height: f32,
}
impl Default for Environment {
fn default() -> Self {
Self {
powder_snow_fog: None,
blindness_fog_distance: 5.0,
darkness_fog_distance: 15.0,
boss_fog_distance: 96.0,
water_fog_brightening: 1.0,
water_fog_brightening_time: 600.0,
horizon_height: 63.0,
}
}
}
/// The packs' colours; `None` (and the defaults) where they keep vanilla's.
#[derive(Clone, Debug, PartialEq)]
pub struct PackColors {
/// By dye id (`DyeColor` order): `getTextureDiffuseColor`, `getTextColor`, the sheep's wool.
pub dye_diffuse: [Option<u32>; 16],
pub dye_text: [Option<u32>; 16],
pub sheep: [Option<u32>; 16],
/// `RedStoneWireBlock.COLORS` by power.
pub redstone: [Option<u32>; 16],
/// Mob effects' colours, by effect id without vanilla's namespace.
pub effects: Vec<(String, u32)>,
/// False hides every entity's round shadow, whatever the video option says.
pub entity_shadows: bool,
/// The experience level number's colour and outline.
pub xp_bar: [Option<u32>; 2],
/// The effect fogs' settings: the fog reads them every frame.
pub env: Environment,
}
impl Default for PackColors {
fn default() -> Self {
Self {
dye_diffuse: [None; 16],
dye_text: [None; 16],
sheep: [None; 16],
redstone: [None; 16],
effects: Vec::new(),
entity_shadows: true,
xp_bar: [None; 2],
env: Environment::default(),
}
}
}
impl PackColors {
/// Whether entities draw their round shadow, as far as the packs say.
pub fn entity_shadows(&self) -> bool {
self.entity_shadows
}
}
/// 0 is unset, else `1 << 32 | rgb`.
static DIFFUSE: [AtomicU64; 16] = [const { AtomicU64::new(0) }; 16];
@@ -16,6 +89,30 @@ static TEXT: [AtomicU64; 16] = [const { AtomicU64::new(0) }; 16];
static SHEEP: [AtomicU64; 16] = [const { AtomicU64::new(0) }; 16];
static REDSTONE: [AtomicU64; 16] = [const { AtomicU64::new(0) }; 16];
/// The colours of the pack overlay at `root`, from the installed pack formats; their dye, sheep
/// and redstone colours go to the draw paths' tables ([`set`]).
pub fn read(root: &Path) -> PackColors {
let formats = crate::pack_hooks::formats();
let colors = formats.colors(root).unwrap_or_default();
set(&colors);
*ITEM_BARS.write().unwrap_or_else(|e| e.into_inner()) = formats.item_bars(root);
colors
}
/// The packs' durability bar colours by item (Polytone's item modifiers' `bar_color`).
pub trait ItemBars: Send + Sync {
/// The bar colour (RGB) of `item` at this damage (0 to 1), when a pack sets one.
fn color(&self, item: &str, damage: f32) -> Option<u32>;
}
static ITEM_BARS: RwLock<Option<Arc<dyn ItemBars>>> = RwLock::new(None);
/// A pack's durability bar colour (RGB) for an item at this damage (0 to 1).
pub fn item_bar_color(item: &str, damage: f32) -> Option<u32> {
let bars = ITEM_BARS.read().unwrap_or_else(|e| e.into_inner());
bars.as_ref()?.color(item, damage)
}
/// Takes the colours of the packs just loaded (vanilla's where they set none).
pub fn set(colors: &PackColors) {
let store = |table: &[AtomicU64; 16], i: usize, color: Option<u32>| {
@@ -24,129 +121,39 @@ pub fn set(colors: &PackColors) {
Relaxed,
);
};
for (i, (name, _)) in DYES.iter().enumerate() {
store(&DIFFUSE, i, colors.dye(name, "diffuse"));
store(&TEXT, i, colors.dye(name, "text"));
store(&SHEEP, i, colors.sheep(name));
store(&REDSTONE, i, colors.redstone(i as u8));
for i in 0..16 {
store(&DIFFUSE, i, colors.dye_diffuse[i]);
store(&TEXT, i, colors.dye_text[i]);
store(&SHEEP, i, colors.sheep[i]);
store(&REDSTONE, i, colors.redstone[i]);
}
}
/// An item modifier's `bar_color` of the `damage` type: a row of colours picked by the stack's
/// damage, the first pixel undamaged, the last at full damage (measured on the real mod).
struct DamageBar {
targets: horizon_polytone::Targets,
row: Vec<u32>,
}
static ITEM_BARS: RwLock<Vec<DamageBar>> = RwLock::new(Vec::new());
/// Reads the packs' item modifiers' durability bar colours under a pack overlay root: an
/// `<item>_bar.png` alone, or a json whose `bar_color` is `damage` with its `<name>_bar.png` (or
/// `<name>.png`) beside it. Colormap ids and inline colormaps aren't read.
pub fn set_item_bars(root: &Path) {
let mut bars = Vec::new();
for namespace in std::fs::read_dir(root.join("assets"))
.into_iter()
.flatten()
.flatten()
{
let base = namespace.path().join("polytone/item_modifiers");
let mut stack = vec![base.clone()];
while let Some(dir) = stack.pop() {
for entry in std::fs::read_dir(&dir).into_iter().flatten().flatten() {
let path = entry.path();
if path.is_dir() {
stack.push(path);
} else if let Some(bar) = item_bar(root, &base, &path) {
bars.push(bar);
}
}
}
}
*ITEM_BARS.write().unwrap_or_else(|e| e.into_inner()) = bars;
}
fn item_bar(root: &Path, base: &Path, path: &Path) -> Option<DamageBar> {
let name = path.file_name()?.to_str()?;
let row = |png: &Path| {
let (width, _, rgba) = crate::sprites::read_rgba(png).ok()?;
let row: Vec<u32> = rgba[..width as usize * 4]
.as_chunks::<4>()
.0
.iter()
.map(|p| u32::from(p[0]) << 16 | u32::from(p[1]) << 8 | u32::from(p[2]))
.collect();
(!row.is_empty()).then_some(row)
};
if let Some(stem) = name.strip_suffix("_bar.png") {
// A json of the same name owns its png.
if path.with_file_name(format!("{stem}.json")).exists() {
return None;
}
let relative = path.parent()?.strip_prefix(base).ok()?.join(stem);
let namespace = base.parent()?.parent()?.file_name()?.to_str()?;
let id = format!("{namespace}:{}", relative.to_str()?.replace('\\', "/"));
let targets = horizon_polytone::Targets::parse(None, Some(&id)).ok()?;
return Some(DamageBar {
targets,
row: row(path)?,
});
}
let stem = name.strip_suffix(".json")?;
let json: serde_json::Value = horizon_world::json_file::read(path).ok()?;
if json.get("bar_color")?.as_str()? != "damage" {
return None;
}
let png = [format!("{stem}_bar.png"), format!("{stem}.png")]
.into_iter()
.map(|png| path.with_file_name(png))
.find(|png| png.exists())?;
let relative = path.strip_prefix(root).unwrap_or(path).to_string_lossy();
let implicit = horizon_polytone::implicit_id(&relative, "item_modifiers");
let targets =
horizon_polytone::Targets::parse(json.get("targets"), implicit.as_deref()).ok()?;
Some(DamageBar {
targets,
row: row(&png)?,
})
}
/// A pack's durability bar colour (RGB) for an item at this damage (0 to 1).
pub fn item_bar_color(item: &str, damage: f32) -> Option<u32> {
let bars = ITEM_BARS.read().unwrap_or_else(|e| e.into_inner());
let bar = bars
.iter()
.rev()
.find(|b| b.targets.matches(item, |_| false))?;
let last = (bar.row.len() - 1) as f32;
Some(bar.row[(damage.clamp(0.0, 1.0) * last).round() as usize])
}
fn read(table: &[AtomicU64; 16], i: usize) -> Option<u32> {
fn get(table: &[AtomicU64; 16], i: usize) -> Option<u32> {
let v = table[i & 15].load(Relaxed);
(v != 0).then_some(v as u32)
}
/// `DyeColor.getTextureDiffuseColor` (RGB) as the packs draw it.
pub fn diffuse(dye: usize) -> u32 {
read(&DIFFUSE, dye).unwrap_or(DYES[dye & 15].1)
get(&DIFFUSE, dye).unwrap_or(DYES[dye & 15].1)
}
/// `DyeColor.getTextColor` (RGB) as the packs draw it.
pub fn text(dye: usize) -> u32 {
read(&TEXT, dye).unwrap_or(DYE_TEXT[dye & 15].1)
get(&TEXT, dye).unwrap_or(DYE_TEXT[dye & 15].1)
}
/// A pack's `RedStoneWireBlock.COLORS` entry for this power (RGB), when it sets one.
pub fn redstone(power: u8) -> Option<u32> {
read(&REDSTONE, usize::from(power))
get(&REDSTONE, usize::from(power))
}
/// `ColorLerper.Type.SHEEP` wool colour: a pack's `sheep.<name>`, else white 0xE6E6E6 and the
/// others 75% of vanilla's dye (a pack's `dye.*.diffuse` doesn't reach wool).
pub fn sheep_wool(dye: u8) -> u32 {
let i = usize::from(dye & 15);
if let Some(color) = read(&SHEEP, i) {
if let Some(color) = get(&SHEEP, i) {
return color;
}
if i == 0 {
@@ -156,81 +163,3 @@ pub fn sheep_wool(dye: u8) -> u32 {
let f = |c: u32| ((c as f32 * 0.75).floor() as u32).min(255);
f(src >> 16 & 255) << 16 | f(src >> 8 & 255) << 8 | f(src & 255)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_pack_recolours_only_what_it_names() {
// Dyes no other test draws: the table is process-wide.
let dir = std::env::temp_dir().join(format!("pack-dyes-{}", std::process::id()));
let polytone = dir.join("assets/obs/polytone");
std::fs::create_dir_all(&polytone).unwrap();
std::fs::write(
polytone.join("colors.json"),
r#"{"dye": {"cyan": {"diffuse": "00ff00", "text": "0000ff"}}, "sheep": {"pink": "2040ff"}, "redstone": {"7": "0x123456"}}"#,
)
.unwrap();
set(&PackColors::read(&dir));
let (cyan, pink, purple) = (9, 6, 10);
assert_eq!(diffuse(cyan), 0x00ff00);
assert_eq!(text(cyan), 0x0000ff);
assert_eq!(sheep_wool(pink as u8), 0x2040ff);
// Wool reads vanilla's dye, not the pack's diffuse: 75% of 0x169C9C.
assert_eq!(sheep_wool(cyan as u8), 0x107575);
assert_eq!(diffuse(purple), 0x8932B8);
assert_eq!(text(purple), 0xA020F0);
assert_eq!((redstone(7), redstone(15)), (Some(0x123456), None));
set(&PackColors::default());
assert_eq!(redstone(7), None);
assert_eq!(diffuse(cyan), 0x169C9C);
assert_eq!(sheep_wool(pink as u8), 0xB6687F);
std::fs::remove_dir_all(&dir).ok();
}
fn png_row(path: &Path, pixels: &[[u8; 3]]) {
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
let file = std::fs::File::create(path).unwrap();
let mut encoder = png::Encoder::new(file, pixels.len() as u32, 1);
encoder.set_color(png::ColorType::Rgba);
let data: Vec<u8> = pixels
.iter()
.flat_map(|p| [p[0], p[1], p[2], 255])
.collect();
encoder
.write_header()
.unwrap()
.write_image_data(&data)
.unwrap();
}
#[test]
fn a_damage_bar_picks_its_pixel_by_the_stacks_damage() {
let dir = std::env::temp_dir().join(format!("pack-bars-{}", std::process::id()));
let modifiers = dir.join("assets/minecraft/polytone/item_modifiers");
let rgby = [[255, 0, 0], [0, 255, 0], [0, 0, 255], [255, 255, 0]];
png_row(&modifiers.join("diamond_pickaxe_bar.png"), &rgby);
std::fs::write(
modifiers.join("tools.json"),
r#"{"targets": ["minecraft:iron_axe"], "bar_color": "damage"}"#,
)
.unwrap();
png_row(&modifiers.join("tools_bar.png"), &[[1, 2, 3], [4, 5, 6]]);
set_item_bars(&dir);
// The real mod: damage 200 of 1561 shows the first pixel, 1400 the last.
assert_eq!(
item_bar_color("minecraft:diamond_pickaxe", 200.0 / 1561.0),
Some(0xFF0000)
);
assert_eq!(
item_bar_color("minecraft:diamond_pickaxe", 1400.0 / 1561.0),
Some(0xFFFF00)
);
assert_eq!(item_bar_color("minecraft:iron_axe", 0.9), Some(0x040506));
assert_eq!(item_bar_color("minecraft:diamond_shovel", 0.5), None);
set_item_bars(&dir.join("none"));
assert_eq!(item_bar_color("minecraft:diamond_pickaxe", 0.5), None);
std::fs::remove_dir_all(&dir).ok();
}
}
@@ -801,6 +801,26 @@ impl Host for Ctx<'_, '_> {
_ => Err(format!("{name} is not available here")),
}
}
/// A particle's own fields, as `particle_method` answers them.
fn field(&mut self, root: Root, field: horizon_polytone::expr::Field) -> Option<V> {
use horizon_polytone::expr::Field as F;
let Subject::Particle(p) = &self.subject else {
return None;
};
if root != Root::Object {
return None;
}
Some(V::Num(match field {
F::Age => f64::from(p.age),
F::Life => f64::from(p.lifetime),
F::Custom => *self.custom,
F::X => p.position[0],
F::Y => p.position[1],
F::Z => p.position[2],
F::Temperature | F::Downfall => return None,
}))
}
}
fn eval(program: &Program, ctx: &mut Ctx) -> Option<f64> {
@@ -913,6 +913,20 @@ pub trait Backend {
fn unpause(&mut self, channel: ChannelId);
/// `Channel.stopped`.
fn stopped(&mut self, channel: ChannelId) -> bool;
/// Update volume, pitch, and position in a single backend call.
fn update_channel(&mut self, channel: ChannelId, volume: f32, pitch: f32, position: [f64; 3]) {
self.set_volume(channel, volume);
self.set_pitch(channel, pitch);
self.set_position(channel, position);
}
/// Filter which handles have stopped playing in a single pass.
fn filter_stopped(&mut self, live: &[(u64, ChannelId)], stopped: &mut Vec<u64>) {
for &(h, c) in live {
if self.stopped(c) {
stopped.push(h);
}
}
}
/// Whether the channel plays clearly through a mod's muffle (`Audio::muffle`): its sound
/// event is one the mod exempted. A backend without a muffle ignores it.
fn set_unmuffled(&mut self, _channel: ChannelId, _unmuffled: bool) {}
@@ -1494,13 +1508,14 @@ impl SoundEngine {
.iter()
.filter_map(|(h, handle)| handle.channel.map(|c| (*h, c))),
);
for (h, c) in live.drain(..) {
if backend.stopped(c) {
self.release_handle(h, backend);
}
let mut stopped = std::mem::take(&mut self.mapped_scratch);
stopped.clear();
backend.filter_stopped(&live, &mut stopped);
for h in stopped.drain(..) {
self.release_handle(h, backend);
}
// Released handles nobody maps any more.
let mut mapped = std::mem::take(&mut self.mapped_scratch);
let mut mapped = stopped;
mapped.clear();
mapped.extend(self.instance_to_channel.iter().map(|(_, h)| *h));
self.handles
@@ -1550,9 +1565,7 @@ impl SoundEngine {
h.pitch_edited = pitch_edited;
}
if let Some(c) = self.handles.get(&handle).and_then(handle_channel) {
backend.set_volume(c, volume);
backend.set_pitch(c, pitch);
backend.set_position(c, position);
backend.update_channel(c, volume, pitch, position);
}
let instance = self.instances.get_mut(&id).expect("present");
if instance.looping
+23 -1
View File
@@ -1251,6 +1251,9 @@ pub struct EditBox {
/// `getMessage`: what the narrator calls the box ("<message> edit box:
/// <value>").
pub message: String,
/// `EditBox.setInvertHighlightedTextColor`: a selection draws its text
/// inverted (the default) or in the box's own colour (`AnvilScreen`).
pub invert_highlighted_text_color: bool,
/// Where a borderless box drawn in a frame of its own focuses: a controller's outline goes
/// round the frame, not over the text.
pub frame: Option<[f32; 4]>,
@@ -1543,6 +1546,7 @@ impl EditBox {
text_color_uneditable: rgba(112, 112, 112, 255),
editable: true,
message: String::new(),
invert_highlighted_text_color: true,
frame: None,
}
}
@@ -1918,7 +1922,11 @@ impl EditBox {
let right = self.x + self.width;
let (x0, x1) = (cursor_x.min(right), (hx - 1.0).min(right));
let (a, b) = (x0.min(x1), x0.max(x1));
batch.text_highlight(atlas, (a, ty - 1.0, b - a, 11.0), true);
batch.text_highlight(
atlas,
(a, ty - 1.0, b - a, 11.0),
self.invert_highlighted_text_color,
);
}
if show_cursor {
if insert {
@@ -2628,6 +2636,20 @@ mod tests {
);
}
/// `EditBox.setInvertHighlightedTextColor`: a selection inverts its text
/// unless the box asks it not to (the anvil's rename box).
#[test]
fn a_selection_inverts_its_text_unless_the_box_says_not_to() {
let mut edit = EditBox::new(0.0, 0.0, 100.0, 20.0);
assert!(edit.invert_highlighted_text_color);
edit.invert_highlighted_text_color = false;
edit.set_value("name");
edit.set_cursor(0, false);
edit.set_cursor(4, true);
assert_eq!(edit.selected_text(), "name");
assert!(!edit.invert_highlighted_text_color);
}
/// `EditBox.setEditable(false)`: the box keeps the focus, the caret keys
/// and copy, but `charTyped`/paste/Backspace/Delete do nothing, and Cut
/// copies without taking the text out. A value and the caret still show,
+3 -2
View File
@@ -119,10 +119,11 @@ audio = ["horizon-client-render/audio", "horizon-client-lib/audio"]
controllers = ["horizon-client-lib/controllers", "dep:gilrs", "dep:horizon-dualsense", "horizon-client-input/controllers"]
# Horizon's own extras over the vanilla game, for a fork that wants them out (docs/forking.md):
# cosmetics and emotes, the "Horizon player" presence, the official server added to
# the server list, the Horizon Settings and Mods pages, Discord and Play with Friends. Players always get them; there is no switch. `grep -rn horizon-extras crates/` lists
# the server list, the Horizon Settings and Mods pages, Discord and Play with Friends, and ray
# tracing on request (`HORIZON_RAY_TRACING=1`). Players always get them; there is no switch. `grep -rn horizon-extras crates/` lists
# every place it gates. Without it (`--no-default-features --features audio,controllers`) the
# client is best effort: CI builds only the default.
horizon-extras = ["horizon-client-lib/horizon-extras", "discord", "friends"]
horizon-extras = ["horizon-client-lib/horizon-extras", "horizon-client-render/horizon-extras", "discord", "friends"]
# Online extras a server or a port can leave out; the server build has none of them. "Playing Horizon"
# on Discord (game/discord.rs).
discord = ["horizon-client-lib/discord"]
@@ -441,6 +441,7 @@
"HDR Calibration %s/%s: %s": "HDR Calibration %s/%s: %s",
"Sets the three below full screen, one test picture at a time.": "Sets the three below full screen, one test picture at a time.",
"Your display didn't say how bright it gets: calibrate to set it up.": "Your display didn't say how bright it gets: calibrate to set it up.",
"Your display's reported peak is often too high: calibrate to set it up.": "Your display's reported peak is often too high: calibrate to set it up.",
"Already set up for your display. Only calibrate if HDR looks wrong.": "Already set up for your display. Only calibrate if HDR looks wrong.",
"Puts Peak Brightness and Paper White back to your display's setup.": "Puts Peak Brightness and Paper White back to your display's setup.",
"Set up for your display. Leave on Auto unless it looks wrong.": "Set up for your display. Leave on Auto unless it looks wrong.",
+6 -5
View File
@@ -21,11 +21,11 @@ pub use horizon_client_render::{
mipmap, mod_browser, mod_list, model_library, models, multiline_edit, native_emissive,
options_file, options_fixes, options_ui, overlay, pack_browser, pack_formats, pack_hooks,
pack_palette, pack_screen, packs, pad_cursor, pad_glyph, par, particles, poi_sections,
polytone_colors, polytone_creative_tabs, polytone_post, post_chain, potent_sulfur, preedit,
providers, pvp, pvp_hud, random_source, screen_draw, screen_effects, sculk, section_mask,
server_terrain, settings, shader_options, shader_pack_list, signs, skins, social, sound_engine,
sound_events, sound_preview, spans, split_layout, split_map, split_profiles, sprites,
streaming, structure_block, tab_list, terrain_model, test_block, test_instance_block, testgen,
polytone_creative_tabs, polytone_post, post_chain, potent_sulfur, preedit, providers, pvp,
pvp_hud, random_source, screen_draw, screen_effects, sculk, section_mask, server_terrain,
settings, shader_options, shader_pack_list, signs, skins, social, sound_engine, sound_events,
sound_preview, spans, split_layout, split_map, split_profiles, sprites, streaming,
structure_block, tab_list, terrain_model, test_block, test_instance_block, testgen,
title_edition, trims, ui, vault, weather, widgets, world, worldborder, zip,
};
pub mod attack_strength;
@@ -171,6 +171,7 @@ pub use horizon_client_input::gamepad;
pub use horizon_client_input::gameplay_guide;
pub use horizon_client_input::held;
pub use horizon_client_input::input;
pub use horizon_client_input::input_source;
pub use horizon_client_input::interaction_input;
pub use horizon_client_input::key_names;
pub use horizon_client_input::keybinds;
+3 -3
View File
@@ -2666,9 +2666,9 @@ pub fn mob_from_nbt_with_random(
m.extra.counter = number(tag.get("still_timeout")).unwrap_or(0) as i32;
}
if m.species() == crate::mobs::Species::Shulker {
m.extra.variant3 = number(tag.get("AttachFace")).unwrap_or(0).clamp(0, 5) as u8;
m.extra.counter = number(tag.get("Peek")).unwrap_or(0).clamp(0, 100) as i32;
m.extra.color = number(tag.get("Color")).map_or(16, |c| c.clamp(0, 16) as u8);
m.extra.variant3 = (number(tag.get("AttachFace")).unwrap_or(0) % 6).unsigned_abs() as u8;
m.extra.counter = number(tag.get("Peek")).map_or(0, |v| v as i8 as i32);
m.extra.color = number(tag.get("Color")).map_or(16, |v| v as i8 as u8);
m.anim.v[0] = m.extra.counter as f32 * 0.01;
m.anim.vo[0] = m.anim.v[0];
// Shulker.setPos: square on its block.
+57 -77
View File
@@ -2028,7 +2028,7 @@ pub struct PackResources {
/// The packs' Polytone post chains (#11486), when a pack has some.
polytone_post: Option<Arc<horizon_client::polytone_post::PolytonePost>>,
/// The packs' Polytone custom colours (`polytone/colors.json`).
polytone_colors: Arc<horizon_client::polytone_colors::PackColors>,
polytone_colors: Arc<horizon_client::pack_palette::PackColors>,
}
/// A quick craft drag as the screen draws it: each dragged slot's count and
/// whether the slot caps it (None: hidden), and what stays in hand.
@@ -2882,19 +2882,8 @@ struct Game<'a> {
/// The open connection joined from Realms: `ServerData.isRealm` for the friends
/// service's presence status.
realm_session: bool,
/// Active packet replay session (game/studio.rs).
pub(super) studio_replay: Option<horizon_client::studio::ReplayDriver>,
pub(super) studio_freecam: horizon_client::studio::StudioFreecam,
pub(super) studio_timeline: horizon_client::studio::TimelineUi,
pub(super) studio_topbar: horizon_client::studio::TopBarUi,
pub(super) studio_rmb_down: bool,
studio_camera_track_dirty: bool,
/// Camera perspective to restore after leaving replay playback.
studio_replay_previous_camera_type: Option<perspective::CameraType>,
/// Replay opened from the title screen owns the synthetic remote session.
studio_replay_standalone: bool,
last_replay_tick: Option<Instant>,
pub(super) studio_virtual_tick_ms: f32,
/// Horizon Studio: replay playback, its free camera, timeline and top bar (game/studio.rs).
pub(super) studio: studio::Studio,
/// This world is open to the network (game/lan.rs).
lan: Option<lan::LanHost>,
/// Single player's server thread, which `remote` is connected to.
@@ -5026,7 +5015,7 @@ impl Game<'_> {
if canceled {
return Ok(false);
}
self.pad_rumble(horizon_client::gamepad::Rumble::BlockBroken);
self.input_feedback(horizon_client::input_source::Feedback::BlockBroken);
let broken = state;
let facts = self.res.facts().get(state).clone();
let state = self.crack_mined_pot(pos, state);
@@ -5845,7 +5834,7 @@ impl Game<'_> {
batch
}
fn hud_layers(&mut self, size: [u32; 2]) -> HudBatch {
self.pad.guide_shown.clear();
self.input_hud_begin();
let mut batch = HudBatch::new(size);
batch.glint_colour = self.settings.extras.pvp.tweaks.glint_texel();
// GlobalSettingsUniform's GameTime, for a resource pack's text shader.
@@ -5942,7 +5931,7 @@ impl Game<'_> {
// the sleep overlay, debug screen and open screens still draw.
let spectator = self.spectator();
let (wi, hi) = (w as i32, h as i32);
let in_studio = self.studio_replay.is_some();
let in_studio = self.studio.replay.is_some();
let show_hud = !self.ui.hide_gui && !in_studio;
// Hud.extractRenderState asks `Screen.isInGameUi` twice: such a screen
// defers the subtitles over itself, and keeps them while F1 hides the
@@ -6142,7 +6131,7 @@ impl Game<'_> {
let atlas = &g.gui.atlas;
let width = |s: &str| HudBatch::text_width(atlas, s) as i32;
let draws = hud_layout::experience_colored(
g.pack.polytone_colors.xp_bar(),
g.pack.polytone_colors.xp_bar,
wi,
hi,
g.experience.progress,
@@ -6284,19 +6273,19 @@ impl Game<'_> {
}
if !self.ui.hide_gui
&& self.screen == Screen::Playing
&& (self.studio_replay.is_some() || self.studio_freecam.active)
&& (self.studio.replay.is_some() || self.studio.freecam.active)
{
self.studio_topbar.render(
self.studio.topbar.render(
&mut batch,
&self.gui.atlas,
self.cursor,
self.studio_freecam.locked_to_path,
self.studio.freecam.locked_to_path,
);
self.studio_timeline.render(
self.studio.timeline.render(
&mut batch,
&self.gui.atlas,
self.cursor,
&self.studio_freecam,
&self.studio.freecam,
);
}
if show_hud {
@@ -6521,12 +6510,12 @@ impl Game<'_> {
/// `Camera.setRotation`: the camera's orientation, turned round in
/// third-person front view.
pub(super) fn camera_orientation(&self) -> glam::Quat {
if self.studio_freecam.active {
if self.studio.freecam.active {
return camera_rotation(
perspective::CameraType::FirstPerson,
self.studio_freecam.yaw,
self.studio_freecam.pitch,
) * glam::Quat::from_rotation_z(self.studio_freecam.roll.to_radians());
self.studio.freecam.yaw,
self.studio.freecam.pitch,
) * glam::Quat::from_rotation_z(self.studio.freecam.roll.to_radians());
}
match self.posed_rotation {
// The frame's camera, already turned round in front view.
@@ -6733,8 +6722,8 @@ impl Game<'_> {
self.mark_player(out.len(), !self.own_body_in_view());
let player_start = out.len();
self.mark_motion(player_start, Self::MOTION_OWN_PLAYER);
let player_alpha = if self.studio_replay.is_some() {
(self.studio_virtual_tick_ms as f64 / 50.0).clamp(0.0, 1.0)
let player_alpha = if self.studio.replay.is_some() {
(self.studio.virtual_tick_ms as f64 / 50.0).clamp(0.0, 1.0)
} else {
self.clock.camera_fraction()
};
@@ -9236,7 +9225,7 @@ impl Game<'_> {
let camera_alpha = self.clock.camera_fraction();
let vanilla = self.camera_view(camera_alpha as f32);
let view = vanilla.map(|view| {
if self.shows_panorama() || self.studio_freecam.active {
if self.shows_panorama() || self.studio.freecam.active {
view
} else {
self.native_camera_pose_now(camera_alpha as f32, view)
@@ -9414,9 +9403,9 @@ impl Game<'_> {
// hitboxes (F3+G, F3+B).
let mut lines = self.fishing_line(alpha, size);
let mut g = self.debug_gizmos(alpha as f32, camera.to_array());
if self.studio_freecam.active || self.studio_replay.is_some() {
if self.studio.freecam.active || self.studio.replay.is_some() {
horizon_client::studio::render_camera_path(
&self.studio_freecam.track,
&self.studio.freecam.track,
&mut g,
None,
100,
@@ -9443,7 +9432,7 @@ impl Game<'_> {
Vec::new()
};
pr.lap("pr_native_visuals");
let view = if self.studio_freecam.active {
let view = if self.studio.freecam.active {
glam::Mat4::from_quat(self.camera_orientation().conjugate())
} else {
horizon_client::camera::view_matrix(view_yaw, view_pitch)
@@ -9569,7 +9558,7 @@ impl Game<'_> {
} else {
self.fov_degrees(camera_alpha as f32, camera.to_array())
};
let camera_effects = fov::camera_effects_enabled(title, self.studio_freecam.active);
let camera_effects = fov::camera_effects_enabled(title, self.studio.freecam.active);
let bob = if !camera_effects {
glam::Mat4::IDENTITY
} else {
@@ -10074,7 +10063,7 @@ impl Game<'_> {
)
)
{
self.pad.keyboard_took_over = true;
self.input_keyboard_used();
}
if let WindowEvent::KeyboardInput { event, .. } = &event
&& event.state == ElementState::Pressed
@@ -10463,19 +10452,19 @@ impl Game<'_> {
let previous = self.cursor;
self.cursor = (position.x as f32 / b.scale, position.y as f32 / b.scale);
if self.screen == Screen::Playing
&& (self.studio_timeline.dragging_playhead
|| self.studio_timeline.dragging_keyframe.is_some())
&& (self.studio.timeline.dragging_playhead
|| self.studio.timeline.dragging_keyframe.is_some())
{
let action = self.studio_timeline.handle_mouse_drag(
let action = self.studio.timeline.handle_mouse_drag(
self.cursor,
b.width,
&mut self.studio_freecam,
&mut self.studio.freecam,
);
if matches!(
action,
horizon_client::studio::TimelineAction::KeyframeMoved
) {
self.studio_camera_track_dirty = true;
self.studio.camera_track_dirty = true;
}
return Ok(());
}
@@ -10527,7 +10516,7 @@ impl Game<'_> {
}
}
WindowEvent::MouseWheel { .. }
if self.screen == Screen::Playing && self.studio_replay.is_some() => {}
if self.screen == Screen::Playing && self.studio.replay.is_some() => {}
WindowEvent::MouseWheel { delta, .. } => {
let (raw_x, raw_y) = match delta {
MouseScrollDelta::LineDelta(x, y) => (f64::from(x), f64::from(y)),
@@ -10805,44 +10794,44 @@ impl Game<'_> {
WindowEvent::MouseInput { state, button, .. } => {
let pressed = state == ElementState::Pressed;
if !pressed && button == MouseButton::Left {
let action = self.studio_timeline.handle_mouse_up();
let action = self.studio.timeline.handle_mouse_up();
if !matches!(action, horizon_client::studio::TimelineAction::None) {
self.handle_studio_timeline_action(action);
}
}
if (self.studio_freecam.active || self.studio_replay.is_some())
if (self.studio.freecam.active || self.studio.replay.is_some())
&& button == MouseButton::Right
{
if let Some(renderer) = &self.renderer {
let batch =
HudBatch::new([renderer.config.width, renderer.config.height]);
if self.studio_timeline.visible
&& self.cursor.1 >= batch.height - self.studio_timeline.height()
if self.studio.timeline.visible
&& self.cursor.1 >= batch.height - self.studio.timeline.height()
{
if pressed
&& let Some(index) = self.studio_timeline.keyframe_at_cursor(
&& let Some(index) = self.studio.timeline.keyframe_at_cursor(
self.cursor,
batch.width,
batch.height,
&self.studio_freecam,
&self.studio.freecam,
)
{
if index < self.studio_freecam.track.keyframes.len() {
self.studio_freecam.track.keyframes.remove(index);
self.studio_camera_track_dirty = true;
if index < self.studio.freecam.track.keyframes.len() {
self.studio.freecam.track.keyframes.remove(index);
self.studio.camera_track_dirty = true;
}
self.studio_timeline.selected_keyframe = None;
self.studio.timeline.selected_keyframe = None;
}
return Ok(());
}
}
if pressed {
self.studio_topbar.close_dropdown();
self.studio_rmb_down = true;
self.studio.topbar.close_dropdown();
self.studio.rmb_down = true;
self.capture(true);
return Ok(());
} else if self.studio_rmb_down {
self.studio_rmb_down = false;
} else if self.studio.rmb_down {
self.studio.rmb_down = false;
self.capture(false);
return Ok(());
}
@@ -10850,7 +10839,7 @@ impl Game<'_> {
if pressed
&& button == MouseButton::Left
&& self.screen == Screen::Playing
&& (self.studio_replay.is_some() || self.studio_freecam.active)
&& (self.studio.replay.is_some() || self.studio.freecam.active)
{
let size = self
.renderer
@@ -10858,8 +10847,8 @@ impl Game<'_> {
.map(|renderer| [renderer.config.width, renderer.config.height])
.unwrap_or([1, 1]);
let batch = HudBatch::new(size);
let had_open_menu = self.studio_topbar.open_menu.is_some();
let topbar_action = self.studio_topbar.handle_mouse_click(
let had_open_menu = self.studio.topbar.open_menu.is_some();
let topbar_action = self.studio.topbar.handle_mouse_click(
self.cursor,
batch.width,
batch.height,
@@ -10868,26 +10857,26 @@ impl Game<'_> {
self.handle_studio_topbar_action(topbar_action);
return Ok(());
}
if had_open_menu || self.cursor.1 <= self.studio_topbar.height {
if had_open_menu || self.cursor.1 <= self.studio.topbar.height {
return Ok(());
}
if self.studio_timeline.visible {
let action = self.studio_timeline.handle_mouse_down(
if self.studio.timeline.visible {
let action = self.studio.timeline.handle_mouse_down(
self.cursor,
batch.width,
batch.height,
&self.studio_freecam,
&self.studio.freecam,
);
if !matches!(action, horizon_client::studio::TimelineAction::None) {
self.handle_studio_timeline_action(action);
return Ok(());
}
if self.cursor.1 >= batch.height - self.studio_timeline.height() {
if self.cursor.1 >= batch.height - self.studio.timeline.height() {
return Ok(());
}
}
}
if self.screen == Screen::Playing && self.studio_replay.is_some() {
if self.screen == Screen::Playing && self.studio.replay.is_some() {
return Ok(());
}
if matches!(self.screen, Screen::Inventory | Screen::Creative)
@@ -11357,7 +11346,7 @@ impl Game<'_> {
let between = now.saturating_duration_since(self.frame_end);
self.frame_ticks = elapsed.as_secs_f32() * 20.0;
self.previous = now;
if self.studio_freecam.active
if self.studio.freecam.active
&& self.screen == Screen::Playing
&& !self.dialog_open()
{
@@ -11367,7 +11356,7 @@ impl Game<'_> {
let vertical =
held(KeyCode::KeyE) - held(KeyCode::KeyQ) + held(KeyCode::Space);
let fast = self.keys.raw(&KeyCode::ControlRight);
self.studio_freecam.update_flight_motion(
self.studio.freecam.update_flight_motion(
forward,
strafe,
vertical,
@@ -11447,7 +11436,7 @@ impl Game<'_> {
self.extras_frame(elapsed);
self.extras_retry()?;
self.apply_mouse_look();
self.pad_look(elapsed.as_secs_f32());
self.input_look(elapsed.as_secs_f32());
self.advance_flight();
self.tick_world_icon();
let ticked = Instant::now();
@@ -12157,16 +12146,7 @@ impl<'a> Game<'a> {
entity_attachments: Default::default(),
remote: None,
realm_session: false,
studio_replay: None,
studio_freecam: Default::default(),
studio_timeline: Default::default(),
studio_topbar: Default::default(),
studio_rmb_down: false,
studio_camera_track_dirty: false,
studio_replay_previous_camera_type: None,
studio_replay_standalone: false,
last_replay_tick: None,
studio_virtual_tick_ms: 0.0,
studio: Default::default(),
lan: None,
integrated: None,
level_shapes: Default::default(),
+2 -2
View File
@@ -644,7 +644,7 @@ impl Game<'_> {
.into());
}
if arg(2)? != "up" {
self.pad.keyboard_took_over = true;
self.input_keyboard_used();
}
// The command confirmation takes the keys; none go past it.
if self.command_prompt.is_some() {
@@ -800,7 +800,7 @@ impl Game<'_> {
// controller still holding one keeps it.
let options = [self.settings.toggle_crouch, self.settings.toggle_sprint];
for (slot, name) in [(0, "key.sneak"), (1, "key.sprint")] {
if !self.pad.holds_action(&self.settings.controller, name) {
if !self.input_holds(name) {
self.toggles.key(
slot,
horizon_client::keymapping::KeyAction::Release,
@@ -9,7 +9,7 @@ impl Game<'_> {
pub(super) fn mapped_key_down(&self, mapping: &str) -> bool {
keybinds::key_code(self.settings.keys.get(mapping))
.is_some_and(|k| self.physical_keys.contains(&k))
|| self.pad.holds_action(&self.settings.controller, mapping)
|| self.input_holds(mapping)
}
/// `CreativeModeInventoryScreen.selectTab` on the HOTBAR tab: each saved
+2 -2
View File
@@ -2317,7 +2317,7 @@ impl Game<'_> {
a.spawn_velocity = Some(p.velocity);
a.spawn_rot = Some((p.pitch, p.yaw));
}
self.creatures.projectiles.push(p);
self.creatures.projectiles.put_back(p);
self.native_projectile_launch(player, &name, id, kind);
}
/// `MushroomCow.shear`'s `sendParticles(EXPLOSION, x, getY(0.5), z, 1, 0, 0, 0, 0)`:
@@ -6949,7 +6949,7 @@ impl Game<'_> {
{
m.heal(25.0);
consume = true;
sound = Some("entity.iron_golem.repair");
eat = Some(("entity.iron_golem.repair", 1.0, m.golem_repair_pitch()));
}
Species::Creeper if creeper_igniter => {
m.extra.flag = true;
+4 -1
View File
@@ -1008,7 +1008,10 @@ impl Game<'_> {
p.position.z - center[2],
];
let distance = (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]).sqrt();
self.pad_rumble(horizon_client::gamepad::Rumble::Explosion { distance, radius });
self.input_feedback(horizon_client::input_source::Feedback::Explosion {
distance,
radius,
});
}
// Explosion.explode: the blast is heard.
let ctx = horizon_client::sculk::Context::default();
+2 -2
View File
@@ -135,8 +135,8 @@ impl Game<'_> {
}
/// `Camera.calculateFov` with `modifyFovBasedOnDeathOrFluid`.
pub(super) fn fov_degrees(&self, partial: f32, camera: [f64; 3]) -> f32 {
if self.studio_freecam.active {
return self.studio_freecam.fov.clamp(1.0, 179.0);
if self.studio.freecam.active {
return self.studio.freecam.fov.clamp(1.0, 179.0);
}
let fov = self.view.calculate_fov(
partial,
@@ -193,7 +193,7 @@ impl Game<'_> {
// replay player's hands remain visible in first person; freecam has
// no player-view hand.
if !fov::studio_draws_hand(
self.studio_freecam.active,
self.studio.freecam.active,
self.ui.hands_drawn(
self.spectator(),
self.sleeping.is_some(),
+1 -1
View File
@@ -1820,7 +1820,7 @@ impl Game<'_> {
// from carries those, as `save_guest` gives them on leaving. The map
// stays their one owner.
let live = self.guest_attachments.get(&uuid).cloned();
let g = &mut host.hub.guests[i];
let g = playerdata::with_warden(&mut host.hub.guests[i], self.warden_tracker_tag());
let held = live.map(|a| std::mem::replace(&mut g.attachments, a));
playerdata::store(g, &mut self.level, vehicle);
if let Some(held) = held {
+27 -24
View File
@@ -61,46 +61,49 @@ impl Game<'_> {
/// that are gone, and read what the instances follow.
pub(super) fn start_mob_sounds(&mut self) -> Vec<MobSound> {
let game_time = self.world.game_time;
let mobs: Vec<MobSound> = self
.mobs
.iter()
.filter(|m| {
!m.removed
&& matches!(
m.species(),
Species::Bee
| Species::Guardian
| Species::ElderGuardian
| Species::Sniffer
)
})
.map(|m| MobSound {
let mut mobs = Vec::new();
let mut bee_indices = Vec::new();
for m in &self.mobs {
if m.removed {
continue;
}
let species = m.species();
if !matches!(
species,
Species::Bee | Species::Guardian | Species::ElderGuardian | Species::Sniffer
) {
continue;
}
let is_bee = species == Species::Bee;
let sound = MobSound {
id: m.id,
position: [m.position.x, m.position.y, m.position.z],
// Vec3.horizontalDistance.
speed: m.velocity.x.hypot(m.velocity.z),
baby: m.is_baby(),
// NeutralMob.isAngry: the anger end time is ahead.
angry: m.species() == Species::Bee
angry: is_bee
&& bee::get(m).is_some_and(|b| b.anger_end > 0 && b.anger_end - game_time > 0),
silent: m.silent,
attack_scale: guardian::attack_scale(m),
// SnifferSoundInstance.tick.
sniffer_digging: m.species() == Species::Sniffer
sniffer_digging: species == Species::Sniffer
&& m.ai.target.is_none()
&& sniffer::can_play_digging_sound(m),
})
.collect();
};
if is_bee {
bee_indices.push(mobs.len());
}
mobs.push(sound);
}
self.guardian_sounds
.retain(|id| mobs.iter().any(|m| m.id == *id));
self.bee_sounds
.retain(|id, _| mobs.iter().any(|m| m.id == *id));
for sound in &mobs {
let is_bee = self
.mobs
.iter()
.any(|m| m.id == sound.id && m.species() == Species::Bee);
if is_bee && self.bee_sounds.get(&sound.id) != Some(&sound.angry) {
for &idx in &bee_indices {
let sound = &mobs[idx];
if self.bee_sounds.get(&sound.id) != Some(&sound.angry) {
self.bee_sounds.insert(sound.id, sound.angry);
let instance = SoundInstance::bee(sound, sound.angry, random_source::create());
self.audio.play_instance(instance, false);
-20
View File
@@ -679,26 +679,6 @@ impl Game<'_> {
gamepad::move_vector(self.pad.state.left, settings.move_deadzone)
}
/// Whether `key` is held, a movement key by the left stick too: as the keys the stick holds
/// (`eight_direction_keys`), whatever moves the player. For readers of the keys that aren't
/// the movement itself.
pub(super) fn movement_key_held(&self, key: KeyCode) -> bool {
if self.keys.raw(&key) {
return true;
}
let Some(stick) = self.pad_move() else {
return false;
};
let [forward, backward, left, right] = gamepad::eight_direction_keys(stick);
match key {
KeyCode::KeyW => forward,
KeyCode::KeyS => backward,
KeyCode::KeyA => left,
KeyCode::KeyD => right,
_ => false,
}
}
/// The right stick turns the view, once per frame (`Entity.turn`).
pub(super) fn pad_look(&mut self, seconds: f32) {
let settings = &self.settings.controller;
@@ -280,11 +280,11 @@ impl Game<'_> {
/// front of) it, pulled in where visual shapes are in the way. Returns the
/// position, yaw and pitch to render from.
pub(super) fn camera_view(&mut self, partial: f32) -> Option<(glam::DVec3, f32, f32)> {
if self.studio_freecam.active {
if self.studio.freecam.active {
return Some((
self.studio_freecam.position,
self.studio_freecam.yaw,
self.studio_freecam.pitch,
self.studio.freecam.position,
self.studio.freecam.yaw,
self.studio.freecam.pitch,
));
}
// Minecraft.cameraEntity: a server's spectator camera on a mob or
@@ -643,8 +643,9 @@ impl Game<'_> {
/// The model's old pitch is the player's `xRotO`, which the turn moves
/// with `xRot` (`turn_rotation`).
pub(super) fn turn_player(&mut self, xo: f64, yo: f64) {
if self.studio_freecam.active {
self.studio_freecam
if self.studio.freecam.active {
self.studio
.freecam
.turn((xo * 0.15) as f32, (yo * 0.15) as f32);
return;
}
@@ -697,7 +698,7 @@ impl Game<'_> {
/// `LevelExtractor`'s skip of the camera entity: the player's own body
/// is drawn unless the camera is in first person, or while it sleeps.
pub(super) fn own_body_in_view(&self) -> bool {
!self.camera_type.first_person() || self.sleeping.is_some() || self.studio_freecam.active
!self.camera_type.first_person() || self.sleeping.is_some() || self.studio.freecam.active
}
/// Whether the player's own model shows in the world view (its body or,
/// while invisible, only its armour and held items).
+77 -6
View File
@@ -101,7 +101,7 @@ impl Game<'_> {
};
// A controller's stick click acts as the key without setting the modifier: it is held
// while the pad holds it (or its release waits for a tick), not when the keyboard says.
let pad = self.pad.holds_action(&self.settings.controller, mapping);
let pad = self.input_holds(mapping);
if !held && !pad {
self.toggles.0[slot].set_down(false, needs_toggle);
self.sync_toggle(slot);
@@ -180,7 +180,7 @@ impl Game<'_> {
raw: KeyCode,
source: Source,
) -> Result<()> {
if self.screen == Screen::Playing && self.studio_replay.is_some() {
if self.screen == Screen::Playing && self.studio.replay.is_some() {
if !pressed {
self.keys.release(&key, source);
return Ok(());
@@ -191,7 +191,7 @@ impl Game<'_> {
}
return Ok(());
}
if !studio_freecam_movement_key(key) || !self.studio_freecam.active {
if !studio_freecam_movement_key(key) || !self.studio.freecam.active {
return Ok(());
}
}
@@ -352,9 +352,7 @@ impl Game<'_> {
_ => return false,
};
match source {
Source::Keyboard | Source::Agent => {
self.pad.holds_action(&self.settings.controller, mapping)
}
Source::Keyboard | Source::Agent => self.input_holds(mapping),
Source::Pad => {
let keys = &self.settings.keys;
self.physical_buttons
@@ -450,6 +448,79 @@ impl Game<'_> {
}
}
/// The input source (docs/layers.md, "Controllers, splitscreen, replays and UI pages"): what
/// gameplay asks of a device beyond the keyboard and mouse, and tells it. Gameplay calls these,
/// never the controller modules; today `pad` answers.
impl Game<'_> {
/// The analog move vector (`[left, forward]`, -1..1) while a device moves the player.
pub(super) fn input_move(&self) -> Option<[f32; 2]> {
self.pad_move()
}
/// Whether a device holds the key mapping named `mapping` (`key.use`).
pub(super) fn input_holds(&self, mapping: &str) -> bool {
self.pad.holds_action(&self.settings.controller, mapping)
}
/// Turns the view by what the devices give this frame (`Entity.turn`).
pub(super) fn input_look(&mut self, seconds: f32) {
self.pad_look(seconds);
}
/// The keyboard or mouse acted in play (a key or button pressed): it has control again, though
/// only moving the mouse takes a pad out of use.
pub(super) fn input_keyboard_used(&mut self) {
self.pad.keyboard_took_over = true;
}
/// Whether the pointer event being handled is one a device made (a pad's menu cursor
/// clicking), not the mouse's.
pub(super) fn input_made_pointer_event(&self) -> bool {
self.pad.menu.synthetic
}
/// A new player entity took over (spawn, respawn, a server joined, a dimension change).
pub(super) fn input_player_replaced(&mut self) {
self.pad.player_replaced();
}
/// Whether the drop about to happen is a device's whole-stack drop (it has no Control key to
/// hold). Asking answers once.
pub(super) fn input_takes_stack_drop(&mut self) -> bool {
std::mem::take(&mut self.pad.drop_stack)
}
/// The HUD starts a frame: what a device drew on the last one is gone.
pub(super) fn input_hud_begin(&mut self) {
self.pad.guide_shown.clear();
}
/// Something happened to the player that a device may let them feel.
pub(super) fn input_feedback(&mut self, event: horizon_client::input_source::Feedback) {
self.pad_rumble(event.into());
}
/// Whether `key` is held, a movement key by the analog move vector too: as the keys it holds
/// (`eight_direction_keys`), whatever moves the player. For readers of the keys that aren't
/// the movement itself.
pub(super) fn movement_key_held(&self, key: KeyCode) -> bool {
if self.keys.raw(&key) {
return true;
}
let Some(stick) = self.input_move() else {
return false;
};
let [forward, backward, left, right] = horizon_client::gamepad::eight_direction_keys(stick);
match key {
KeyCode::KeyW => forward,
KeyCode::KeyS => backward,
KeyCode::KeyA => left,
KeyCode::KeyD => right,
_ => false,
}
}
}
#[cfg(test)]
mod tests {
use super::{studio_freecam_movement_key, studio_replay_shortcut};
+7 -8
View File
@@ -10,7 +10,7 @@ impl Game<'_> {
/// the container's hotbar keys are now (`checkHotbarKeyPressed`).
pub(super) fn key_pressed(&mut self, key: KeyCode, raw: KeyCode) -> Result<()> {
self.direct_craft_stop();
if self.screen == Screen::Playing && self.studio_replay.is_some() {
if self.screen == Screen::Playing && self.studio.replay.is_some() {
match key {
KeyCode::Escape => {
self.close_studio_replay();
@@ -25,19 +25,19 @@ impl Game<'_> {
KeyCode::KeyF => self.handle_studio_timeline_action(
horizon_client::studio::TimelineAction::ToggleFreecam,
),
KeyCode::KeyT => self.studio_timeline.visible = !self.studio_timeline.visible,
KeyCode::KeyT => self.studio.timeline.visible = !self.studio.timeline.visible,
KeyCode::KeyM => self.add_studio_marker(),
KeyCode::Home => self.handle_studio_topbar_action(
horizon_client::studio::TopBarAction::ResetCameraToPlayer,
),
KeyCode::KeyL => {
self.studio_freecam.locked_to_path = !self.studio_freecam.locked_to_path;
self.studio.freecam.locked_to_path = !self.studio.freecam.locked_to_path;
}
KeyCode::KeyK => self.handle_studio_timeline_action(
horizon_client::studio::TimelineAction::AddCameraKeyframe,
),
KeyCode::Delete => {
if let Some(index) = self.studio_timeline.selected_keyframe {
if let Some(index) = self.studio.timeline.selected_keyframe {
self.handle_studio_timeline_action(
horizon_client::studio::TimelineAction::RemoveCameraKeyframe(index),
);
@@ -78,7 +78,7 @@ impl Game<'_> {
KeyCode::Escape => match self.screen {
Screen::Options => self.options_key(KeyCode::Escape, None)?,
Screen::Playing => {
if self.studio_replay.is_some() && self.captured {
if self.studio.replay.is_some() && self.captured {
self.capture(false);
return Ok(());
}
@@ -213,7 +213,7 @@ impl Game<'_> {
// key.toggleGui is a KeyMapping: it clicks only with no screen open.
KeyCode::F1 if self.screen == Screen::Playing => self.toggle_hide_gui(),
KeyCode::F11 => self.toggle_fullscreen(),
KeyCode::F5 if self.screen == Screen::Playing && self.studio_replay.is_none() => {
KeyCode::F5 if self.screen == Screen::Playing && self.studio.replay.is_none() => {
self.cycle_camera()
}
KeyCode::KeyE
@@ -279,8 +279,7 @@ impl Game<'_> {
KeyCode::KeyQ if self.screen == Screen::Playing => {
// handleKeybinds: the number keys select before key.drop.
self.select_queued_hotbar();
let all =
drop_whole_stack(self.modifiers) || std::mem::take(&mut self.pad.drop_stack);
let all = drop_whole_stack(self.modifiers) || self.input_takes_stack_drop();
self.drop_held(all);
}
KeyCode::Digit1
@@ -111,7 +111,7 @@ impl Game<'_> {
self.stop_sounds_for_new_level();
}
self.player = Some(player);
self.pad.player_replaced();
self.input_player_replaced();
self.sway = Default::default();
self.apply_equipment();
self.eye = 1.62;
@@ -26,7 +26,7 @@ impl Game<'_> {
let pointer = self.captured || self.agent_pointer;
let grabbed = pointer
&& self.screen == Screen::Playing
&& (self.player.is_some() || self.studio_freecam.active);
&& (self.player.is_some() || self.studio.freecam.active);
let active = self.focused || self.agent_pointer;
if let Some((xo, yo)) = self
.mouse
@@ -76,8 +76,8 @@ impl Game<'_> {
&& self.control.is_none()
&& self.screen == Screen::Playing
&& !studio_suppresses_focus_pause(
self.studio_replay.is_some(),
self.studio_freecam.active,
self.studio.replay.is_some(),
self.studio.freecam.active,
)
&& self.player.is_some()
&& !self.options.no_pause
@@ -149,7 +149,7 @@ impl Game<'_> {
self.reset_inventory_clicks();
if !capture {
self.stop_mining();
self.studio_rmb_down = false;
self.studio.rmb_down = false;
}
// The real pointer takes over from an agent's.
self.agent_pointer = false;
@@ -353,9 +353,9 @@ impl Game<'_> {
/// click. A screen that is open keeps it free, as releasing the pointer
/// for that screen did: it is the screen, not the focus, that shows it.
pub(super) fn regrab_on_refocus(&mut self) {
if self.studio_replay.is_some() || self.studio_freecam.active {
if self.studio.replay.is_some() || self.studio.freecam.active {
self.regrab_on_refocus = false;
self.studio_rmb_down = false;
self.studio.rmb_down = false;
self.capture(false);
return;
}
+9 -9
View File
@@ -2433,7 +2433,7 @@ impl Game<'_> {
/// view centre, `calculateStorageRange` (the server's radius, at least
/// two, plus three) chunks each way.
pub(super) fn remote_chunk_in_range(&self, x: i32, z: i32) -> bool {
if self.studio_replay.is_some() {
if self.studio.replay.is_some() {
return true;
}
self.remote
@@ -6176,7 +6176,7 @@ impl Game<'_> {
player.spectator = self.spectator();
player.velocity = delta;
self.player = Some(player);
self.pad.player_replaced();
self.input_player_replaced();
self.sway = Default::default();
self.eye = 1.62;
self.previous_eye = 1.62;
@@ -6185,7 +6185,7 @@ impl Game<'_> {
self.apply_remote_abilities();
}
}
if self.studio_replay.is_none() {
if self.studio.replay.is_none() {
self.previous_position = position;
}
self.yaw = yaw;
@@ -6441,7 +6441,7 @@ impl Game<'_> {
}
return Ok(());
}
let stick = self.pad_move();
let stick = self.input_move();
if self.player.is_none() {
return Ok(());
}
@@ -6521,7 +6521,7 @@ impl Game<'_> {
return Ok(());
};
player.fluids.boat = boat;
if !riding && self.studio_replay.is_none() {
if !riding && self.studio.replay.is_none() {
self.previous_position = player.position;
}
let before = (
@@ -6728,7 +6728,7 @@ impl Game<'_> {
self.snap_player_model_pitch();
}
// The player's own model (third person, the inventory's preview).
if self.studio_replay.is_none() {
if self.studio.replay.is_none() {
self.tick_player_model();
}
self.tick_emotes();
@@ -9525,7 +9525,7 @@ impl Game<'_> {
KeyCode::KeyQ if !self.spectator() => {
// Minecraft.hasControlDown: the physical keys, so a toggled
// sprint on Left Control does not make Q drop the stack.
let all = self.has_control_down() || std::mem::take(&mut self.pad.drop_stack);
let all = self.has_control_down() || self.input_takes_stack_drop();
self.remote_drop(all);
}
KeyCode::KeyE
@@ -10528,7 +10528,7 @@ impl Game<'_> {
/// A connection's screen is over the world: connecting, reconfiguring, or
/// the level loading screen, a portal's included (`remote_overlay`).
pub(super) fn remote_screen_up(&self) -> bool {
self.studio_replay.is_none()
self.studio.replay.is_none()
&& self
.remote
.as_ref()
@@ -10612,7 +10612,7 @@ impl Game<'_> {
/// Connected or connecting with no player yet: `ConnectScreen`, then
/// `LevelLoadingScreen`, over the panorama with its blur.
pub(super) fn remote_loading(&self) -> bool {
if self.studio_replay.is_some() {
if self.studio.replay.is_some() {
return false;
}
use horizon_client::level_loading::Reason;
@@ -292,10 +292,8 @@ fn pack_particles(
}
/// The packs' custom colours; their dye and sheep colours go to the draw paths' table.
fn read_colors(root: &std::path::Path) -> horizon_client::polytone_colors::PackColors {
let colors = horizon_client::polytone_colors::PackColors::read(root);
horizon_client::pack_palette::set(&colors);
horizon_client::pack_palette::set_item_bars(root);
horizon_client::brewing::set_pack_colors(colors.effects());
fn read_colors(root: &std::path::Path) -> horizon_client::pack_palette::PackColors {
let colors = horizon_client::pack_palette::read(root);
horizon_client::brewing::set_pack_colors(colors.effects.clone());
colors
}
+11 -4
View File
@@ -359,12 +359,19 @@ impl Game<'_> {
self.sculk.tracker = WardenSpawnTracker::from_nbt(tag);
}
}
/// Write the tracker into the player data being saved.
/// The tracker as saved, once it has been loaded.
pub(super) fn warden_tracker_tag(&self) -> Option<horizon_world::nbt::Tag> {
self.sculk
.tracker_loaded
.then(|| self.sculk.tracker.to_nbt())
}
/// Write the tracker into the player data being saved. With a LAN owner,
/// `store_owner` rewrites that from the owner's guest, so it puts the
/// tracker there as well (`playerdata::with_warden`).
pub(super) fn save_warden_tracker(&mut self) {
if !self.sculk.tracker_loaded {
let Some(tag) = self.warden_tracker_tag() else {
return;
}
let tag = self.sculk.tracker.to_nbt();
};
let extra = self
.level
.player_extra
@@ -15,6 +15,8 @@ pub(super) fn rename_box() -> horizon_client::ui::EditBox {
edit.text_color = u32::MAX;
// AnvilScreen also sets `setTextColorUneditable(-1)`: white either way.
edit.text_color_uneditable = u32::MAX;
// AnvilScreen sets `setInvertHighlightedTextColor(false)`.
edit.invert_highlighted_text_color = false;
edit.focused = true;
edit.editable = false;
edit
@@ -40,6 +42,7 @@ mod tests {
// AnvilScreen.init: no input yet, so the box is read-only but focused.
let station_box = rename_box();
assert!(station_box.focused && !station_box.editable);
assert!(!station_box.invert_highlighted_text_color);
// slotChanged with an item: editable, and it shows the item's name.
let mut station = Station::new_kind(Kind::Anvil, [0; 3]);
+162 -127
View File
@@ -15,6 +15,26 @@ use std::{
time::{Duration, SystemTime, UNIX_EPOCH},
};
/// Studio's state in a `Game`: the replay playing, its free camera, timeline and top bar. Studio is
/// a Horizon extra (docs/layers.md: the replay editor); the engine only asks it whether a replay
/// plays or the free camera flies.
#[derive(Default)]
pub(super) struct Studio {
/// The packet replay playing, if any.
pub(super) replay: Option<ReplayDriver>,
pub(super) freecam: horizon_client::studio::StudioFreecam,
pub(super) timeline: horizon_client::studio::TimelineUi,
pub(super) topbar: horizon_client::studio::TopBarUi,
pub(super) rmb_down: bool,
pub(super) camera_track_dirty: bool,
/// Camera perspective to restore after leaving replay playback.
pub(super) replay_previous_camera_type: Option<super::perspective::CameraType>,
/// Replay opened from the title screen owns the synthetic remote session.
pub(super) replay_standalone: bool,
pub(super) last_replay_tick: Option<std::time::Instant>,
pub(super) virtual_tick_ms: f32,
}
pub const HELP: &[&str] = &[
"studio record start [NAME] start recording clientbound packets into .mcpr archive",
"studio record stop stop recording and finalize .mcpr archive",
@@ -109,13 +129,13 @@ impl Game<'_> {
match words[0] {
"freecam" => match words.get(1).copied() {
Some("on") => {
if self.studio_replay.is_none() {
if self.studio.replay.is_none() {
self.system_message(Text::translate(
"horizon.studio.freecam.replay_required",
&[],
));
} else if let Some((position, yaw, pitch)) = self.camera_view(1.0) {
self.studio_freecam.activate(
self.studio.freecam.activate(
position,
yaw,
pitch,
@@ -131,24 +151,24 @@ impl Game<'_> {
}
}
Some("off") => {
self.studio_freecam.deactivate();
self.studio.freecam.deactivate();
self.capture(false);
self.system_message(Text::translate("horizon.studio.freecam.disabled", &[]));
}
_ => self.system_message(Text::translate("horizon.studio.freecam.usage", &[])),
},
"keyframe" => {
let Some(driver) = self.studio_replay.as_ref() else {
let Some(driver) = self.studio.replay.as_ref() else {
self.system_message(Text::translate("horizon.studio.replay.inactive", &[]));
return true;
};
let time_ms = driver.position_ms();
match words.get(1).copied() {
Some("add") => {
if !self.studio_freecam.active
if !self.studio.freecam.active
&& let Some((position, yaw, pitch)) = self.camera_view(1.0)
{
self.studio_freecam.activate(
self.studio.freecam.activate(
position,
yaw,
pitch,
@@ -156,16 +176,16 @@ impl Game<'_> {
);
}
self.capture(true);
self.studio_freecam.add_keyframe_at_current(time_ms);
self.studio_camera_track_dirty = true;
self.studio.freecam.add_keyframe_at_current(time_ms);
self.studio.camera_track_dirty = true;
self.system_message(Text::tr(
"horizon.studio.keyframe.added",
&[&time_ms.to_string()],
));
}
Some("clear") => {
self.studio_freecam.track.clear();
self.studio_camera_track_dirty = true;
self.studio.freecam.track.clear();
self.studio.camera_track_dirty = true;
self.system_message(Text::translate(
"horizon.studio.keyframe.cleared",
&[],
@@ -181,15 +201,15 @@ impl Game<'_> {
));
return true;
};
if index >= self.studio_freecam.track.keyframes.len() {
if index >= self.studio.freecam.track.keyframes.len() {
self.system_message(Text::translate(
"horizon.studio.keyframe.index_invalid",
&[],
));
return true;
}
self.studio_freecam.track.keyframes.remove(index);
self.studio_camera_track_dirty = true;
self.studio.freecam.track.keyframes.remove(index);
self.studio.camera_track_dirty = true;
self.system_message(Text::tr(
"horizon.studio.keyframe.removed",
&[&index.to_string()],
@@ -199,14 +219,14 @@ impl Game<'_> {
}
}
"path" => match words.get(1).copied() {
Some("lock") if !self.studio_freecam.track.is_empty() => {
self.studio_freecam.active = true;
self.studio_freecam.locked_to_path = true;
Some("lock") if !self.studio.freecam.track.is_empty() => {
self.studio.freecam.active = true;
self.studio.freecam.locked_to_path = true;
self.capture(true);
self.system_message(Text::translate("horizon.studio.path.locked", &[]));
}
Some("unlock") => {
self.studio_freecam.locked_to_path = false;
self.studio.freecam.locked_to_path = false;
self.system_message(Text::translate("horizon.studio.path.unlocked", &[]));
}
_ => self.system_message(Text::translate("horizon.studio.path.usage", &[])),
@@ -299,7 +319,7 @@ impl Game<'_> {
}
}
Some("pause") => {
if let Some(r) = self.studio_replay.as_mut() {
if let Some(r) = self.studio.replay.as_mut() {
r.set_paused(true);
self.system_message(Text::translate("horizon.studio.replay.paused", &[]));
} else {
@@ -307,7 +327,7 @@ impl Game<'_> {
}
}
Some("resume") => {
if let Some(r) = self.studio_replay.as_mut() {
if let Some(r) = self.studio.replay.as_mut() {
r.set_paused(false);
self.system_message(Text::translate("horizon.studio.replay.resumed", &[]));
} else {
@@ -323,7 +343,7 @@ impl Game<'_> {
return true;
};
if let Ok(spd) = spd_str.parse::<f64>() {
let new_speed = if let Some(r) = self.studio_replay.as_mut() {
let new_speed = if let Some(r) = self.studio.replay.as_mut() {
r.set_speed(spd);
Some(r.speed())
} else {
@@ -357,11 +377,12 @@ impl Game<'_> {
return true;
};
if let Ok(ms) = ms_str.parse::<u32>() {
if self.studio_replay.is_some() {
if self.studio.replay.is_some() {
match self.seek_studio_replay(ms) {
Ok(()) => {
let actual_ms = self
.studio_replay
.studio
.replay
.as_ref()
.map_or(ms, |replay| ms.min(replay.duration_ms()));
let ms_text = actual_ms.to_string();
@@ -400,7 +421,7 @@ impl Game<'_> {
}
}
Some("status") => {
if let Some(r) = self.studio_replay.as_ref() {
if let Some(r) = self.studio.replay.as_ref() {
let position = r.position_ms().to_string();
let duration = r.duration_ms().to_string();
let progress = format!("{:.1}", r.progress() * 100.0);
@@ -435,7 +456,7 @@ impl Game<'_> {
/// Reset playback tick accumulator and align positions on seek.
pub(super) fn reset_studio_playback_ticks(&mut self) {
self.studio_virtual_tick_ms = 0.0;
self.studio.virtual_tick_ms = 0.0;
if let Some(player) = &self.player {
self.previous_position = player.position;
if let Some(m) = self.player_model.as_mut() {
@@ -452,12 +473,14 @@ impl Game<'_> {
/// forward because its pre-replay world must remain intact.
pub(super) fn seek_studio_replay(&mut self, target_ms: u32) -> std::io::Result<()> {
let current_ms = self
.studio_replay
.studio
.replay
.as_ref()
.map_or(0, ReplayDriver::position_ms);
let packets = if self.studio_replay_standalone {
let packets = if self.studio.replay_standalone {
let packets = self
.studio_replay
.studio
.replay
.as_mut()
.expect("replay checked by caller")
.seek_and_collect(target_ms)?;
@@ -471,7 +494,8 @@ impl Game<'_> {
"backward seek requires a standalone replay",
));
}
self.studio_replay
self.studio
.replay
.as_mut()
.expect("replay checked by caller")
.seek_forward(target_ms)?
@@ -479,7 +503,7 @@ impl Game<'_> {
self.dispatch_studio_replay_packets(packets);
self.reset_studio_playback_ticks();
self.last_replay_tick = Some(std::time::Instant::now());
self.studio.last_replay_tick = Some(std::time::Instant::now());
Ok(())
}
@@ -510,19 +534,19 @@ impl Game<'_> {
/// Advance active replay playback by elapsed frame time and dispatch ready packets.
pub(super) fn advance_studio_replay(&mut self) -> Result<()> {
let Some(driver) = self.studio_replay.as_mut() else {
self.last_replay_tick = None;
let Some(driver) = self.studio.replay.as_mut() else {
self.studio.last_replay_tick = None;
return Ok(());
};
let now = std::time::Instant::now();
let delta = match self.last_replay_tick {
let delta = match self.studio.last_replay_tick {
Some(last) => now
.saturating_duration_since(last)
.min(Duration::from_millis(250)),
None => Duration::from_millis(16),
};
self.last_replay_tick = Some(now);
self.studio.last_replay_tick = Some(now);
let ready_packets = match driver.advance(delta) {
Ok(pkts) => pkts,
@@ -533,16 +557,18 @@ impl Game<'_> {
};
self.dispatch_studio_replay_packets(ready_packets);
if self.studio_freecam.locked_to_path
if self.studio.freecam.locked_to_path
&& let Some(position) = self
.studio_replay
.studio
.replay
.as_ref()
.map(|replay| replay.position_ms())
{
self.studio_freecam.update_spline_playback(position);
self.studio.freecam.update_spline_playback(position);
}
let paused = self
.studio_replay
.studio
.replay
.as_ref()
.is_some_and(|replay| replay.is_paused());
if self.player_model.is_none() {
@@ -550,13 +576,14 @@ impl Game<'_> {
}
if !paused {
let speed = self
.studio_replay
.studio
.replay
.as_ref()
.map_or(1.0, |r| r.speed() as f32)
.max(0.1);
self.studio_virtual_tick_ms += delta.as_secs_f32() * 1000.0 * speed;
while self.studio_virtual_tick_ms >= 50.0 {
self.studio_virtual_tick_ms -= 50.0;
self.studio.virtual_tick_ms += delta.as_secs_f32() * 1000.0 * speed;
while self.studio.virtual_tick_ms >= 50.0 {
self.studio.virtual_tick_ms -= 50.0;
if let Some(player) = &self.player {
let current_pos = player.position;
let (dx, dz) = (
@@ -607,7 +634,7 @@ impl Game<'_> {
m.previous_limb_speed = m.limb_speed;
}
if let Some((position, duration, paused, markers)) =
self.studio_replay.as_ref().map(|replay| {
self.studio.replay.as_ref().map(|replay| {
(
replay.position_ms(),
replay.duration_ms(),
@@ -616,10 +643,10 @@ impl Game<'_> {
)
})
{
self.studio_timeline.current_time_ms = u64::from(position);
self.studio_timeline.duration_ms = u64::from(duration);
self.studio_timeline.playing = !paused;
self.studio_timeline.markers = markers;
self.studio.timeline.current_time_ms = u64::from(position);
self.studio.timeline.duration_ms = u64::from(duration);
self.studio.timeline.playing = !paused;
self.studio.timeline.markers = markers;
}
Ok(())
}
@@ -639,10 +666,10 @@ impl Game<'_> {
self.capture(false);
}
TopBarAction::ExitStudio => {
if self.studio_replay.is_some() {
if self.studio.replay.is_some() {
self.close_studio_replay();
} else {
self.studio_freecam.deactivate();
self.studio.freecam.deactivate();
self.capture(false);
}
}
@@ -668,42 +695,46 @@ impl Game<'_> {
} else {
(glam::DVec3::ZERO, 0.0, 0.0)
};
self.studio_freecam
self.studio
.freecam
.activate(position, yaw, pitch, self.settings.fov);
}
TopBarAction::ToggleLockToPath => {
self.studio_freecam.locked_to_path = !self.studio_freecam.locked_to_path;
self.studio.freecam.locked_to_path = !self.studio.freecam.locked_to_path;
}
TopBarAction::ToggleFreecam => {
if self.studio_freecam.active {
self.studio_freecam.deactivate();
if self.studio.freecam.active {
self.studio.freecam.deactivate();
self.capture(false);
} else {
let (position, yaw, pitch) =
self.camera_view(0.0)
.unwrap_or((glam::DVec3::ZERO, 0.0, 0.0));
self.studio_freecam
self.studio
.freecam
.activate(position, yaw, pitch, self.settings.fov);
self.capture(true);
}
}
TopBarAction::AddKeyframe => {
self.studio_freecam
.add_keyframe_at_current(self.studio_timeline.current_time_ms as u32);
self.studio_camera_track_dirty = true;
self.studio
.freecam
.add_keyframe_at_current(self.studio.timeline.current_time_ms as u32);
self.studio.camera_track_dirty = true;
}
TopBarAction::AddMarker => self.add_studio_marker(),
TopBarAction::ClearKeyframes => {
self.studio_freecam.track.keyframes.clear();
self.studio_timeline.selected_keyframe = None;
self.studio_camera_track_dirty = true;
self.studio.freecam.track.keyframes.clear();
self.studio.timeline.selected_keyframe = None;
self.studio.camera_track_dirty = true;
}
TopBarAction::ToggleTimeline => {
self.studio_timeline.visible = !self.studio_timeline.visible;
self.studio.timeline.visible = !self.studio.timeline.visible;
}
TopBarAction::SplitClip => {
self.studio_timeline
.split_at(self.studio_timeline.current_time_ms);
self.studio
.timeline
.split_at(self.studio.timeline.current_time_ms);
}
}
}
@@ -716,93 +747,97 @@ impl Game<'_> {
use horizon_client::studio::TimelineAction;
match action {
TimelineAction::PauseForSeek => {
self.studio_timeline.playing = false;
if let Some(replay) = self.studio_replay.as_mut() {
self.studio.timeline.playing = false;
if let Some(replay) = self.studio.replay.as_mut() {
replay.set_paused(true);
}
}
TimelineAction::Seek(time_ms) => {
let time_ms = if self.studio_replay_standalone {
let time_ms = if self.studio.replay_standalone {
time_ms
} else {
let current =
self.studio_replay
self.studio
.replay
.as_ref()
.map_or(0, ReplayDriver::position_ms) as u64;
time_ms.max(current)
};
self.studio_timeline.current_time_ms = time_ms;
self.studio.timeline.current_time_ms = time_ms;
if let Err(error) = self.seek_studio_replay(time_ms.min(u32::MAX as u64) as u32) {
log::warn!("Studio timeline seek failed: {error}");
}
}
TimelineAction::TogglePlay => {
self.studio_timeline.playing = !self.studio_timeline.playing;
if let Some(replay) = self.studio_replay.as_mut() {
replay.set_paused(!self.studio_timeline.playing);
self.studio.timeline.playing = !self.studio.timeline.playing;
if let Some(replay) = self.studio.replay.as_mut() {
replay.set_paused(!self.studio.timeline.playing);
}
}
TimelineAction::StepBack => {
let time_ms = self.studio_timeline.current_time_ms.saturating_sub(1000);
let time_ms = self.studio.timeline.current_time_ms.saturating_sub(1000);
self.handle_studio_timeline_action(TimelineAction::Seek(time_ms));
}
TimelineAction::StepForward => {
let time_ms = self
.studio_timeline
.studio
.timeline
.current_time_ms
.saturating_add(1000)
.min(self.studio_timeline.duration_ms);
.min(self.studio.timeline.duration_ms);
self.handle_studio_timeline_action(TimelineAction::Seek(time_ms));
}
TimelineAction::SeekStart => {
self.handle_studio_timeline_action(TimelineAction::Seek(0))
}
TimelineAction::SeekEnd => self.handle_studio_timeline_action(TimelineAction::Seek(
self.studio_timeline.duration_ms,
self.studio.timeline.duration_ms,
)),
TimelineAction::SetSpeed(speed) => {
self.studio_timeline.speed = speed;
if let Some(replay) = self.studio_replay.as_mut() {
self.studio.timeline.speed = speed;
if let Some(replay) = self.studio.replay.as_mut() {
replay.set_speed(speed);
}
}
TimelineAction::ToggleFreecam => {
if self.studio_freecam.active {
self.studio_freecam.deactivate();
if self.studio.freecam.active {
self.studio.freecam.deactivate();
} else {
let (position, yaw, pitch) =
self.camera_view(0.0)
.unwrap_or((glam::DVec3::ZERO, 0.0, 0.0));
self.studio_freecam
self.studio
.freecam
.activate(position, yaw, pitch, self.settings.fov);
}
}
TimelineAction::AddCameraKeyframe => {
self.studio_freecam
.add_keyframe_at_current(self.studio_timeline.current_time_ms as u32);
self.studio_camera_track_dirty = true;
self.studio
.freecam
.add_keyframe_at_current(self.studio.timeline.current_time_ms as u32);
self.studio.camera_track_dirty = true;
}
TimelineAction::RemoveCameraKeyframe(index) => {
if index < self.studio_freecam.track.keyframes.len() {
self.studio_freecam.track.keyframes.remove(index);
self.studio_camera_track_dirty = true;
if index < self.studio.freecam.track.keyframes.len() {
self.studio.freecam.track.keyframes.remove(index);
self.studio.camera_track_dirty = true;
}
self.studio_timeline.selected_keyframe = None;
self.studio.timeline.selected_keyframe = None;
}
TimelineAction::SelectKeyframe(index) => {
self.studio_timeline.selected_keyframe = Some(index);
self.studio.timeline.selected_keyframe = Some(index);
}
TimelineAction::KeyframeMoved => {
self.studio_camera_track_dirty = true;
self.studio.camera_track_dirty = true;
}
TimelineAction::SplitClip(time_ms) => self.studio_timeline.split_at(time_ms),
TimelineAction::SplitClip(time_ms) => self.studio.timeline.split_at(time_ms),
TimelineAction::None => {}
}
}
/// Add a bookmark at the replay playhead and save it in the `.mcpr` archive.
pub(super) fn add_studio_marker(&mut self) {
let Some(replay) = self.studio_replay.as_mut() else {
let Some(replay) = self.studio.replay.as_mut() else {
return;
};
let label = Text::translate(
@@ -811,7 +846,7 @@ impl Game<'_> {
)
.plain();
match replay.add_marker(label) {
Ok(_) => self.studio_timeline.markers = replay.markers().to_vec(),
Ok(_) => self.studio.timeline.markers = replay.markers().to_vec(),
Err(error) => log::warn!("Studio: could not save replay marker: {error}"),
}
}
@@ -845,7 +880,7 @@ impl Game<'_> {
Ok(Some(res))
}
Some("pause") => {
if let Some(r) = self.studio_replay.as_mut() {
if let Some(r) = self.studio.replay.as_mut() {
r.set_paused(true);
Ok(Some(json!({ "ok": true, "paused": true })))
} else {
@@ -853,7 +888,7 @@ impl Game<'_> {
}
}
Some("resume") => {
if let Some(r) = self.studio_replay.as_mut() {
if let Some(r) = self.studio.replay.as_mut() {
r.set_paused(false);
Ok(Some(json!({ "ok": true, "paused": false })))
} else {
@@ -863,7 +898,7 @@ impl Game<'_> {
Some("speed") => {
let spd_str = words.get(3).ok_or("missing speed value")?;
let spd: f64 = spd_str.parse().map_err(|_| "invalid speed")?;
if let Some(r) = self.studio_replay.as_mut() {
if let Some(r) = self.studio.replay.as_mut() {
r.set_speed(spd);
Ok(Some(json!({ "ok": true, "speed": r.speed() })))
} else {
@@ -873,7 +908,7 @@ impl Game<'_> {
Some("seek") => {
let ms_str = words.get(3).ok_or("missing seek timestamp")?;
let ms: u32 = ms_str.parse().map_err(|_| "invalid timestamp")?;
let pos = if let Some(r) = self.studio_replay.as_mut() {
let pos = if let Some(r) = self.studio.replay.as_mut() {
r.seek(ms).map_err(|e| format!("{e}"))?;
Some(r.position_ms())
} else {
@@ -887,7 +922,7 @@ impl Game<'_> {
}
}
Some("status") => {
if let Some(r) = self.studio_replay.as_ref() {
if let Some(r) = self.studio.replay.as_ref() {
Ok(Some(json!({
"ok": true,
"active": true,
@@ -999,13 +1034,13 @@ impl Game<'_> {
}
pub(super) fn open_studio_replay(&mut self, path: &str) -> Result<Value> {
if self.studio_camera_track_dirty
&& let Some(active) = self.studio_replay.as_mut()
if self.studio.camera_track_dirty
&& let Some(active) = self.studio.replay.as_mut()
{
if let Err(error) = active.save_camera_track(&self.studio_freecam.track) {
if let Err(error) = active.save_camera_track(&self.studio.freecam.track) {
return Ok(json!({ "ok": false, "error": error.to_string() }));
}
self.studio_camera_track_dirty = false;
self.studio.camera_track_dirty = false;
}
// The recordings browser can be opened while the title screen is
// available but the slower world tables are still loading. Replay
@@ -1028,7 +1063,7 @@ impl Game<'_> {
}
};
let standalone = self.studio_replay.is_none() && self.remote.is_none();
let standalone = self.studio.replay.is_none() && self.remote.is_none();
if self.remote.is_none()
&& let Err(error) = self.init_remote_for_replay()
{
@@ -1038,17 +1073,17 @@ impl Game<'_> {
let duration_ms = driver.duration_ms();
let packets = driver.packet_count();
self.studio_timeline.duration_ms = u64::from(duration_ms);
self.studio_timeline.current_time_ms = 0;
self.studio_timeline.playing = !driver.is_paused();
self.studio_timeline.markers = driver.markers().to_vec();
self.studio_freecam.track = driver.camera_track().cloned().unwrap_or_default();
self.studio_camera_track_dirty = false;
if self.studio_replay.is_none() {
self.studio_replay_previous_camera_type = Some(self.camera_type);
self.studio_replay_standalone = standalone;
self.studio.timeline.duration_ms = u64::from(duration_ms);
self.studio.timeline.current_time_ms = 0;
self.studio.timeline.playing = !driver.is_paused();
self.studio.timeline.markers = driver.markers().to_vec();
self.studio.freecam.track = driver.camera_track().cloned().unwrap_or_default();
self.studio.camera_track_dirty = false;
if self.studio.replay.is_none() {
self.studio.replay_previous_camera_type = Some(self.camera_type);
self.studio.replay_standalone = standalone;
}
self.studio_replay = Some(driver);
self.studio.replay = Some(driver);
self.camera_type = super::perspective::CameraType::FirstPerson;
self.title = None;
self.screen = Screen::Playing;
@@ -1066,14 +1101,14 @@ impl Game<'_> {
}))
}
pub(super) fn close_studio_replay(&mut self) -> bool {
if self.studio_camera_track_dirty
&& let Some(driver) = self.studio_replay.as_mut()
&& let Err(error) = driver.save_camera_track(&self.studio_freecam.track)
if self.studio.camera_track_dirty
&& let Some(driver) = self.studio.replay.as_mut()
&& let Err(error) = driver.save_camera_track(&self.studio.freecam.track)
{
log::warn!("Studio: could not save camera path: {error}");
}
self.studio_camera_track_dirty = false;
let closed = self.studio_replay.take().is_some();
self.studio.camera_track_dirty = false;
let closed = self.studio.replay.take().is_some();
if !closed {
return false;
}
@@ -1081,23 +1116,23 @@ impl Game<'_> {
// A standalone replay owns a synthetic Remote connection. Treat that
// connection as replay state even if the saved origin flag was lost;
// sending it through leave_server() opens the Multiplayer screen.
let standalone = self.studio_replay_standalone
let standalone = self.studio.replay_standalone
|| self
.remote
.as_ref()
.is_some_and(|remote| remote.brand == "horizon-studio");
self.studio_replay_standalone = false;
if let Some(camera_type) = self.studio_replay_previous_camera_type.take() {
self.studio.replay_standalone = false;
if let Some(camera_type) = self.studio.replay_previous_camera_type.take() {
self.camera_type = camera_type;
}
self.last_replay_tick = None;
self.studio_timeline.current_time_ms = 0;
self.studio_timeline.playing = false;
self.studio_timeline.markers.clear();
self.studio_timeline.split_points.clear();
self.studio_timeline.selected_keyframe = None;
self.studio_freecam.deactivate();
self.studio_virtual_tick_ms = 0.0;
self.studio.last_replay_tick = None;
self.studio.timeline.current_time_ms = 0;
self.studio.timeline.playing = false;
self.studio.timeline.markers.clear();
self.studio.timeline.split_points.clear();
self.studio.timeline.selected_keyframe = None;
self.studio.freecam.deactivate();
self.studio.virtual_tick_ms = 0.0;
self.capture(false);
if standalone {
if let Some(mut remote) = self.remote.take() {
+1 -1
View File
@@ -149,7 +149,7 @@ impl Game<'_> {
self.audio
.play_unshared("minecraft:item.totem.use", Some(body.bounds.feet), 1.0, 1.0);
if target == TrackingTarget::LocalPlayer {
self.pad_rumble(horizon_client::gamepad::Rumble::Totem);
self.input_feedback(horizon_client::input_source::Feedback::Totem);
// findTotem, then LocalPlayer.displayItemActivation. The offsets
// come from the player's own random in vanilla, not the level's:
// the client-only particle random stands in for it. The server
+1 -1
View File
@@ -298,7 +298,7 @@ impl super::Game<'_> {
.into_iter()
.any(|action| self.keys.held(action))
|| self
.pad_move()
.input_move()
.is_some_and(|[left, forward]| left.abs() > 0.3 || forward.abs() > 0.3))
{
self.tutorial.input();
@@ -107,9 +107,9 @@ impl Game<'_> {
state: ElementState::Pressed,
..
}
) && !self.pad.menu.synthetic
) && !self.input_made_pointer_event()
{
self.pad.keyboard_took_over = true;
self.input_keyboard_used();
}
if let WindowEvent::MouseInput { state, button, .. } = &event {
if *state == ElementState::Pressed {
@@ -245,7 +245,7 @@ impl Game<'_> {
// Pause-menu and death-screen exits use the normal world-close action.
// A standalone replay owns a synthetic remote session, so it must go
// through replay cleanup instead of being treated like a server.
if self.studio_replay.is_some() {
if self.studio.replay.is_some() {
self.close_studio_replay();
return Ok(());
}
+43
View File
@@ -165,6 +165,22 @@ impl<T: Joined> JoinList<T> {
self.push(entity);
}
}
/// An entity that never left its level keeps its place in
/// `EntityTickList`: one a pass took out and puts back (an arrow bouncing
/// off) goes back before the first entity that joined after it. One that
/// has not joined yet is appended and numbered, as by `push`.
pub fn put_back(&mut self, entity: T) {
let seq = entity.join_seq();
let at = if seq.is_joined() {
self.list
.iter()
.position(|q| q.join_seq() > seq)
.unwrap_or(self.list.len())
} else {
self.list.len()
};
self.insert(at, entity);
}
}
impl<'a, T> IntoIterator for &'a JoinList<T> {
@@ -193,6 +209,33 @@ impl<T> IntoIterator for JoinList<T> {
mod tests {
use super::*;
#[derive(Debug)]
struct E {
join: JoinSeq,
}
crate::impl_joined!(E);
/// A numbered entity put back lands by its join number; a new one goes last.
#[test]
fn put_back_keeps_the_join_order() {
let mut list = JoinList::default();
for _ in 0..3 {
list.push(E {
join: JoinSeq::UNJOINED,
});
}
let first = list.remove(0);
let first_seq = first.join;
list.put_back(first);
assert_eq!(list[0].join, first_seq, "back before the later joins");
list.put_back(E {
join: JoinSeq::UNJOINED,
});
let seqs: Vec<_> = list.iter().map(|e| e.join).collect();
assert!(seqs.windows(2).all(|w| w[0] < w[1]), "{seqs:?}");
assert_eq!(seqs.len(), 4);
}
/// Whatever can change a list changes its stamp; only reading leaves it.
#[test]
fn a_stamp_holds_until_the_list_can_have_changed() {
@@ -53,6 +53,27 @@ pub fn exists(world: &Path, uuid: u128) -> bool {
path(world, uuid).is_file()
}
/// The key `ServerPlayer.addAdditionalSaveData` stores the `WardenSpawnTracker` under.
pub const WARDEN_TRACKER_KEY: &str = "warden_spawn_tracker";
/// Put a player's `warden_spawn_tracker` into the compound `store` writes from
/// (`guest.saved`), so a save keeps it rather than the older one loaded with
/// the file (the LAN owner's tracker lives in `Game`, `save_warden_tracker`).
/// Other saved keys are left as they are; no tracker (not loaded yet) changes
/// nothing.
pub fn with_warden(guest: &mut Guest, tracker: Option<Tag>) -> &mut Guest {
let Some(tracker) = tracker else {
return guest;
};
let saved = guest
.saved
.get_or_insert_with(|| Tag::Compound(Default::default()));
if let Tag::Compound(map) = saved {
map.insert(WARDEN_TRACKER_KEY.into(), tracker);
}
guest
}
/// `PlayerDataStorage.load`: a guest's saved state, if they have been here
/// before. The player's file, else its `.dat_old` (what a save cut off
/// between its two renames leaves, `write_dat`).
@@ -651,6 +672,42 @@ mod tests {
)
}
/// #9965: the owner's warden warning level and cooldown reach the file on
/// a save, instead of the ones the file was loaded with.
#[test]
fn a_stored_warden_tracker_replaces_the_loaded_one() {
let mut g = guest();
g.saved = Some(Tag::compound(vec![
(
"warden_spawn_tracker",
Tag::compound(vec![
("warning_level", Tag::Int(2)),
("cooldown_ticks", Tag::Int(77)),
("ticks_since_last_warning", Tag::Int(5)),
]),
),
("unrelated_key", Tag::Int(9)),
]));
let tracker = crate::sculk::WardenSpawnTracker {
ticks_since_last_warning: 0,
warning_level: 3,
cooldown_ticks: 200,
};
with_warden(&mut g, Some(tracker.to_nbt()));
let (tag, _) = round_trip(&g);
let mut back = guest();
let mut level = Level::default();
level.read_player(&tag);
level.player_extra = Some(tag);
apply(&mut back, &level);
let saved = back.saved.as_ref().unwrap();
let read =
crate::sculk::WardenSpawnTracker::from_nbt(saved.get("warden_spawn_tracker").unwrap());
assert_eq!((read.warning_level, read.cooldown_ticks), (3, 200));
assert_eq!(read.ticks_since_last_warning, 0);
assert!(matches!(saved.get("unrelated_key"), Some(Tag::Int(9))));
}
#[test]
fn a_new_player_faces_the_world_spawn_angle() {
let mut g = guest();
+111 -9
View File
@@ -246,7 +246,9 @@ impl Goal for DefendVillage {
// wider, as the box test is strict).
let near = b.inflate(Vec3::new(1.0, 1.0, 1.0));
// Villager.getPlayerReputation of the player this golem sees: the
// villager's gossips about that player's own UUID.
// villager's gossips about that player's own UUID. The villagers come
// through the same `attackTargeting` (`forCombat().range(64)`), so the
// golem must see them too.
let bad = cx.w.others_near(near).any(|s| {
s.species == Species::Villager
&& s.alive
@@ -255,6 +257,7 @@ impl Goal for DefendVillage {
.is_some_and(|v| v.gossips.reputation(p.uuid) <= -100)
&& b.contains(s.position)
&& s.position.distance_squared(m.position) <= 64.0 * 64.0
&& m.sees(cx.w, Who::Mob(s.id))
});
bad && m.sees(cx.w, Who::Player)
}
@@ -322,6 +325,39 @@ impl Goal for MoveTowardsTarget {
m.nav_stop();
}
}
impl Mob {
/// `IronGolem.mobInteract`: the repair sound's pitch comes from the
/// golem's own random, not the level's.
pub fn golem_repair_pitch(&mut self) -> f32 {
1.0 + (self.random.next_float() - self.random.next_float()) * 0.2
}
}
/// `Level.isBrightOutside`: a fixed-time dimension (the End) is never bright.
fn bright_outside(w: &MobWorld) -> bool {
w.daylight && !w.dimension_type.has_fixed_time
}
/// `OfferFlowerGoal.getNearestEntity`: the nearest of
/// #candidate_for_iron_golem_gift (villagers and copper golems) in the golem's
/// box inflated by (6, 2, 6) that passes `forNonCombat().range(6.0)`: within
/// six blocks and in sight.
fn gift_candidate(m: &mut Mob, w: &MobWorld) -> Option<u32> {
let area = m.bounds().inflate(Vec3::new(6.0, 2.0, 6.0));
let mut best: Option<(f64, u32)> = None;
for s in w.others_near(area) {
if !matches!(s.species, Species::Villager | Species::CopperGolem)
|| !s.alive
|| !area.intersects(s.bounds)
{
continue;
}
let d = s.position.distance_squared(m.position);
if d > 36.0 || best.is_some_and(|(b, _)| d >= b) || !m.sees(w, Who::Mob(s.id)) {
continue;
}
best = Some((d, s.id));
}
best.map(|(_, id)| id)
}
/// `OfferFlowerGoal`: by day, now and then, hold out a poppy to a villager.
#[derive(Clone, Debug)]
struct OfferFlower {
@@ -334,16 +370,10 @@ impl Goal for OfferFlower {
MOVE | LOOK
}
fn can_use(&mut self, m: &mut Mob, cx: &mut Cx) -> bool {
if !cx.w.daylight || m.random.next_int_bound(8000).unwrap_or(1) != 0 {
if !bright_outside(cx.w) || m.random.next_int_bound(8000).unwrap_or(1) != 0 {
return false;
}
// The nearest of #candidate_for_iron_golem_gift: villagers and copper golems.
self.villager =
cx.w.nearby(m.position, 6.0, |s| {
matches!(s.species, Species::Villager | Species::CopperGolem) && s.alive
})
.map(|s| s.id)
.next();
self.villager = gift_candidate(m, cx.w);
self.villager.is_some()
}
fn can_continue(&mut self, _: &mut Mob, _: &mut Cx) -> bool {
@@ -612,6 +642,78 @@ mod tests {
Mob::new(id, Arc::new(kind), at, 0.0)
}
fn villager_at(id: u32, at: Vec3) -> crate::mobs::Seen {
mob(id, Species::Villager, at).seen(None)
}
fn pick(w: &MobWorld) -> Option<u32> {
let mut golem = mob(1, Species::IronGolem, Vec3::new(0.5, 64.0, 0.5));
gift_candidate(&mut golem, w)
}
fn with_chunks(world: &mut crate::world::World, _: &horizon_world::registry::BlockRegistry) {
for cx in -2..2 {
for cz in -2..2 {
world.chunks.insert(
(cx, cz),
std::sync::Arc::new(crate::chunk::Chunk::empty(cx, cz)),
);
}
}
}
/// `OfferFlowerGoal`: the search box is the golem's box inflated by
/// (6, 2, 6) and the candidate must be within six blocks (Euclidean).
#[test]
fn the_poppy_goes_to_a_villager_in_the_box_within_six_blocks() {
let cases = [
(Vec3::new(4.5, 64.0, 0.5), true),
// 6.5 blocks on one axis: outside the range.
(Vec3::new(7.0, 64.0, 0.5), false),
// About 8.5 blocks away, inside the per-axis box of six.
(Vec3::new(6.0, 64.0, 6.0), false),
// Five blocks above: outside the box's two-block rise.
(Vec3::new(0.5, 69.0, 0.5), false),
];
for (at, offered) in cases {
let villager = villager_at(2, at);
crate::mobs::world::with_built_test_world(&[villager], with_chunks, |w, _| {
assert_eq!(pick(w).is_some(), offered, "villager at {at:?}");
});
}
}
/// The candidate must also be in sight, and a fixed-time dimension is
/// never bright outside.
#[test]
fn the_poppy_needs_sight_and_a_dimension_with_a_day() {
let villager = villager_at(2, Vec3::new(4.5, 64.0, 0.5));
let wall = |world: &mut crate::world::World, r: &horizon_world::registry::BlockRegistry| {
with_chunks(world, r);
let stone = r.default_state("minecraft:stone").unwrap();
for y in 62..70 {
for z in -6..8 {
world.set(2, y, z, stone).unwrap();
}
}
};
crate::mobs::world::with_built_test_world(std::slice::from_ref(&villager), wall, |w, _| {
assert_eq!(pick(w), None, "a villager behind a wall");
});
crate::mobs::world::with_built_test_world(&[villager], with_chunks, |w, _| {
assert!(bright_outside(w));
assert_eq!(pick(w), Some(2));
let mut end = w.clone();
end.dimension_type =
horizon_world::dimension_type::DimensionFacts::vanilla("minecraft:the_end")
.unwrap();
assert!(!bright_outside(&end));
let mut night = w.clone();
night.daylight = false;
assert!(!bright_outside(&night));
});
}
#[test]
fn snow_trail_posts_block_place_with_golem_and_snow_state() {
let ran = crate::mobs::world::with_built_test_world(
+48 -3
View File
@@ -855,9 +855,11 @@ pub fn texture(m: &Mob) -> String {
"red",
"black",
];
match COLORS.get(m.extra.color as usize) {
Some(c) => format!("entity/shulker/shulker_{c}"),
None => "entity/shulker/shulker".into(),
// Shulker.getColor: the saved byte is signed; 16 and above are undyed, and
// DyeColor.byId sends a negative id to white (OutOfBoundsStrategy.ZERO).
match m.extra.color as i8 {
16.. => "entity/shulker/shulker".into(),
c => format!("entity/shulker/shulker_{}", COLORS[c.max(0) as usize]),
}
}
/// `attachFace.getOpposite().getRotation()` by attach face: the open
@@ -1144,3 +1146,46 @@ mod tests {
assert!((h - 1.0).abs() < 1e-9, "{h}");
}
}
#[cfg(test)]
mod saved_bytes_tests {
use super::*;
/// `Shulker.readAdditionalSaveData`: `AttachFace` is
/// `Direction.LEGACY_ID_CODEC` (`from3DDataValue` wraps the id through
/// `abs(id % 6)`), while `Peek` and `Color` are raw `getByteOr` bytes. The
/// load clamped all three to their setters' ranges instead.
#[test]
fn a_shulker_reads_its_face_and_lid_bytes_like_vanilla() {
use crate::entity_nbt::mob_from_nbt;
use horizon_world::nbt::Tag;
let mut kind = crate::mobs::sensor_scan_tests::kind();
let k = std::sync::Arc::make_mut(&mut kind);
k.id = "minecraft:shulker".into();
k.species = Species::Shulker;
let types = [("minecraft:shulker".into(), kind)].into();
let tag = Tag::compound([
("id", Tag::String("minecraft:shulker".into())),
(
"Pos",
Tag::List(vec![
Tag::Double(0.0f64.to_bits()),
Tag::Double(64.0f64.to_bits()),
Tag::Double(0.0f64.to_bits()),
]),
),
("AttachFace", Tag::Byte(7)),
("Peek", Tag::Byte(-1)),
("Color", Tag::Byte(-1)),
]);
let m = mob_from_nbt(&tag, &types, 1, None).unwrap();
assert_eq!(m.extra.variant3, 1, "abs(7 % 6) is up");
assert_eq!(m.extra.counter, -1, "the peek byte is kept");
assert_eq!(m.extra.color, 255, "the color byte is kept");
assert_eq!(
texture(&m),
"entity/shulker/shulker_white",
"DyeColor.byId(-1)"
);
}
}
+15 -17
View File
@@ -2148,18 +2148,16 @@ impl MotionWorld<'_, '_, '_> {
let gravity = living_motion::effective_gravity(self)?;
self.player.velocity = fall_flying_movement(v, self.player.pitch, self.player.yaw, gravity);
let movement = self.player.velocity;
let before = self.player.position;
self.move_self(movement)?;
// LivingEntity.handleFallFlyingCollisions: the fall-damage sound plays
// on both sides (a glider's own travel is client-side, and the sound
// must reach its own ears, #8906), only the server hurts, and it
// compares the delta before the move with the one after it, which
// `Entity.move` leaves as the movement it resolved. `move_entity` does
// not write that back, so the distance actually travelled stands in.
// compares the horizontal speed before `updateFallFlyingMovement`
// with the delta `Entity.move` leaves (the collided axes zeroed).
if self.player.collision.horizontal {
let travelled = self.player.position.subtract(before);
let new_h = (travelled.x * travelled.x + travelled.z * travelled.z).sqrt();
let dmg = fly_into_wall_damage(move_h, new_h);
let v = self.player.velocity;
let after_h = (v.x * v.x + v.z * v.z).sqrt();
let dmg = fly_into_wall_damage(move_h, after_h);
if dmg > 0.0 {
let first = self.player.events.len();
// getFallDamageSound((int) dmg)
@@ -3148,6 +3146,7 @@ mod tests {
assert_eq!(fly_into_wall_damage(0.3, 0.0), 0.0);
assert!((fly_into_wall_damage(0.5, 0.1) - 1.0).abs() < 1e-5);
assert!((fly_into_wall_damage(1.2, 0.0) - 9.0).abs() < 1e-5);
assert!(fly_into_wall_damage(0.01, 0.0) < 0.0);
}
use super::*;
@@ -4195,17 +4194,16 @@ mod tests {
health: &resources.health,
};
w.travel_fall_flying().unwrap();
assert!(
w.player.events.iter().any(|e| matches!(
let is_fall = |e: &_| {
matches!(
e,
MotionEvent::Fall(crate::landing::FallEvent::Sound {
sound: crate::landing::SceneSound::SmallFall,
..
})
)),
"{:?}",
w.player.events
);
MotionEvent::Fall(crate::landing::FallEvent::Sound { .. })
)
};
assert_eq!(w.player.events.iter().filter(|e| is_fall(e)).count(), 1);
// The sound must play only once on impact, not repeat on subsequent ticks (#12304):
w.travel_fall_flying().unwrap();
assert_eq!(w.player.events.iter().filter(|e| is_fall(e)).count(), 1);
assert!(
!w.player
.hurt_log
+36 -5
View File
@@ -852,14 +852,24 @@ fn parse_recipe_sources<'a>(
"minecraft:stonecutting" => {
// A result count outside 1..=99 fails vanilla's codec: no recipe.
if let Some(count) = crate::crafting::template_count(&v["result"]) {
stonecutting.push(Stonecutting {
id,
input: ingredient(&v["ingredient"], items),
result: ItemStack::new(
let result = if v["result"].get("components").is_some() {
match SmithingResult::parse(&v["result"], defaults)
.and_then(|result| result.create())
{
Some(result) => result,
None => continue,
}
} else {
ItemStack::new(
horizon_world::loot::recipe_result_id(&v["result"])
.unwrap_or("minecraft:air"),
count,
),
)
};
stonecutting.push(Stonecutting {
id,
input: ingredient(&v["ingredient"], items),
result,
});
}
}
@@ -2216,6 +2226,27 @@ mod tests {
vec!["minecraft:diamond_sword", "minecraft:diamond_axe"]
);
}
#[test]
fn stonecutter_result_keeps_its_components() {
let root = std::env::temp_dir().join(format!(
"horizon-stonecutter-components-{}",
std::process::id()
));
let dir = root.join("data/minecraft/recipe");
fs::create_dir_all(&dir).unwrap();
fs::write(root.join("items.json"), r#"{"minecraft:stone":{}}"#).unwrap();
fs::write(
dir.join("cut.json"),
r#"{"type":"minecraft:stonecutting","ingredient":"minecraft:stone","result":{"id":"minecraft:stone","components":{"minecraft:custom_name":"Cut Stone"}}}"#,
)
.unwrap();
let recipes = StationRecipes::load(&root, &sample_items(), &PackOverlay::NONE);
let _ = fs::remove_dir_all(&root);
let listed = recipes.stonecutter(&ItemStack::new("minecraft:stone", 1));
assert_eq!(listed.len(), 1);
assert_eq!(listed[0].result.custom_name().as_deref(), Some("Cut Stone"));
}
/// A world pack's stonecutting recipe takes its place in registration
/// order (path, then namespace), not a place after the game's own.
#[test]
+9
View File
@@ -47,6 +47,15 @@ pub fn open_vulkan_device(
Some(unsafe { adapter.create_device_from_hal(open, desc) })
}
/// wgpu's opt-in to its `EXPERIMENTAL_*` features, which the crates that forbid unsafe code
/// can't give: hardware ray queries, asked for only when the player turns ray tracing on
/// (`gfx/ray_query.rs` in horizon-client-render).
pub fn experimental_features() -> wgpu::ExperimentalFeatures {
// Safety: wgpu warns that its experimental features may have bugs that reach undefined
// behaviour through safe calls. Horizon accepts that only on request, for ray queries.
unsafe { wgpu::ExperimentalFeatures::enabled() }
}
/// Tells the compositor, through `VK_EXT_hdr_metadata`, that the swapchain's
/// content is BT.709, peaks at `peak` nits and is no darker than `black`. Needs a
/// device from `open_vulkan_device` and a configured surface; does nothing otherwise.
+267
View File
@@ -0,0 +1,267 @@
//! The numeric fast path: a program of one expression whose every part is a number (constants,
//! arithmetic, comparisons of numbers, math functions, ternaries and `root.method(...)` calls) is
//! compiled again into a tree of `f64`s, which runs without the interpreter's `Value`s and
//! `Result`s. It answers exactly what the interpreter would: anything that could tell them apart
//! (strings, objects, `==` on a method's value, locals, game functions) keeps the interpreter.
use super::parse::{BinOp, Expr, Stmt};
use super::{Field, Host, MathFn, Root, Value};
use std::sync::Arc;
/// What a node gives: always a number, always a boolean, or whatever a host method answers.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
enum Kind {
Num,
Bool,
Unknown,
}
/// A method argument, handed to the host as the interpreter would: a constant of any kind
/// (`o.custom('glow')`), another method's own value, or a number or boolean.
#[derive(Debug)]
pub(super) enum Arg {
Value(Value),
Method(Num),
Num(Num, bool),
}
#[derive(Debug)]
pub(super) enum Num {
Const(f64),
Neg(Box<Num>),
Not(Box<Num>),
Bin(BinOp, Box<Num>, Box<Num>),
And(Box<Num>, Box<Num>),
Or(Box<Num>, Box<Num>),
Cond(Box<Num>, Box<Num>, Box<Num>),
Call(MathFn, Vec<Num>),
Method(Root, Arc<str>, Vec<Arg>),
/// A method without arguments the host may answer by [`Field`] (its name otherwise).
Field(Root, Field, Arc<str>),
}
/// The fast form of a whole program, with the kind of value it gives.
#[derive(Debug)]
pub(super) struct Fast {
root: Num,
kind: Kind,
}
impl Fast {
/// The fast form of a program, when it is one expression the fast path covers.
pub(super) fn of(body: &[Stmt], locals: usize) -> Option<Self> {
let [Stmt::Expr(e)] = body else {
return None;
};
if locals != 0 {
return None;
}
let root = Num::of(e)?;
let kind = root.kind();
// A method at the top hands back its own value; elsewhere the kind must be known.
(kind != Kind::Unknown || matches!(root, Num::Method(..) | Num::Field(..)))
.then_some(Self { root, kind })
}
pub(super) fn eval(&self, host: &mut dyn Host) -> Result<Value, String> {
match &self.root {
Num::Method(root, name, args) => return call(host, *root, name, args),
Num::Field(root, field, name) => return field_value(host, *root, *field, name),
_ => {}
}
let n = self.root.eval(host)?;
Ok(match self.kind {
Kind::Bool => Value::Bool(n != 0.0),
_ => Value::Num(n),
})
}
}
fn field_value(host: &mut dyn Host, root: Root, field: Field, name: &str) -> Result<Value, String> {
match host.field(root, field) {
Some(value) => Ok(value),
None => call(host, root, name, &[]),
}
}
fn call(host: &mut dyn Host, root: Root, name: &str, args: &[Arg]) -> Result<Value, String> {
const FEW: usize = 4;
let target = host.root(root);
if args.is_empty() {
return host.method(&target, name, &[]);
}
let mut values: [Value; FEW] = std::array::from_fn(|_| Value::Null);
if args.len() > FEW {
let all = args
.iter()
.map(|a| a.value(host))
.collect::<Result<Vec<_>, _>>()?;
return host.method(&target, name, &all);
}
for (slot, arg) in values.iter_mut().zip(args) {
*slot = arg.value(host)?;
}
host.method(&target, name, &values[..args.len()])
}
impl Arg {
fn value(&self, host: &mut dyn Host) -> Result<Value, String> {
Ok(match self {
Self::Value(v) => v.clone(),
Self::Method(Num::Method(root, name, args)) => call(host, *root, name, args)?,
Self::Method(Num::Field(root, field, name)) => field_value(host, *root, *field, name)?,
Self::Method(n) | Self::Num(n, false) => Value::Num(n.eval(host)?),
Self::Num(n, true) => Value::Bool(n.eval(host)? != 0.0),
})
}
}
/// Whether a subtree calls the host, whose answer may be no number.
fn has_method(e: &Expr) -> bool {
match e {
Expr::Method(..) => true,
Expr::Neg(a) | Expr::Not(a) => has_method(a),
Expr::Binary(_, a, b) | Expr::And(a, b) | Expr::Or(a, b) => has_method(a) || has_method(b),
Expr::Cond(c, a, b) => has_method(c) || has_method(a) || has_method(b),
Expr::Call(_, args) | Expr::Host(_, args) => args.iter().any(has_method),
_ => false,
}
}
impl Num {
fn of(e: &Expr) -> Option<Self> {
let boxed = |e: &Expr| Self::of(e).map(Box::new);
Some(match e {
Expr::Const(Value::Num(n)) => Self::Const(*n),
Expr::Const(_) | Expr::Local(_) | Expr::Root(_) | Expr::Host(..) => return None,
Expr::Neg(a) => Self::Neg(boxed(a)?),
Expr::Not(a) => Self::Not(boxed(a)?),
Expr::Binary(op, a, b) => {
// `==` and `!=` also compare strings and objects: only between plain numbers.
if matches!(op, BinOp::Eq | BinOp::Ne) && (has_method(a) || has_method(b)) {
return None;
}
Self::Bin(*op, boxed(a)?, boxed(b)?)
}
Expr::And(a, b) => Self::And(boxed(a)?, boxed(b)?),
Expr::Or(a, b) => Self::Or(boxed(a)?, boxed(b)?),
Expr::Cond(c, a, b) => Self::Cond(boxed(c)?, boxed(a)?, boxed(b)?),
Expr::Call(f, args) => {
Self::Call(*f, args.iter().map(Self::of).collect::<Option<_>>()?)
}
Expr::Method(target, name, args) => {
let Expr::Root(root) = **target else {
return None;
};
if let (true, Some(field)) = (args.is_empty(), Field::of(name)) {
return Some(Self::Field(root, field, name.clone()));
}
let args = args
.iter()
.map(|a| match a {
Expr::Const(v) => Some(Arg::Value(v.clone())),
other => {
let n = Self::of(other)?;
match n.kind() {
Kind::Unknown
if matches!(n, Self::Method(..) | Self::Field(..)) =>
{
Some(Arg::Method(n))
}
// A ternary between method values: the interpreter's own value.
Kind::Unknown => None,
kind => Some(Arg::Num(n, kind == Kind::Bool)),
}
}
})
.collect::<Option<_>>()?;
Self::Method(root, name.clone(), args)
}
})
}
fn kind(&self) -> Kind {
match self {
Self::Const(_) | Self::Neg(_) | Self::Call(..) => Kind::Num,
Self::Bin(op, ..) => match op {
BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => Kind::Bool,
_ => Kind::Num,
},
Self::Not(_) | Self::And(..) | Self::Or(..) => Kind::Bool,
Self::Cond(_, a, b) => match (a.kind(), b.kind()) {
(x, y) if x == y => x,
_ => Kind::Unknown,
},
Self::Method(..) | Self::Field(..) => Kind::Unknown,
}
}
/// The value as a number, as the interpreter's `Value::num` reads it.
fn eval(&self, host: &mut dyn Host) -> Result<f64, String> {
Ok(match self {
Self::Const(n) => *n,
Self::Neg(a) => -a.eval(host)?,
Self::Not(a) => f64::from(u8::from(!a.truthy(host)?)),
Self::Bin(op, a, b) => {
let (x, y) = (a.eval(host)?, b.eval(host)?);
let t = |b: bool| f64::from(u8::from(b));
match op {
BinOp::Add => x + y,
BinOp::Sub => x - y,
BinOp::Mul => x * y,
BinOp::Div => x / y,
BinOp::Rem => x % y,
BinOp::Pow => x.powf(y),
BinOp::Eq => t(x == y),
BinOp::Ne => t(x != y),
BinOp::Lt => t(x < y),
BinOp::Le => t(x <= y),
BinOp::Gt => t(x > y),
BinOp::Ge => t(x >= y),
}
}
Self::And(a, b) => f64::from(u8::from(a.truthy(host)? && b.truthy(host)?)),
Self::Or(a, b) => f64::from(u8::from(a.truthy(host)? || b.truthy(host)?)),
Self::Cond(c, a, b) => {
if c.truthy(host)? {
a.eval(host)?
} else {
b.eval(host)?
}
}
Self::Call(f, args) if args.len() <= 4 => {
let mut nums = [0.0; 4];
for (slot, arg) in nums.iter_mut().zip(args) {
*slot = arg.eval(host)?;
}
f(&nums[..args.len()])
}
Self::Call(f, args) => {
let nums = args
.iter()
.map(|a| a.eval(host))
.collect::<Result<Vec<_>, _>>()?;
f(&nums)
}
Self::Method(root, name, args) => call(host, *root, name, args)?.num(),
Self::Field(root, field, name) => field_value(host, *root, *field, name)?.num(),
})
}
/// The value's truth, as the interpreter's `Value::truthy` reads it: a method's own answer
/// (a string or an object is true), else whether the number isn't 0.
fn truthy(&self, host: &mut dyn Host) -> Result<bool, String> {
match self {
Self::Method(root, name, args) => Ok(call(host, *root, name, args)?.truthy()),
Self::Field(root, field, name) => Ok(field_value(host, *root, *field, name)?.truthy()),
Self::Cond(c, a, b) => {
if c.truthy(host)? {
a.truthy(host)
} else {
b.truthy(host)
}
}
other => Ok(other.eval(host)? != 0.0),
}
}
}
+50 -1
View File
@@ -3,6 +3,7 @@
//! loads, with every name resolved, and then evaluated against a [`Host`], the game side that
//! answers context objects (`o`, `p`, `g`...) and their methods.
mod colors;
mod fast;
mod legacy;
mod lex;
mod parse;
@@ -68,6 +69,36 @@ impl Root {
}
}
/// A method without arguments that expressions read most, resolved when the program compiles so
/// a host can answer it without comparing names ([`Host::field`]).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Field {
Age,
Life,
Custom,
X,
Y,
Z,
Temperature,
Downfall,
}
impl Field {
pub(crate) fn of(name: &str) -> Option<Self> {
Some(match name {
"age" => Self::Age,
"life" => Self::Life,
"custom" => Self::Custom,
"x" => Self::X,
"y" => Self::Y,
"z" => Self::Z,
"temperature" => Self::Temperature,
"downfall" => Self::Downfall,
_ => return None,
})
}
}
/// What the game answers while an expression runs.
pub trait Host {
fn root(&mut self, root: Root) -> Value;
@@ -76,6 +107,12 @@ pub trait Host {
fn method(&mut self, target: &Value, name: &str, args: &[Value]) -> Result<Value, String>;
/// A global function of the game's (`config`, `colormap`, `modOn`, `date*`).
fn function(&mut self, name: &str, args: &[Value]) -> Result<Value, String>;
/// `root.field()` answered without its name, or `None` to answer it through [`Self::method`]:
/// a host that answers must give what `method` would.
fn field(&mut self, root: Root, field: Field) -> Option<Value> {
let _ = (root, field);
None
}
}
type MathFn = fn(&[f64]) -> f64;
@@ -139,13 +176,16 @@ pub(crate) const MATH: &[(&str, usize, usize, MathFn)] = &[
pub struct Program {
body: Vec<Stmt>,
locals: usize,
/// The same program on the numeric fast path, when it is one (`fast.rs`).
fast: Option<fast::Fast>,
}
impl Program {
/// Parses `src`; a syntax error or an unknown name fails here.
pub fn compile(src: &str) -> Result<Self, String> {
let (body, locals) = parse::parse(src)?;
Ok(Self { body, locals })
let fast = fast::Fast::of(&body, locals);
Ok(Self { body, locals, fast })
}
/// Whether the program reads nothing of its context but the `root.name()` methods `allowed`
@@ -185,6 +225,15 @@ impl Program {
/// Runs the statements; the result is the last statement's value (an assignment's is the
/// value it stored).
pub fn eval(&self, host: &mut dyn Host) -> Result<Value, String> {
if let Some(fast) = &self.fast {
return fast.eval(host);
}
self.interpret(host)
}
/// Runs the statements through the interpreter (what [`Self::eval`] does for a program the
/// fast path doesn't cover).
fn interpret(&self, host: &mut dyn Host) -> Result<Value, String> {
let mut run = Run {
host,
locals: vec![Value::Null; self.locals],
+111
View File
@@ -231,3 +231,114 @@ fn reads_only_names_what_a_program_may_read() {
assert!(!ok("r.noise(o.y, 0)"));
assert!(!ok("config('pack:option')"));
}
/// A host whose methods answer every kind of value, and record the arguments they get.
struct Kinds {
age: f64,
seen: Vec<String>,
/// Answers `o.age` and `o.life` by field too, as the particles' host does.
fields: bool,
}
impl Host for Kinds {
fn root(&mut self, root: Root) -> Value {
match root {
Root::Object => Value::Object(1),
Root::Random => Value::Object(2),
_ => Value::Object(3),
}
}
fn method(&mut self, _: &Value, name: &str, args: &[Value]) -> Result<Value, String> {
self.seen.push(format!("{name}{args:?}"));
Ok(match name {
"age" => Value::Num(self.age),
"life" => Value::Num(140.0),
"custom" => Value::Num(if args.is_empty() { 0.3 } else { 2.0 }),
"inWater" => Value::Bool(self.age > 50.0),
"biome" => Value::Str("minecraft:plains".into()),
"empty" => Value::Str("".into()),
"me" => Value::Object(7),
"noise" => Value::Num(args.iter().map(Value::num).sum::<f64>().sin()),
"fail" => return Err("no such thing".into()),
_ => Value::Null,
})
}
fn function(&mut self, _: &str, _: &[Value]) -> Result<Value, String> {
Ok(Value::Null)
}
fn field(&mut self, root: Root, field: Field) -> Option<Value> {
if !self.fields || root != Root::Object {
return None;
}
match field {
Field::Age => Some(Value::Num(self.age)),
Field::Life => Some(Value::Num(140.0)),
_ => None,
}
}
}
#[test]
fn the_fast_path_answers_what_the_interpreter_does() {
let corpus = [
"(0.7 + 0.3*sin(o.age*0.18 + o.custom*13000)) * min(o.age/(o.life*0.15),1)",
"0.5+(r.noise(o.age/60,5+o.age/60)*0.55)",
"o.age > 40",
"o.age >= 40 && o.age < 90",
"!(o.age > 3)",
"o.age > 10 || o.fail",
"o.age > 70 ? 1 : 0.25",
"o.age > 70 ? o.age : o.life",
"o.age > 70 ? o.biome : o.life",
"o.inWater",
"o.inWater ? 2 : 3",
"!o.inWater",
"o.biome ? 1 : 0",
"o.empty ? 1 : 0",
"o.me ? 1 : 0",
"o.biome + 1",
"-o.inWater",
"o.custom('glow') + 1",
"o.custom(o.age > 3)",
"r.noise(o.inWater, 2)",
"o.fail + 1",
"o.age % 7 - 2 ^ 3",
"clamp(o.age, 10, 20) / 0",
"o.age == 3",
"2 == 2",
"1 != 2 ? o.age : 0",
"max(o.age, o.life) - min(o.age, 1)",
"o.age > 3 ? o.age > 5 : o.inWater",
];
for src in corpus {
let program = Program::compile(src).unwrap();
let cases = [0.0, 3.0, 45.0, 75.0, 139.0]
.into_iter()
.flat_map(|a| [(a, false), (a, true)]);
for (age, fields) in cases {
let mut fast_host = Kinds {
age,
seen: Vec::new(),
fields,
};
let mut slow_host = Kinds {
age,
seen: Vec::new(),
fields,
};
let fast = program.eval(&mut fast_host);
let slow = program.interpret(&mut slow_host);
let same = match (&fast, &slow) {
(Ok(Value::Num(a)), Ok(Value::Num(b))) => a.to_bits() == b.to_bits(),
(a, b) => a == b,
};
assert!(same, "{src} at {age}: fast {fast:?}, interpreter {slow:?}");
// A field the host answers skips its call; the interpreter makes it by name.
if !fields {
assert_eq!(fast_host.seen, slow_host.seen, "{src} at {age}: the calls");
}
}
}
// The fast path covers the particles' and colormaps' plain arithmetic.
assert!(Program::compile(corpus[0]).unwrap().fast.is_some());
assert!(Program::compile(corpus[1]).unwrap().fast.is_some());
}
+1 -1
View File
@@ -45,7 +45,7 @@ Every setting applies at once, except worker threads, the graphics API and trans
**Translucent batching** (Advanced, after Graphics API; on by default, `batchTranslucent` in `horizon-graphics.txt`, a new key so that the `translucentBatching:false` earlier builds saved for everyone doesn't keep it off; it applies at the next start or resource reload, and is no part of a preset) gives water, glass, ice and other translucent quads a vertex buffer of their own, with pages up to 2 GiB, and their sorted indices the same: the back-to-front list then stays in one page and goes out in a few draw calls instead of switching pages every few sections. The picture is the same and frames come faster, most over water and at high render distances (RTX 4090 at 1080p: 4 to 16% more FPS at render distance 32; over the ocean at 64, 354 draw calls a frame instead of 3,832 and 43% more FPS); it costs a little video memory, as solid and translucent quads no longer share free space (terrain meshes take 1 to 15% more at render distance 32, 5 to 10% more at 64). The large pages shrink once the view has settled (a second after terrain stops arriving): one much larger than what it holds, as after a teleport or a lower render distance, moves into a page of the right size, about 32 MiB a frame. It needs indirect multi-draw that isn't OpenGL's (which loops over the entries on the CPU), and devices whose vanilla frames draw flat (Metal, Intel Gen11 and Gen12 on Vulkan) don't offer it: there the switch is greyed out and reads Off, and macOS doesn't show it. A `shaders/` pack's terrain and shadow passes, and the `[shadow]` pass of one of Horizon's own packs, draw flat where the device can, reading translucent quads beside their section's solid ones: while such a pack runs they go back there. Such a pack picked at the start has the world laid out for it from the first; switching to or from one later meshes the world again.
**HDR** has its own page and three choices: **Off** (the default) keeps SDR; **On** uses HDR wherever the display path offers it; **Auto** uses HDR only while the system reports HDR active for the window's display and an HDR output is offered, otherwise SDR. On is unavailable where no HDR output is offered; Auto stays selectable before the system is queried, including on an SDR display. The controls below work only while HDR is active. The existing `hdr` key in `horizon-graphics.txt` saves On as `true`, Off as `false`, and Auto as `auto`; old boolean files keep their meaning, and older builds ignore `auto` and keep their Off default. It presents to an HDR10 swapchain (`Rgb10a2Unorm`, BT.2020 with the PQ curve) or, where only that is offered, an scRGB one (`Rgba16Float`, extended linear sRGB), on displays and compositors that offer either; `HORIZON_HDR_OUTPUT=pq` or `scrgb` allows only one, and offers it to an `--offscreen` run, which has no display to ask: there HDR is drawn and screenshotted (the `-hdr.png` below) but not presented, and automatic brightness takes 203 and 1000 nits, so HDR can be checked without an HDR display. The frame is drawn exactly as in SDR, in vanilla's gamma space (into a 16-bit target (`Rgba16Unorm`, which clips at white after every pass as the 8-bit one does) when HDR is on as the renderer is made, at the start or a resource reload, with **Smooth Gradients** on (the default, `hdrSmoothGradients`; off, the 8-bit frame) and where the device can draw into it, else an 8-bit one; HDR switched off after that keeps the 16-bit frame and copies it to the 8-bit swapchain, without frame generation, until the next start; with `HORIZON_HDR_FRAME=float` the frame follows HDR, Smooth Gradients and the picked pack unless it was refused, is missing or its owner mod is off (the renderer is made again on the same device before the next frame, and the world meshed again), and with no shader pack or a 0.2 one, where the device can keep the HUD on a layer of its own, a float one (`Rgba16Float`) takes the 16-bit one's place whatever Smooth Gradients is: the world's shaders write light past white into it themselves, and it holds no marks (below)), and a last pass (`hdr.wgsl`) decodes it to linear light at the **Paper White** and lifts light sources (blocks that emit light, lava, the sun and the moon) towards the **Peak Brightness**; everything else stays as in SDR. The mesher puts the light a block's face emits in its vertex colour's alpha (`EMISSION_BITS`), the frame's alpha carries the mark, and only pixels that still show the world before the hand and HUD are lifted. On Vulkan, `horizon-hdr` sends HDR metadata (MaxCLL and mastering luminance at the peak, MaxFALL as 0, unknown, since a frame's average isn't known ahead of it), which wgpu doesn't: without it a compositor may clip everything above SDR white. Paper White and Peak Brightness are **Auto** by default: they follow what the system reports for the display. Set by hand, on the slider and in calibration alike, Paper White runs from 10 to 480 nits by 10, and Peak Brightness from 200 to 2000 nits by 50, where most displays' peaks are, then by 500 up to PQ's 10 000, for displays that are brighter or tone-map the signal themselves; `hdrPeak` keeps any value from 200 to 10 000. On Wayland that's the compositor's preferred image description of the window (`wp_color_management_v1`, in `horizon-hdr`'s `wayland.rs`), watched while HDR is On or Auto (Off does not ask the system); the preferred target peak above reference white reports HDR headroom, so a move to another output or a recalibrated desktop applies at once. KWin maps the content's reference white (203 nits) onto the desktop's SDR white, so Auto puts Paper White at 203 and Peak Brightness at the display's peak over that ratio; Hyprland (0.57) doesn't: it reports the standard 203 as reference white, so Auto puts Paper White at 203, and it shows HDR windows below its own SDR white (`sdr_max_luminance`, which it doesn't report): in a test, a white browser page was brighter than both the game's white and a 1000-nit patch in mpv. Other compositors are unchecked. On Windows Auto takes what wgpu reads from the OS (`Surface::display_hdr_info`: DXGI's `MaxLuminance` and the SDR white level of Windows' SDR content brightness slider, both absolute nits), read again every 2 seconds since no event says they changed; the same reading's current output colour-space state drives Auto (an offered Direct3D 12 HDR10 swapchain alone does not). macOS reports potential EDR headroom, fixed for a display rather than following desktop brightness: Auto uses it above 1, or stays SDR if it is missing or invalid. macOS reports no absolute nits or separate HDR-mode flag. X11, OpenGL, other paths without a report and offscreen runs keep Auto in SDR. Windows' luminance readings often come from the display's EDID and may run optimistic, and this is untested so far. **Calibrate...** (`hdr_calibration.rs`) sets Black Level, Peak Line truncated
**HDR** has its own page and three choices: **Off** (the default) keeps SDR; **On** uses HDR wherever the display path offers it; **Auto** uses HDR only while the system reports HDR active for the window's display and an HDR output is offered, otherwise SDR. On is unavailable where no HDR output is offered; Auto stays selectable before the system is queried, including on an SDR display. The controls below work only while HDR is active. The existing `hdr` key in `horizon-graphics.txt` saves On as `true`, Off as `false`, and Auto as `auto`; old boolean files keep their meaning, and older builds ignore `auto` and keep their Off default. It presents to an HDR10 swapchain (`Rgb10a2Unorm`, BT.2020 with the PQ curve) or, where only that is offered, an scRGB one (`Rgba16Float`, extended linear sRGB), on displays and compositors that offer either; `HORIZON_HDR_OUTPUT=pq` or `scrgb` allows only one, and offers it to an `--offscreen` run, which has no display to ask: there HDR is drawn and screenshotted (the `-hdr.png` below) but not presented, and automatic brightness takes 203 and 1000 nits, so HDR can be checked without an HDR display. The frame is drawn exactly as in SDR, in vanilla's gamma space (into a 16-bit target (`Rgba16Unorm`, which clips at white after every pass as the 8-bit one does) when HDR is on as the renderer is made, at the start or a resource reload, with **Smooth Gradients** on (the default, `hdrSmoothGradients`; off, the 8-bit frame) and where the device can draw into it, else an 8-bit one; HDR switched off after that keeps the 16-bit frame and copies it to the 8-bit swapchain, without frame generation, until the next start; with `HORIZON_HDR_FRAME=float` the frame follows HDR, Smooth Gradients and the picked pack unless it was refused, is missing or its owner mod is off (the renderer is made again on the same device before the next frame, and the world meshed again), and with no shader pack or a 0.2 one, where the device can keep the HUD on a layer of its own, a float one (`Rgba16Float`) takes the 16-bit one's place whatever Smooth Gradients is: the world's shaders write light past white into it themselves, and it holds no marks (below)), and a last pass (`hdr.wgsl`) decodes it to linear light at the **Paper White** and lifts light sources (blocks that emit light, lava, the sun and the moon) towards the **Peak Brightness**; everything else stays as in SDR. The mesher puts the light a block's face emits in its vertex colour's alpha (`EMISSION_BITS`), the frame's alpha carries the mark, and only pixels that still show the world before the hand and HUD are lifted. On Vulkan, `horizon-hdr` sends HDR metadata (MaxCLL and mastering luminance at the peak, MaxFALL as 0, unknown, since a frame's average isn't known ahead of it), which wgpu doesn't: without it a compositor may clip everything above SDR white. Paper White and Peak Brightness are **Auto** by default: they follow what the system reports for the display. Set by hand, on the slider and in calibration alike, Paper White runs from 10 to 480 nits by 10, and Peak Brightness from 200 to 2000 nits by 50, where most displays' peaks are, then by 500 up to PQ's 10 000, for displays that are brighter or tone-map the signal themselves; `hdrPeak` keeps any value from 200 to 10 000. On Wayland that's the compositor's preferred image description of the window (`wp_color_management_v1`, in `horizon-hdr`'s `wayland.rs`), watched while HDR is On or Auto (Off does not ask the system); the preferred target peak above reference white reports HDR headroom, so a move to another output or a recalibrated desktop applies at once. KWin maps the content's reference white (203 nits) onto the desktop's SDR white, so Auto puts Paper White at 203 and Peak Brightness at the display's peak over that ratio; Hyprland (0.57) doesn't: it reports the standard 203 as reference white, so Auto puts Paper White at 203, and it shows HDR windows below its own SDR white (`sdr_max_luminance`, which it doesn't report): in a test, a white browser page was brighter than both the game's white and a 1000-nit patch in mpv. Other compositors are unchecked. On Windows Auto takes what wgpu reads from the OS (`Surface::display_hdr_info`: DXGI's `MaxLuminance` and the SDR white level of Windows' SDR content brightness slider, both absolute nits), read again every 2 seconds since no event says they changed; the same reading's current output colour-space state drives Auto (an offered Direct3D 12 HDR10 swapchain alone does not). macOS reports potential EDR headroom, fixed for a display rather than following desktop brightness: Auto uses it above 1, or stays SDR if it is missing or invalid. macOS reports no absolute nits or separate HDR-mode flag. X11, OpenGL, other paths without a report and offscreen runs keep Auto in SDR. Windows' SDR white is the player's own slider, but its peak is mostly the display's EDID figure, which often runs high: Auto still uses it, over the 1000-nit default, but the HDR Line truncated
With `HORIZON_HDR_FRAME=float`, HDR on and no shader pack or a 0.2 one, devices with independent blending draw the frame in layers ([hdr-linear-light.md](design/hdr-linear-light.md), The HUD and menus). The world's shaders write their own light into the frame instead of a mark (`hdr_written`, `hdr_light.wgsl`), a whole frame at a time, so glass, water, clouds and particles each lay their own light over the light behind them. Improved Transparency's layers write their own light too, before they are weighted and composited. No float frame holds marks: under a 0.2 pack Horizon's own draws keep their colour, alpha 1 where opaque and coverage where blended, HDR output lifts nothing, and the pack's `[tonemap]` takes the tone curve's place below (one or the other runs, never both); without the HUD layer (HDR off, or a device without independent blending) its float frame finishes on the swapchain's 8 bits before the camera overlays, which then draw with the HUD as in SDR, and HDR output stays off. The camera overlays (vignette, pumpkin, powder snow, portal, nausea), post effects and entity outlines draw on light. After the post effects and before the camera overlays, the tone curve eases that light into the peak (`Hdr::tonemap`) in place of HDR lighting's own easing and the light sources' cap at the peak: up to 60% of the peak light stays as it is, and above it ITU-R BT.2390's EETF in PQ rolls it off, on its brightest channel so it keeps its hue. The HUD and menus then draw on an 8-bit target of their own, the world clipped to white, as they found the frame before (each draw clips at white as there), and write how much of the world they hide into an R8 coverage target. The last pass lays the HUD over the world's light by that coverage, in gamma as the HUD blends: light behind see-through HUD shows as vanilla weights the HUD over it, and none shows through what covers it. The menu blur blurs that picture, light above white included, and the menu draws over the result. UI Brightness scales the HUD's own part, not the world under it. A screenshot maps the world's light into SDR, unchanged up to 0.6 of paper white in linear light and smoothly rolled towards white above it, with one scale for all RGB channels to keep their hue (where Horizon lifts nothing, with HDR Lighting off or under a 0.2 pack, the world is clipped at white as SDR draws it); the HUD's own part stays as drawn, whatever UI Brightness is, over the mapped world by its coverage. The world's icon uses the same mapping without the HUD; the `-hdr.png` beside a screenshot keeps the whole HDR picture. `HORIZON_HDR_DEBUG=coverage` tints the coverage magenta for inspection.
+1 -1
View File
@@ -20,7 +20,7 @@ plan are in [server.md](server.md).
takes the account's UUID when someone owns that name, as vanilla does, and that player is then refused.
- **An offline server** (`online_mode = false`) never checks accounts: anyone who reaches it can join under
any name. Keep it on your LAN or a tailnet (Tailscale, ZeroTier), or share it only with friends you trust.
A Horizon player under an offline name can join only such a server.
A Horizon game started without a session (no network at Play) can join only such a server.
- **Secure chat** works as on vanilla's server: in online mode, vanilla clients and Horizon's (Nightly
2026-11-01 and newer) sign their chat, and with `enforce-secure-profile=true` (the default) unsigned chat is
refused. On an offline server, or for a player without a chat session, chat stays unsigned and shows as not
+1 -36
View File
@@ -188,7 +188,7 @@ MCP: `account_sign_out`, needs `confirm: true`.
## `horizon-launcher account select`
Play as this account, or as one of your offline names.
Play as this account.
horizon-launcher account select <WHO>
@@ -196,41 +196,6 @@ Play as this account, or as one of your offline names.
MCP: `account_select`.
## `horizon-launcher account offline`
Play offline (LAN, offline-mode servers) beside a signed-in account that owns the game: as NAME (kept to switch back to; 3 to 16 letters, digits or _), or as the name the game made up.
horizon-launcher account offline [NAME]
- `NAME`
MCP: `account_offline`.
## `horizon-launcher account forget-offline`
Forget one of your offline names; its skin and cape go with it.
horizon-launcher account forget-offline <NAME>
- `NAME`
MCP: `account_forget_offline`.
## `horizon-launcher account skin`
Show or set an offline name's skin and cape: a 64x64 (or 64x32) skin PNG, a 64x32 cape PNG, the model. Kept by the launcher and given to the game when that name plays.
horizon-launcher account skin <NAME> [FILE]
- `NAME`
- `FILE`: The skin's PNG
- `--model`: classic or slim arms
- `--cape`: The cape's PNG
- `--no-skin`: Back to the default skin
- `--no-cape`: Take the cape off
MCP: `account_skin`.
## `horizon-launcher settings`
Show the launcher's settings, or set one (the Settings page): selected-version TAG, game-architecture auto|x64|arm64, minecraft-dir PATH, server-dir PATH ("default" resets a folder), install-new-versions on|off, prune-old-versions on|off (delete old versions after an install, keeping the selected one, the ones instances use and the newest few), keep-versions N (how many of the newest to keep; "default" is 2), opening-animation on|off, proxy http://host:port|socks5://host:port ("default" removes it), while-playing stay|minimize|hide (what the window does while the game runs), language system|en|fr|ru|de|zh|es|uk|pl (the window's language; system follows the computer's), accent violet|blue|teal|green|amber|red|pink|#rrggbb|DEGREES (a named accent, any colour, or any hue), background PATH (a picture behind Home; "default" shows Horizon's landscape), native-cache-gib N (combined native compilation cache limit in GiB, default 30; 0 disables automatic cleanup), native-profile performance|dev|release (the profile native mods build with: performance is incremental, dev rebuilds a mod quickest for a slow game, release is slowest to build and slightly faster to play).
+72
View File
@@ -423,6 +423,78 @@ pub trait Layer: Sync {
- Sprites, items and the player's state come with their platform API (M6). They are not in this first
version.
### Look (`horizon_platform::look`)
What the engine draws differently for a crate above, as plain data: PvP & HUD's knobs today (#14217).
```rust
pub struct Look { // #[non_exhaustive]; Default is vanilla's
pub legacy_pose: bool, pub hide_attack_indicator: bool,
pub mute_attack_sounds: bool, pub hide_attack_particles: bool,
pub frame: Frame, // outline, hurt overlay and glint colours
pub shield_size: u8, pub totem_scale: f32, pub fire_lower: f32,
pub clear_lava: bool, pub clear_water: bool, pub chat: Chat,
pub hide_effect_icons: bool, pub time_of_day: Option<i64>, pub weather: Option<(f32, f32)>,
}
pub fn update(change: impl FnOnce(&mut Look)); // the player whose turn it is (`seat()`)
```
- Pushed, not asked: a crate changes its own fields when its settings load or change (several crates share the
look, each keeping to its fields), and the engine reads it where it draws (`game/look.rs`, the only reader).
Nothing is called per frame, and a seat nothing changed sees vanilla's.
- A knob is named by what it changes in the picture or the sound, never by the feature that uses it. A new knob
is a field added with vanilla's value as its default.
### Container screens (`horizon_platform::containers`)
Input and drawing on an open container screen (the inventory, chests, furnaces, crafting tables...), for the
extras that act on one: Mouse Tweaks and sorting (M5).
```rust
/// The open screen's menu, for the length of one call. The engine implements it.
pub trait Container {
fn menu(&self) -> &str; // "inventory", "minecraft:generic_9x3", "minecraft:furnace"...
fn slots(&self) -> Vec<Slot>; // every slot drawn, in the screen's order
fn stack(&mut self, slot: SlotId) -> Option<Stack>;
fn carried(&self) -> Option<Stack>; // the stack on the cursor
fn takes_one(&mut self, slot: SlotId, of: &Stack) -> bool; // the menu's rules: mayPlace, the slot's limit
fn landing(&mut self, slot: SlotId) -> Vec<SlotId>; // where quickMoveStack would put its items
fn click(&mut self, slot: SlotId, click: Click) -> bool; // one ordinary click, as vanilla sends it
fn spread(&self) -> usize; // the slots vanilla's quick craft drag covers now
fn cursor(&self) -> (f32, f32); // GUI pixels, from the panel's corner
fn shift(&self) -> bool;
fn order(&mut self, slot: SlotId) -> (u32, String); // the creative tabs' order and the shown name
}
pub struct SlotId(pub u32); // opaque, stable while the screen is open
pub struct Slot { pub id: SlotId, pub role: Role, pub x: f32, pub y: f32 } // top left, from the panel's corner
pub enum Role { Hotbar, Inventory, Storage, Input, Result, Equipment, Other } // a crafting grid is Input
pub struct Stack { pub item: String, pub count: u32, pub max: u32, pub kind: u64 } // kind: equal for the same item and components
pub enum Click { Pick { right: bool }, QuickMove, Put { one: bool } } // Put: a one-slot QUICK_CRAFT drag
// In `Hooks`, each `false` (or nothing) by default, so vanilla's handling runs:
fn container_press(&self, c: &mut dyn Container, slot: Option<SlotId>, right: bool) -> bool;
fn container_drag(&self, c: &mut dyn Container, slot: Option<SlotId>) -> bool; // the cursor moved, a button held
fn container_release(&self, c: &mut dyn Container);
fn container_wheel(&self, c: &mut dyn Container, slot: Option<SlotId>, steps: f32) -> bool;
fn container_key(&self, c: &mut dyn Container, slot: Option<SlotId>, key: &str) -> bool; // `key.keyboard.r`, `key.mouse.middle`
fn container_draw(&self, c: &dyn Container, canvas: &mut dyn hud::Canvas); // over the panel, from its corner
```
- `true` means the hook took the input: vanilla's press, drag or wheel doesn't run, and a press or drag taken
ends vanilla's quick craft drag, as Mouse Tweaks' right-drag replaces it. Every hook hears `release`. The
first hook that returns `true` wins.
- Each `click` is an ordinary slot click: the menu engine's on the player's own world, a `ContainerClick` on a
server. So an extra built on it works wherever vanilla's clicks do, and anticheats see vanilla's packets.
- The engine offers every menu screen's slots; the crate decides which menus it acts in, by `menu()` (Mouse
Tweaks stays out of those whose slots cost or trigger something: anvils, enchanting, merchants, beacons,
crafters). Creative's tabs are no container screen.
- The reads that ask the menu's rules take `&mut self`, as the engine's do; drawing gets `&dyn Container`,
so it reads the rest only.
- The engine builds a `Container` only when a hook is registered and a container screen gets input or draws.
Without one there is no cost, and vanilla's handling is unchanged.
- `order` is the only text: Sorting ranks by it. The rest is ids and numbers, so the API names no engine type
(`ItemStack` stays in the engine).
## Extras that may leave the game
Horizon's extras are Horizon-layer code. Each one is a candidate to become an optional native mod that players add
+14 -8
View File
@@ -2,9 +2,9 @@
Horizon signs players in with their Microsoft account in the launcher and joins online-mode
(authenticated) servers like vanilla 26.3 does. The launcher plays only with an account that owns
Minecraft: Java Edition ([the owner gate](#the-owner-gate)); offline names, LAN and offline-mode
servers play behind it. This note is the design, the status of each part and what Ludovic has to
register.
Minecraft: Java Edition ([the owner gate](#the-owner-gate)), as that account, on LAN and
offline-mode servers too. There are no offline names. This note is the design, the status of each
part and what Ludovic has to register.
## What Ludovic registers (needs his accounts)
@@ -87,7 +87,7 @@ possible; the launcher just doesn't offer it on its own.
says "Sign in with a Microsoft account that owns Minecraft: Java Edition to play", with Sign in.
- **The window says it once.** A player without an owner (one who played offline until now) sees
the gate's screen once when the launcher opens: why Horizon needs the account ("like other
launchers"), that worlds, offline names and settings stay where they are, and Sign in, which shows
launchers"), and Sign in, which shows
the device code on the same screen. It comes back whenever Play is refused; Not now closes it,
and Home keeps a Sign in row (`launcher/src/owner_page.rs`).
- **The answer lives with the tokens.** Each account's keychain item keeps the last answer
@@ -96,8 +96,13 @@ possible; the launcher just doesn't offer it on its own.
`secret-tool` or Keychain Access. With no network (or a sign-in that can't be renewed) the
last answer stands: being offline never blocks a player who passed before, and the game starts
without a session, offline. An answer of "doesn't own" (or no profile) blocks at once.
- **Offline names play behind an owner.** They can be added and played only while an owning
account is signed in. Signing the last one out keeps them, and they play again once one is back.
- **The account that plays owns the game.** The game plays as the selected account (else the
first), which must own the game itself: another account's ownership doesn't let it play
(`account::launch_for_game`). The project decided on 2026-11-09 that Horizon plays only with a
Microsoft account that owns Minecraft: Java Edition: the offline names, their skins and capes,
and 0.2.58's hidden developer option are gone. Files from older launchers still load; the next
save drops them (`offline`, `offline_selected`, `looks` and `skins/` in accounts.json's folder,
`dev_offline` in settings.json).
- **Who isn't affected:** the game binary itself (`horizon-client`, `horizon-ctl launch`, the
harnesses, CI), the dedicated server and `horizon-server`, the website. There is no bypass flag:
the launcher's tests use accounts in a memory store (`MemoryStore`, and `HORIZON_NO_KEYCHAIN`
@@ -230,7 +235,7 @@ Progress is public metadata and does not expose credentials through the UI or MC
name the expected player. Signing in to a different account is rejected before storing its
credentials or adding/selecting that identity. Retry keeps the same target; Cancel leaves the
saved account alone. Successful re-sign-in restores that account without changing the player
or offline name currently selected for Play. Adding a new account remains a separate action.
currently selected for Play. Adding a new account remains a separate action.
## Handing the session to the game
@@ -287,7 +292,8 @@ Code: `horizon-protocol` (`rsa.rs`, `crypto::server_hash`), `horizon-client` (`a
Horizon's dedicated server verifies players when `online-mode=true`. A LAN or Play with Friends world
verifies its guests when the host is signed in, as vanilla's `IntegratedServer` does
(`OnlineMode::lan`); under an offline name it stays offline-mode. The host's own player joins through
(`OnlineMode::lan`); started without a session (the services couldn't be reached at Play) it
stays offline-mode. The host's own player joins through
memory and is never asked to authenticate.
`HORIZON_API_DISCOVERY` overrides the discovery URL, the counterpart of authlib's
+2 -2
View File
@@ -115,8 +115,8 @@ run at once there, and each must finish within 10 seconds however slowly its byt
Like LAN, and like vanilla's `IntegratedServer`: a host signed in with a Microsoft account runs the world
in online mode, so each guest signs in through Mojang's session servers and arrives with their own
UUID, skin and cape. A host playing under an offline name runs it in offline mode, where a guest joins
with the name their game uses. Either way the host's own profile is reserved. Every tunnelled guest
UUID, skin and cape. A host playing without a session (the services couldn't be reached at Play) runs it in
offline mode, where a guest joins with the name their game uses. Either way the host's own profile is reserved. Every tunnelled guest
reaches the integrated server from `127.0.0.1`.
## Relays (optional)
+7 -19
View File
@@ -160,15 +160,11 @@ The opening, then Play ([clip](docs/opening.webm)):
(`horizon_launcher::shortcut`). **Remove shortcut** moves it to the trash; it is found by the
instance id inside it, so a rename doesn't lose it. `horizon-launcher instance shortcut
[instance] [--remove]`; `HORIZON_LAUNCHER_DESKTOP` points it at another folder.
- **Accounts and quick switch**: the top bar's account chip opens a menu of everyone who can play:
each signed-in Microsoft account, the offline names the player keeps, and the name the game
made up (`horizon-player.txt`). Picking one plays as it from the next Play. Offline names play
only while an account that owns the game is signed in ([Microsoft accounts](#microsoft-accounts));
signing the last one out keeps them, unplayable until one is back. Settings > Account
adds offline names (3 to 16 letters, digits or `_`; the game gets `--name`) and forgets them,
skin and cape files included, and rolls the game's made-up name for a new one; the Console's
Share log takes the names out of the log too. `horizon-launcher account offline
[NAME]`, `account select <name>` (an account or an offline name), `account forget-offline
- **Accounts and quick switch**: the top bar's account chip opens a menu of the signed-in
Microsoft accounts. Picking one plays as it from the next Play; that account must own the game
([Microsoft accounts](#microsoft-accounts)). There are no offline names: the project decided
that Horizon plays only with a Microsoft account that owns Minecraft: Java Edition. The
Console's Share log takes the account names out of the log. `horizon-launcher account select
<name>`.
- **Accent and Home background**: on top of Dark, Light or System, Settings > Launcher picks an
accent (Horizon's violet, blue, teal, green, amber, red or pink, any hue, or any colour typed as
@@ -185,13 +181,6 @@ The opening, then Play ([clip](docs/opening.webm)):
`launcher/lang/<code>.json`, English text to its translation, Horizon's own; a test fails when
the code asks `tr("…")` for a string a table lacks, or a table keeps one the code dropped.
`horizon-launcher settings language system|en|fr|ru|de|zh|es|uk|pl`.
- **Skin and cape**: each offline name's **Skin…** in Settings > Account shows the front of its
skin and cape, takes a skin PNG (64×64, or the older 64×32) and a cape PNG (64×32), and picks
classic or slim arms. The launcher keeps copies in its `skins/` folder and gives the game
`HORIZON_OFFLINE_SKIN`, `HORIZON_OFFLINE_SKIN_MODEL` and `HORIZON_OFFLINE_CAPE` when that name
plays; the game draws the default skins until it reads them. A Microsoft account's skin and
cape: coming soon, with sign-in. `horizon-launcher account skin <name> [FILE] [--model
classic|slim] [--cape FILE] [--no-skin] [--no-cape]`.
- **Console**: Home's Console shows the game's output of this run as it comes: a search (every
word, any case), Follow to keep the newest line in view, Copy, and Open logs folder. Warnings
and errors stand out. **Share log…** uploads the log to [mclo.gs](https://mclo.gs), a paste
@@ -399,7 +388,6 @@ and don't set `%ERRORLEVEL%` / `$LASTEXITCODE`. Scripts that need the exit code
horizon-launcher account sign-in sign in in your browser with a code
horizon-launcher account sign-out <name>
horizon-launcher account select <name> play as this account
horizon-launcher account offline play without an account
horizon-launcher instance [list] the instances and their game folders (* = Play starts it)
horizon-launcher instance create <name> [--copy <instance>] empty, or a copy of one's worlds, options and packs
horizon-launcher instance create <name> --minecraft <1.21.4|latest|latest-snapshot> a Minecraft: Java Edition instance
@@ -492,8 +480,8 @@ MCP's `play`) says "Sign in with a Microsoft account that owns Minecraft: Java E
and starts nothing. Settings → Accounts signs in: the launcher shows a code, you enter it at
microsoft.com/link, and the launcher checks that the account owns the game. It asks again at every
Play, with the token renewal; with no network the last answer stands, and a "doesn't own" blocks
at once. The account also plays online-mode servers under your own name and skin; offline names
play LAN and offline-mode servers beside it. The game binary started directly (`horizon-client`,
at once. The account that plays must own the game itself, and it plays online-mode servers under
your own name and skin, LAN and offline-mode servers too. The game binary started directly (`horizon-client`,
`horizon-ctl launch`), the harnesses and the servers don't go through this check. Tokens live in the system keychain (Keychain,
Credential Manager, or the Secret Service on Linux), never in a log or the command line;
`accounts.json` in the data folder keeps only names and UUIDs. On Linux without a keychain they go
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Bou van {name} se na-bou-stap",
"In use": "In gebruik",
"Prepare": "Berei voor",
"Developer options": "Ontwikkelaar opsies",
"{online} of {max} players": "{online} van {max} spelers",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java-uitgawe). Play laai dit die eerste keer van Mojang af vir jou rekening, met die Java wat dit nodig het.",
"Close": "Maak toe",
@@ -98,7 +97,6 @@
"From my install": "Van my installasie",
"the update failed: {error}": "die opdatering het misluk: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesa se DRI_PRIME=1, so Vulkan kies die ander kaart.",
"New name": "Nuwe naam",
"Dark": "Donker",
"Not now": "Nie nou nie",
"Use an access token…": "Gebruik 'n toegangtoken...",
@@ -115,7 +113,6 @@
"Partly": "Gedeeltelik",
"All": "Almal",
"Instance": "Instansie",
"Classic arms": "Klassieke arms",
"Versions": "Weergawes",
"Release build: slower to build, slightly faster game": "Vrystelling bou: stadiger om te bou, effens vinniger spel",
"Performance build": "Prestasiebou",
@@ -172,7 +169,6 @@
"about a minute left": "omtrent 'n minuut oor",
"Cancel": "Kanselleer",
"Add to {client}": "Voeg by {client}",
"Skin…": "Vel…",
"Environment": "Omgewing",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Hulle werk dikwels nog saam. As die bou misluk, installeer weergawes wat vir dieselfde Nightly gemaak is.",
"Import an instance folder…": "Voer 'n instansievouer in …",
@@ -184,7 +180,6 @@
"newest stable version": "nuutste stabiele weergawe",
"Choose image…": "Kies prent …",
"No worlds yet: they appear here once you play one.": "Nog geen wêrelde nie: hulle verskyn hier sodra jy een speel.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Vanlyn name speel sonder 'n Microsoft-rekening wat die speletjie besit. Minecraft kom steeds van jou eie installasie af.",
"crash reports beside it": "ineenstortingsverslae langsaan",
"Install all": "Installeer alles",
"No group": "Geen groep nie",
@@ -202,7 +197,6 @@
"My instance": "My voorbeeld",
"Snapshot": "Momentopname",
"Gallery": "Galery",
"Offline name": "Vanlyn naam",
"Home": "Tuis",
"Stopping": "Besig om te stop",
"MSPT · tick time": "MSPT · tiktyd",
@@ -304,8 +298,6 @@
"Patch notes": "Patch notas",
"Your Minecraft server, {online}.": "Jou Minecraft-bediener, {online}.",
"Crash reports": "Ineenstortingsverslae",
"Offline name · the game's own · plays": "Vanlyn naam · die speletjie se eie · speel",
"Slim arms": "Skraal arms",
"Asking GitHub about {owner}/{repo}…": "Vra GitHub oor {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Laai tans Minecraft {version} af vanaf Mojang · {done} van {total} lêers",
"Could not save your choice: {error}": "Kon nie jou keuse stoor nie: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizon se landskap. Kies 'n eie PNG-, JPEG- of WebP-prent.",
"Not needed": "Nie nodig nie",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Hierdie bou van die lanseerder het geen Microsoft-aanmelding nie (HORIZON_MSA_CLIENT_ID), so dit kan nie die speletjie begin nie.",
"Offline name · plays": "Vanlyn naam · speel",
"Run the game through": "Begin die speletjie deur",
"needed by another pack": "benodig deur 'n ander pakkie",
"Older →": "Ouer →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Kon nie {program}: {error} laat loop nie",
"Restart": "Herbegin",
"Copied to the clipboard.": "Gekopieer na die knipbord.",
"Your worlds, offline names and settings stay where they are.": "Jou wêrelde, vanlyn name en instellings bly waar hulle is.",
"Send nothing": "Stuur niks",
"Move to Trash": "Skuif na asblik",
"Start from": "Begin vanaf",
"Asking Mojang for its versions…": "Vra Mojang vir sy weergawes ...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "'n 64×64 (of 64×32) vel PNG en 'n 64×32 cape PNG, gehou deur die lanseerder en aan die speletjie gegee wanneer hierdie naam speel. Die speletjie teken die verstekvelle vir nou; dit gebruik dit sodra dit kan. 'n Microsoft-rekening se vel en mantel: binnekort.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Speel vanlyn onder 'n ander naam, en skakel van die boonste balk af. Aanlyn bedieners neem nie vanlyn name nie.",
"Report on Discord": "Verslag oor Discord",
"Export": "Uitvoer",
"Server": "Bediener",
@@ -384,7 +372,6 @@
"No version installed yet.": "Nog geen weergawe geïnstalleer nie.",
"Release": "Vrystelling",
"Verified": "Geverifieer",
"Choose a skin…": "Kies 'n vel...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} speel nog nie sy oorspronklike mods nie: bou die speletjie daarmee.",
"Use jars from my instance…": "Gebruik potte uit my instansie...",
"Applications menu": "Toepassings-kieslys",
@@ -408,7 +395,6 @@
"Open backups": "Maak rugsteun oop",
"The game is running: change packs in its own menus, or here once it is closed.": "Die speletjie is aan die gang: verander pakke in sy eie spyskaarte, of hier sodra dit gesluit is.",
"Check now": "Kyk nou",
"Choose a cape…": "Kies 'n kaap...",
"Save": "Stoor",
"Folder": "Vouer",
"Searching…": "Soek tans …",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Meld af",
"When it starts": "Wanneer dit begin",
"{name}'s skin": "{name} se vel",
"Start": "Begin",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Geen Minecraft-installasie nodig nie: Horizon laai dit van Mojang af vir jou rekening.",
"Logs": "Logs",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Die woordmerk, terwyl die vrystellinglys laai.",
"Playing offline": "Speel tans vanlyn",
"Sign in to Tailscale": "Meld aan by Tailscale",
"Offline names without an account": "Vanlyn name sonder 'n rekening",
"Help make Horizon faster and steadier?": "Help om Horizon vinniger en bestendiger te maak?",
"Sign in to play": "Meld aan om te speel",
"Ported": "Geplaas",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Dateer hierdie lanseerder op met jou pakketbestuurder.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Maak hierdie lanseerder toe, skuif dit na {folder} en maak dit daar oop om opdaterings te aktiveer.",
"Any MCP client": "Enige MCP-kliënt",
"{name}'s cape is kept.": "{name} se kaap word gehou.",
"Not reviewed by the Horizon registry": "Nie hersien deur die Horizon-register nie",
"Proxy": "Volmag",
"Checking": "Kontroleer",
"Updates": "Opdaterings",
"Asking Microsoft…": "Vra Microsoft …",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Voorbereid vir Minecraft {version}, sonder sy klanke: die speletjie sal stil wees. Berei weer voor om dit vanaf jou Minecraft-installasie te kopieer.",
"Forget": "Vergeet",
"Import a modpack…": "Voer 'n modpack in...",
"Search versions": "Soek weergawes",
"failed": "misluk",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Opgehou: {line}.",
"Resource packs": "Hulpbronpakke",
"yesterday": "gister",
"No cape": "Geen mantel nie",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Na elke sessie: raam-tyd persentiele en 'n 14-emmer histogram, regmerkie tye, piek geheue en opstart tye, met jou masjien (OS, SVE en sy kerns en horlosies, geheue grootte, GPU, sy geheue en drywer, tipe skyf, skerm grootte en herlaaitempo, skootrekenaar of rekenaar, op battery of nie) en die instellings wat werkverrigting verander.",
"Make a token": "Maak 'n teken",
"Added {names}: the game turns it on when the world opens.": "Bygevoeg {names}: die speletjie skakel dit aan wanneer die wêreld oopgaan.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Gedeel: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Vriende op dieselfde Wi-Fi: Multiplayer, Voeg bediener by, plak dan hierdie adres.",
"None yet: drop a .hshader or a shader pack .zip here.": "Nog geen: gooi 'n .hshader- of 'n shader-pak .zip hier.",
"Offline name · the game's own": "Vanlyn naam · die speletjie se eie",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Inheemse mods is nie sandboxed nie: hulle loop met volle toegang tot jou rekenaar, soos enige program. Installeer slegs mods wie se skrywers jy vertrou. Om met een te speel, bou die speletjie op die Mods-bladsy; die eerste bou laai Rust af en neem 20 tot 30 minute.",
"Your selected version only changes if you were playing the newest one.": "Jou gekose weergawe verander net as jy die nuutste een gespeel het.",
"Multiplayer": "Multispeler",
@@ -587,7 +567,6 @@
"the port": "die hawe",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Die bron van {source}. Die vrystelling daarvan stuur {file}, 'n inhoudmodi: installering van dié vanaf GitHub word nog nie ondersteun nie.",
"Build anyway": "Bou in elk geval",
"A name, 3 to 16 letters": "'n Naam, 3 tot 16 letters",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Geïnstalleer {mods} vanaf GitHub ({source}). Bou dit op die Mods-bladsy.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Instellings, Sleutels, Genereer toegangtoken. Dit word in hierdie rekenaar se sleutelhouer gehou en net na Tailscale gestuur.",
"{id} is up to date.": "{id} is op datum.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Ek lees dit en vertrou dit: installeer",
"Close export": "Maak uitvoer toe",
"Playing needs a prepared Horizon version (Play page).": "Speel benodig 'n voorbereide Horizon-weergawe (Speelbladsy).",
"Offline, the game's name": "Vanlyn, die speletjie se naam",
"From Horizon's registry": "Van Horizon se register",
"Sounds": "Klanke",
"Edit…": "Wysig …",
@@ -635,12 +613,10 @@
"up to date": "op datum",
"← Newer": "← Nuwer",
"Downloading from Mojang · {done} of {total} files": "Laai tans af vanaf Mojang · {done} van {total} lêers",
"{name}'s skin is kept.": "{name} se vel word behou.",
"Edit instance": "Wysig instansie",
"Remove shortcut": "Verwyder kortpad",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} is nie hier geïnstalleer nie (of nie op die PATH): kopieer eerder die konfigurasie.",
"No worlds to put in.": "Geen wêrelde om in te plaas nie.",
"Default skin": "Standaard vel",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "'n Skakel na 'n bewaarplek (die jongste vrystelling daarvan), 'n vrystelling, 'n tak of merker, of 'n commit. Die lanseerder installeer een presiese vrystellinglêer of commit, nooit 'n tak wat beweeg nie.",
"Sign in with GitHub to rate": "Meld aan met GitHub om te gradeer",
"Star on GitHub": "Gee 'n ster op GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "gespeel deur {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft-rekening · ook aanlyn bedieners",
"Offline · single player and LAN worlds": "Vanlyn · enkelspeler- en LAN-wêrelde",
"Offline names": "Vanlyn name",
"Add a name": "Voeg 'n naam by",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 tot 16 letters, syfers of onderstrepe. Verander ook name vanaf die boonste balk. Aanlyn bedieners neem nie vanlyn name nie.",
"Play online with your Microsoft account": "Speel aanlyn met jou Microsoft-rekening",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Meld aan met die rekening wat Minecraft: Java Edition besit. Jou naam en vel kom saam na aanlyn bedieners, soos in ander lanseerders.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsoft se eie bladsy maak in jou blaaier oop. Horizon sien nooit jou wagwoord nie.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "خطوة ما بعد البناء لـ {name}",
"In use": "قيد الاستخدام",
"Prepare": "تحضير",
"Developer options": "خيارات المطور",
"{online} of {max} players": "{online} من {max} لاعبين",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "ماين كرافت {version} (إصدار جافا). يقوم الزر \"تشغيل\" بتنزيلها من موجانج لحسابك في المرة الأولى، مع إصدار جافا الذي تحتاجه.",
"Close": "إغلاق",
@@ -98,7 +97,6 @@
"From my install": "من تثبيتي الخاص",
"the update failed: {error}": "فشل التحديث: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "خاصية DRI_PRIME=1 في Mesa، لكي يختار Vulkan البطاقة الأخرى.",
"New name": "اسم جديد",
"Dark": "داكن",
"Not now": "ليس الآن",
"Use an access token…": "استخدام رمز وصول…",
@@ -115,7 +113,6 @@
"Partly": "جزئيًا",
"All": "الكل",
"Instance": "نسخة (Instance)",
"Classic arms": "أذرع كلاسيكية",
"Versions": "الإصدارات",
"Release build: slower to build, slightly faster game": "إصدار رسمي: أبطأ في البناء، وأسرع قليلاً في اللعبة",
"Performance build": "إصدار الأداء",
@@ -172,7 +169,6 @@
"about a minute left": "متبقي حوالي دقيقة",
"Cancel": "إلغاء",
"Add to {client}": "إضافة إلى {client}",
"Skin…": "المظهر (Skin)…",
"Environment": "البيئة",
"They often still work together. If the build fails, install versions made for the same Nightly.": "غالبًا ما تستمر في العمل معًا. إذا فشل البناء، قم بتثبيت الإصدارات المصنوعة لنفس نسخة Nightly.",
"Import an instance folder…": "استيراد مجلد نسخة…",
@@ -184,7 +180,6 @@
"newest stable version": "أحدث إصدار مستقر",
"Choose image…": "اختر صورة…",
"No worlds yet: they appear here once you play one.": "لا توجد عوالم حتى الآن: ستظهر هنا بمجرد لعب أحدها.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "تتيح الأسماء غير المتصلة اللعب بدون حساب مايكروسوفت يمتلك اللعبة. لا تزال ماين كرافت تأتي من تثبيتك الخاص.",
"crash reports beside it": "تقارير الأعطال بجانبها",
"Install all": "تثبيت الكل",
"No group": "بدون مجموعة",
@@ -202,7 +197,6 @@
"My instance": "نسختي",
"Snapshot": "نسخة تجريبية",
"Gallery": "المعرض",
"Offline name": "اسم غير متصل",
"Home": "الرئيسية",
"Stopping": "جاري الإيقاف",
"MSPT · tick time": "MSPT · وقت التكتكة",
@@ -305,8 +299,6 @@
"Patch notes": "ملاحظات الإصدار",
"Your Minecraft server, {online}.": "خادم ماين كرافت الخاص بك، {online}.",
"Crash reports": "تقارير الأعطال",
"Offline name · the game's own · plays": "اسم غير متصل · الخاص باللعبة · يلعب",
"Slim arms": "أذرع نحيفة",
"Asking GitHub about {owner}/{repo}…": "جاري الاستعلام من جيت هاب عن {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "جاري تنزيل ماين كرافت {version} من موجانج · {done} من {total} ملفات",
"Could not save your choice: {error}": "تعذر حفظ اختيارك: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "خلفية هورايزون الأفقية. اختر صورة بصيغة PNG أو JPEG أو WebP خاصة بك.",
"Not needed": "غير مطلوب",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "هذا الإصدار من المشغل لا يحتوي على ميزة تسجيل دخول مايكروسوفت (HORIZON_MSA_CLIENT_ID)، لذا لا يمكنه بدء اللعبة.",
"Offline name · plays": "اسم غير متصل · يلعب",
"Run the game through": "تشغيل اللعبة عبر",
"needed by another pack": "مطلوب بواسطة حزمة أخرى",
"Older →": "الأقدم ←",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "تعذر تشغيل {program}: {error}",
"Restart": "إعادة التشغيل",
"Copied to the clipboard.": "تم النسخ إلى الحافظة.",
"Your worlds, offline names and settings stay where they are.": "عوالمك وأسماؤك غير المتصلة وإعداداتك تبقى كما هي.",
"Send nothing": "لا تقم بإرسال أي شيء",
"Move to Trash": "نقل إلى سلة المهملات",
"Start from": "البدء من",
"Asking Mojang for its versions…": "جاري طلب الإصدارات من موجانج…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "صورة مظهر (Skin) بصيغة PNG بدقة 64×64 (أو 64×32) وصورة رداء (Cape) بدقة 64×32، يتم الاحتفاظ بهما بواسطة المشغل وتمريرهما للعبة عند اللعب بهذا الاسم. ترسم اللعبة المظاهر الافتراضية في الوقت الحالي؛ وستستخدم هذه المظاهر فور إمكانية ذلك. مظهر ورداء حساب مايكروسوفت: قريباً.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "العب بلا اتصال تحت اسم آخر، وقم بالتبديل من الشريط العلوي. لا تقبل خوادم الإنترنت الأسماء غير المتصلة.",
"Report on Discord": "الإبلاغ على ديسكورد",
"Export": "تصدير",
"Server": "خادم",
@@ -385,7 +373,6 @@
"No version installed yet.": "لم يتم تثبيت أي إصدار بعد.",
"Release": "إصدار رسمي",
"Verified": "مُتحقق منه",
"Choose a skin…": "اختر مظهراً (Skin)…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} لا يشغل تعديلاته الأصلية بعد: قم ببناء اللعبة معها.",
"Use jars from my instance…": "استخدام ملفات Jars من نسختي…",
"Applications menu": "قائمة التطبيقات",
@@ -409,7 +396,6 @@
"Open backups": "فتح النسخ الاحتياطية",
"The game is running: change packs in its own menus, or here once it is closed.": "اللعبة قيد التشغيل: قم بتغيير الحزم من قوائمها الداخلية، أو هنا بمجرد إغلاقها.",
"Check now": "تحقق الآن",
"Choose a cape…": "اختر رداءً (Cape)…",
"Save": "حفظ",
"Folder": "المجلد",
"Searching…": "جاري البحث…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "تسجيل الخروج",
"When it starts": "عند البدء",
"{name}'s skin": "مظهر {name}",
"Start": "بدء",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "لا حاجة لتثبيت ماين كرافت: يقوم هورايزون بتنزيلها من موجانج لحسابك.",
"Logs": "السجلات",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "شعار الاسم أثناء تحميل قائمة الإصدارات.",
"Playing offline": "اللعب بدون اتصال",
"Sign in to Tailscale": "تسجيل الدخول إلى Tailscale",
"Offline names without an account": "أسماء غير متصلة بدون حساب",
"Help make Horizon faster and steadier?": "هل تريد المساعدة في جعل هورايزون أسرع وأكثر استقرارًا؟",
"Sign in to play": "تسجيل الدخول للعب",
"Ported": "منقولة",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "حدّث هذا المشغّل باستخدام مدير الحزم.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "أغلق هذا المشغّل، وانقله إلى {folder}، ثم افتحه من هناك لتمكين التحديثات.",
"Any MCP client": "أي عميل MCP",
"{name}'s cape is kept.": "تم الاحتفاظ برداء {name}.",
"Not reviewed by the Horizon registry": "لم يتم مراجعته من قِبل سجل هورايزون",
"Proxy": "الوكيل (Proxy)",
"Checking": "جاري التحقق",
"Updates": "التحديثات",
"Asking Microsoft…": "جاري السؤال مايكروسوفت…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "تم التجهيز لماين كرافت {version} بدون أصوات: ستكون اللعبة صامتة. قم بالتجهيز مرة أخرى لنسخها من تثبيت ماين كرافت الخاص بك.",
"Forget": "نسيان",
"Import a modpack…": "استيراد حزمة تعديلات…",
"Search versions": "البحث في الإصدارات",
"failed": "فشل",
@@ -506,7 +488,6 @@
"Left off: {line}.": "التوقف عند السطر: {line}.",
"Resource packs": "حزم الموارد",
"yesterday": "أمس",
"No cape": "بدون رداء",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "بعد كل جلسة: النسب المئوية لأوقات الإطارات ومخطط بياني بـ 14 فئة، وأوقات التكتكة، وذروة الذاكرة وأوقات البدء، مع مواصفات جهازك (نظام التشغيل، المعالج وأنويته وسرعاته، حجم الذاكرة، بطاقة الرسوميات وذاكرتها وتعريفها، نوع القرص، حجم الشاشة ومعدل التحديث، ما إذا كان لابتوب أو جهاز مكتبياً، ويعمل على البطارية أم لا) والإعدادات التي تغير الأداء.",
"Make a token": "إنشاء رمز وصول (Token)",
"Added {names}: the game turns it on when the world opens.": "تمت إضافة {names}: تفعل اللعبة ذلك تلقائيًا عند فتح العالم.",
@@ -559,7 +540,6 @@
"Shared: {url}": "تمت المشاركة: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "الأصدقاء على نفس شبكة الواي فاي: اللعب الجماعي > إضافة خادم، ثم الصق هذا العنوان.",
"None yet: drop a .hshader or a shader pack .zip here.": "لا شيء بعد: اسحب ملف .hshader أو حزمة تظليل بصيغة .zip وأفلتها هنا.",
"Offline name · the game's own": "اسم غير متصل · الخاص باللعبة",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "التعديلات الأصلية ليست معزولة في بيئة آمنة (Sandboxed): فهي تعمل بصلاحيات كاملة على جهازك، مثل أي برنامج. ثبت فقط التعديلات التي تثق بمؤلفيها. للعب بها، قم ببناء اللعبة من صفحة التعديلات؛ يتطلب البناء الأول تنزيل لغة Rust ويستغرق من 20 إلى 30 دقيقة.",
"Your selected version only changes if you were playing the newest one.": "يتغير إصدارك المحدد فقط إذا كنت تلعب بالأحدث.",
"Multiplayer": "اللعب الجماعي",
@@ -589,7 +569,6 @@
"the port": "المنفذ",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "مصدر {source}. يحتوي إصداره على {file}، وهو تعديل محتوى: تثبيت هذه التعديلات من جيت هاب غير مدعوم بعد.",
"Build anyway": "البناء على أي حال",
"A name, 3 to 16 letters": "اسم، من 3 إلى 16 حرفًا",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "تم تثبيت {mods} من جيت هاب ({source}). قم ببنائه في صفحة التعديلات.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "الإعدادات (Settings) > المفاتيح (Keys) > إنشاء رمز وصول (Generate access token). يتم الاحتفاظ به في سلسلة مفاتيح هذا الكمبيوتر وإرساله إلى Tailscale فقط.",
"{id} is up to date.": "{id} محدث لأحدث نسخة.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "لقد قرأته وأثق به: تثبيت",
"Close export": "إغلاق التصدير",
"Playing needs a prepared Horizon version (Play page).": "يتطلب اللعب وجود إصدار مجهز من هورايزون (صفحة اللعب).",
"Offline, the game's name": "غير متصل، اسم اللعبة",
"From Horizon's registry": "من سجل هورايزون الخاص",
"Sounds": "الأصوات",
"Edit…": "تعديل…",
@@ -637,12 +615,10 @@
"up to date": "محدث",
"← Newer": "← الأحدث",
"Downloading from Mojang · {done} of {total} files": "جاري التنزيل من موجانج · {done} من {total} ملفات",
"{name}'s skin is kept.": "تم الاحتفاظ بمظهر {name}.",
"Edit instance": "تعديل النسخة",
"Remove shortcut": "إزالة الاختصار",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} غير مثبت هنا (أو غير مدرج في المسار PATH): انسخ ملف التكوين بدلاً من ذلك.",
"No worlds to put in.": "لا توجد عوالم لإضافتها.",
"Default skin": "المظهر الافتراضي",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "رابط إلى مستودع (أحدث إصدار له)، أو إصدار، أو فرع (Branch)، أو علامة (Tag)، أو التزام (Commit). يقوم المشغل بتثبيت ملف إصدار أو التزام محدد تمامًا، ولا يثبت فرعًا متغيرًا.",
"Sign in with GitHub to rate": "سجل الدخول بواسطة جيت هاب للتقييم",
"Star on GitHub": "أضف نجمة على GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "يلعبه {names}",
"{day}, {time} UTC": "{day}، {time} UTC",
"Microsoft account · online servers too": "حساب Microsoft · الخوادم عبر الإنترنت أيضًا",
"Offline · single player and LAN worlds": "دون اتصال · اللعب الفردي وعوالم الشبكة المحلية",
"Offline names": "أسماء دون اتصال",
"Add a name": "أضف اسمًا",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "من 3 إلى 16 حرفًا أو رقمًا أو شرطة سفلية. يمكنك تبديل الأسماء من الشريط العلوي أيضًا. الخوادم عبر الإنترنت لا تقبل الأسماء دون اتصال.",
"Play online with your Microsoft account": "العب عبر الإنترنت بحساب Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "سجّل الدخول بالحساب الذي يملك Minecraft: Java Edition. يرافقك اسمك ومظهرك إلى الخوادم عبر الإنترنت، كما في المشغلات الأخرى.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "تُفتح صفحة Microsoft نفسها في متصفحك. لا يرى Horizon كلمة مرورك أبدًا.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "{name}-nin tikintidən sonrakı addımının qurulması",
"In use": "İstifadədədir",
"Prepare": "Hazırlayın",
"Developer options": "Tərtibatçı seçimləri",
"{online} of {max} players": "{max} oyunçudan {online}",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). Play ehtiyac duyduğu Java ilə ilk dəfə hesabınız üçün onu Mojang-dan endirir.",
"Close": "Bağlayın",
@@ -98,7 +97,6 @@
"From my install": "Quraşdırdığımdan",
"the update failed: {error}": "yeniləmə uğursuz oldu: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesanın DRI_PRIME=1, ona görə də Vulkan digər kartı seçir.",
"New name": "Yeni ad",
"Dark": "Qaranlıq",
"Not now": "İndi yox",
"Use an access token…": "Giriş nişanından istifadə edin...",
@@ -115,7 +113,6 @@
"Partly": "Qismən",
"All": "Hamısı",
"Instance": "Nüsxə",
"Classic arms": "Klassik qollar",
"Versions": "Versiyalar",
"Release build: slower to build, slightly faster game": "Buraxılış quruluşu: qurmaq daha yavaş, bir az daha sürətli oyun",
"Performance build": "Performans qurmaq",
@@ -172,7 +169,6 @@
"about a minute left": "təxminən bir dəqiqə qaldı",
"Cancel": "Ləğv et",
"Add to {client}": "Əlavə et {client}",
"Skin…": "Dəri…",
"Environment": "Ətraf mühit",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Çox vaxt hələ də birlikdə işləyirlər. Quraşdırma uğursuz olarsa, eyni Nightly üçün hazırlanmış versiyaları quraşdırın.",
"Import an instance folder…": "Nümunə qovluğunu idxal edin...",
@@ -184,7 +180,6 @@
"newest stable version": "ən yeni stabil versiya",
"Choose image…": "Şəkil seçin...",
"No worlds yet: they appear here once you play one.": "Hələ dünya yoxdur: siz birini oynadığınız zaman onlar burada görünür.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Oflayn adlar oyunun sahibi olan Microsoft hesabı olmadan oynayır. Minecraft hələ də öz quraşdırmanızdan gəlir.",
"crash reports beside it": "yanında çökmə hesabatları",
"Install all": "Hamısını quraşdırın",
"No group": "Qrup yoxdur",
@@ -202,7 +197,6 @@
"My instance": "Mənim nümunəm",
"Snapshot": "Ani görüntü",
"Gallery": "Qalereya",
"Offline name": "Oflayn ad",
"Home": "Ev",
"Stopping": "Dayanır",
"MSPT · tick time": "MSPT · tik vaxtı",
@@ -304,8 +298,6 @@
"Patch notes": "Yamaq qeydləri",
"Your Minecraft server, {online}.": "Minecraft serveriniz, {online}.",
"Crash reports": "Çökmə hesabatları",
"Offline name · the game's own · plays": "Oflayn ad · oyunun öz · oynayır",
"Slim arms": "İncə qollar",
"Asking GitHub about {owner}/{repo}…": "GitHub-dan {owner}/{repo}... haqqında soruşulur",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Mojang-dan Minecraft {version} endirilir · {done} fayldan {total} fayl",
"Could not save your choice: {error}": "Seçiminizi saxlamaq mümkün olmadı: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizon mənzərəsi. Özünüzə məxsus PNG, JPEG və ya WebP şəklini seçin.",
"Not needed": "Lazım deyil",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Başlatıcının bu quruluşunda Microsoft girişi yoxdur (HORIZON_MSA_CLIENT_ID), ona görə də o, oyunu başlata bilmir.",
"Offline name · plays": "Oflayn ad · oynayır",
"Run the game through": "Oyunu keçin",
"needed by another pack": "başqa paketə lazımdır",
"Older →": "Köhnə →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Çalıştırmaq mümkün olmadı {program}: {error}",
"Restart": "Yenidən başladın",
"Copied to the clipboard.": "Buferə kopyalandı.",
"Your worlds, offline names and settings stay where they are.": "Dünyalarınız, oflayn adlarınız və parametrləriniz olduğu yerdə qalır.",
"Send nothing": "Heç nə göndərmə",
"Move to Trash": "Zibil qutusuna köçürün",
"Start from": "-dən başlayın",
"Asking Mojang for its versions…": "Mojangdan versiyaları soruşulur...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Başlatıcı tərəfindən saxlanılan və bu ad oynanılan zaman oyuna verilən 64×64 (və ya 64×32) dəri PNG və 64×32 baş PNG. Oyun hazırda standart dəriləri çəkir; bir dəfə bunlardan istifadə edir. Microsoft hesabının dərisi və örtüyü: tezliklə.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Başqa ad altında oflayn oynayın və yuxarı paneldən keçin. Onlayn serverlər oflayn adlar götürmür.",
"Report on Discord": "Discord haqqında hesabat",
"Export": "İxrac",
"Server": "Server",
@@ -384,7 +372,6 @@
"No version installed yet.": "Hələ heç bir versiya quraşdırılmayıb.",
"Release": "Buraxılış",
"Verified": "Doğrulanıb",
"Choose a skin…": "Dəri seçin...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} hələ öz doğma modlarını oynamır: onlarla oyunu qurun.",
"Use jars from my instance…": "Mənim nümunəmdəki bankalardan istifadə edin...",
"Applications menu": "Proqramlar menyusu",
@@ -408,7 +395,6 @@
"Open backups": "Yedəkləri açın",
"The game is running: change packs in its own menus, or here once it is closed.": "Oyun işləyir: paketləri öz menyularında və ya burada bağlandıqdan sonra dəyişdirin.",
"Check now": "İndi yoxlayın",
"Choose a cape…": "Başlıq seçin...",
"Save": "Saxla",
"Folder": "Qovluq",
"Searching…": "Axtarılır...",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Çıxın",
"When it starts": "Başlayanda",
"{name}'s skin": "{name} dərisi",
"Start": "Başlayın",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft quraşdırmasına ehtiyac yoxdur: Horizon onu hesabınız üçün Mojang-dan endirir.",
"Logs": "Qeydlər",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Buraxılış siyahısı yüklənərkən söz nişanı.",
"Playing offline": "Oflayn oynayır",
"Sign in to Tailscale": "Tailscale-ə daxil olun",
"Offline names without an account": "Hesab olmadan oflayn adlar",
"Help make Horizon faster and steadier?": "Horizon daha sürətli və sabit olmağa kömək edin?",
"Sign in to play": "Oynamaq üçün daxil olun",
"Ported": "Köçürülüb",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Bu başlatıcını paket menecerinizlə yeniləyin.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Bu başlatıcını bağlayın, onu {folder} ünvanına köçürün və yeniləmələri aktivləşdirmək üçün orada açın.",
"Any MCP client": "İstənilən MCP müştəri",
"{name}'s cape is kept.": "{name} nin papağı saxlanılır.",
"Not reviewed by the Horizon registry": "Horizon reyestr tərəfindən nəzərdən keçirilməyib",
"Proxy": "Proksi",
"Checking": "Yoxlanılır",
"Updates": "Yeniləmələr",
"Asking Microsoft…": "Microsoft soruşulur...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Minecraft {version} üçün hazırlanmışdır, onun səsləri olmadan: oyun səssiz olacaq. Onları Minecraft quraşdırmanızdan köçürmək üçün yenidən hazırlayın.",
"Forget": "Unut",
"Import a modpack…": "Mod paketini idxal edin...",
"Search versions": "Versiyaları axtarın",
"failed": "uğursuz oldu",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Qaldı: {line}.",
"Resource packs": "Resurs paketləri",
"yesterday": "dünən",
"No cape": "Plaş yoxdur",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Hər seansdan sonra: kadr vaxtı faizləri və 14 kova histoqramı, işarələmə vaxtları, pik yaddaş və işə başlama vaxtları, maşınınız (ƏS, CPU və onun nüvələri və saatları, yaddaş ölçüsü, GPU, onun yaddaşı və sürücüsü, sürücünün növü, ekran ölçüsü və yeniləmə sürəti, noutbuk və ya iş masası, batareyada olub-olmaması) və performansı dəyişən parametrlər.",
"Make a token": "Bir nişan hazırlayın",
"Added {names}: the game turns it on when the world opens.": "{names} əlavə edildi: dünya açılanda oyun onu işə salır.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Paylaşıldı: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Eyni Wi-Fi-da olan dostlar: Multiplayer, Server əlavə edin, sonra bu ünvanı yapışdırın.",
"None yet: drop a .hshader or a shader pack .zip here.": "Hələ heç biri: bura .hshader və ya shader paketini .zip buraxın.",
"Offline name · the game's own": "Oflayn ad · oyunun özünə məxsusdur",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Native mods sandboxed deyil: onlar hər hansı bir proqram kimi kompüterinizə tam giriş imkanı ilə işləyirlər. Yalnız müəlliflərinə etibar etdiyiniz modları quraşdırın. Biri ilə oynamaq üçün oyunu Modlar səhifəsində qurun; ilk quruluş Rust-u yükləyir və 20-30 dəqiqə çəkir.",
"Your selected version only changes if you were playing the newest one.": "Seçdiyiniz versiya yalnız ən yenisini ifa etsəniz dəyişir.",
"Multiplayer": "Multiplayer",
@@ -587,7 +567,6 @@
"the port": "liman",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Mənbə {source}. Onun buraxılışı məzmun modu olan {file} göndərilir: GitHub-dan bunları quraşdırmaq hələ dəstəklənmir.",
"Build anyway": "Hər halda tikin",
"A name, 3 to 16 letters": "Ad, 3 ilə 16 hərf",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "GitHub-dan {mods} quraşdırılıb ({source}). Onu Modlar səhifəsində qurun.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Parametrlər, Açarlar, Giriş nişanı yaradın. O, bu kompüterin brelokunda saxlanılır və yalnız Tailscale-ə göndərilir.",
"{id} is up to date.": "{id} güncəldir.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Mən onu oxudum və inanıram: quraşdırın",
"Close export": "İxracatı bağlayın",
"Playing needs a prepared Horizon version (Play page).": "Oynamaq üçün hazırlanmış Horizon versiya lazımdır (Oynatma səhifəsi).",
"Offline, the game's name": "Oflayn, oyunun adı",
"From Horizon's registry": "Horizon reyestrindən",
"Sounds": "Səslər",
"Edit…": "Redaktə et...",
@@ -635,12 +613,10 @@
"up to date": "bu günə qədər",
"← Newer": "← Daha yeni",
"Downloading from Mojang · {done} of {total} files": "Mojang-dan endirilir · {total} fayldan {done} fayl",
"{name}'s skin is kept.": "{name} dərisi saxlanılır.",
"Edit instance": "Nümunəni redaktə edin",
"Remove shortcut": "Qısayolu silin",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} burada quraşdırılmayıb (və ya PATH-də deyil): yerinə konfiqurasiyanı kopyalayın.",
"No worlds to put in.": "Yerləşdirməyə dünyalar yoxdur.",
"Default skin": "Defolt dəri",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Repozitoriyaya keçid (onun ən son buraxılışı), buraxılış, filial və ya etiket və ya öhdəlik. Başlatıcı bir dəqiq buraxılış faylı və ya öhdəliyi quraşdırır, heç vaxt hərəkət edən bir filial yoxdur.",
"Sign in with GitHub to rate": "Qiymətləndirmək üçün GitHub ilə daxil olun",
"Star on GitHub": "GitHub-da ulduz ver",
@@ -1053,10 +1029,6 @@
"played by {names}": "ifa etdi {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft hesabı · onlayn serverlər də",
"Offline · single player and LAN worlds": "Oflayn · tək oyunçu və LAN dünyaları",
"Offline names": "Offline adlar",
"Add a name": "Ad əlavə edin",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3-dən 16-a qədər hərf, rəqəm və ya alt xətt. Üst paneldən də adları dəyişin. Onlayn serverlər oflayn adlar götürmür.",
"Play online with your Microsoft account": "Microsoft hesabınızla onlayn oynayın",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Minecraft: Java Edition-a sahib olan hesabla daxil olun. Adınız və dəriniz digər işəsalanlar kimi onlayn serverlərə gəlir.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Brauzerinizdə Microsoftun öz səhifəsi açılır. Horizon parolunuzu heç vaxt görmür.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Бина {name} төҙөүҙән һуңғы аҙым",
"In use": "Ҡулланыуҙа",
"Prepare": "Әҙерләү .",
"Developer options": "Төҙөүсе варианттары",
"{online} of {max} players": "{max} уйынсыларҙан {online}",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Баҫма). Play скачивает уны Mojang һеҙҙең иҫәп яҙмаһы өсөн беренсе тапҡыр, Java менән ул кәрәк.",
"Close": "Ябыҡ",
@@ -98,7 +97,6 @@
"From my install": "Минең ҡуйыуҙан",
"the update failed: {error}": "Яңыртыу уңышһыҙлыҡҡа осраны: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Месаның DRI_PRIME=1, шуға күрә Vulkan икенсе картаны һайлай.",
"New name": "Яңы исем .",
"Dark": "Ҡараңғы",
"Not now": "Хәҙер түгел .",
"Use an access token…": "Ҡулланыу маркеры рөхсәт...",
@@ -115,7 +113,6 @@
"Partly": "Өлөшләтә",
"All": "Барыһы ла",
"Instance": "Инстанция",
"Classic arms": "Классик ҡоралдар",
"Versions": "Версиялары",
"Release build: slower to build, slightly faster game": "Релиз төҙөү: яйыраҡ төҙөү, бер аҙ тиҙерәк уйын",
"Performance build": "Һөҙөмтәлелек төҙөү",
@@ -172,7 +169,6 @@
"about a minute left": "бер минут самаһы ҡалды .",
"Cancel": "Юҡҡа сығарыу",
"Add to {client}": "{client} тиклем өҫтәргә",
"Skin…": "Скин…",
"Environment": "Тирә-яҡ мөхит",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Йыш ҡына әле лә бергә эшләйҙәр. Әгәр ҙә төҙөү уңышһыҙлыҡҡа осраһа, шул уҡ Nightly өсөн эшләнгән версияларҙы ҡуйығыҙ.",
"Import an instance folder…": "Импортлау экземпляр папкаһы...",
@@ -184,7 +180,6 @@
"newest stable version": "иң яңы тотороҡло версия",
"Choose image…": "Һүрәтте һайлағыҙ...",
"No worlds yet: they appear here once you play one.": "Әлегә донъялар юҡ: улар бында бер тапҡыр уйнаһаң күренә.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Офлайн исемдәр уйнай Microsoft иҫәп яҙмаһы булмаған, тип уйын хужаһы. Minecraft һаман да үҙ ҡуйыуҙан килә.",
"crash reports beside it": "авария тураһында хәбәрҙәр уның эргәһендә",
"Install all": "Барыһын да ҡуйырға",
"No group": "Төркөм юҡ",
@@ -202,7 +197,6 @@
"My instance": "Минең миҫалым",
"Snapshot": "Снапшот",
"Gallery": "Галерея",
"Offline name": "Офлайн исем",
"Home": "Төп Төп",
"Stopping": "Туҡтау",
"MSPT · tick time": "MSPT · тик ваҡыты",
@@ -304,8 +298,6 @@
"Patch notes": "Патч иҫкәрмәләре",
"Your Minecraft server, {online}.": "Һеҙҙең Minecraft серверығыҙ, {online}.",
"Crash reports": "Авария тураһында хәбәрҙәр",
"Offline name · the game's own · plays": "Офлайн исем · уйындың үҙ · уйнай",
"Slim arms": "Нәҙек ҡулдар .",
"Asking GitHub about {owner}/{repo}…": "Һорау GitHub тураһында {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Minecraft {version} Mojang · {done} {total} файлдарынан",
"Could not save your choice: {error}": "Һеҙҙең һайлауҙы һаҡлай алманы: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizon-ның пейзажы. Һайлап алыу PNG, JPEG йәки WebP һүрәте үҙ.",
"Not needed": "Кәрәкмәй",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Был ҡоролма стартер Microsoft логин юҡ (HORIZON_MSA_CLIENT_ID), шуға күрә ул уйынды башлай алмай.",
"Offline name · plays": "Офлайн исем · уйнай",
"Run the game through": "Уйынды үткәреү",
"needed by another pack": "икенсе пакетҡа кәрәк",
"Older →": "Өлкәнерәк →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Йүгерә алманы {program}: {error}",
"Restart": "Перестарт",
"Copied to the clipboard.": "Буферға күсерелгән.",
"Your worlds, offline names and settings stay where they are.": "Һеҙҙең донъялар, офлайн исемдәр һәм параметрҙар улар ҡайҙа ҡала.",
"Send nothing": "Бер нәмә лә ебәрмәгеҙ",
"Move to Trash": "Сүплеккә күсерергә",
"Start from": "2012 йылдан башлай.",
"Asking Mojang for its versions…": "Һорау Mojang уның версиялары өсөн...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (йәки 64×32) тире PNG һәм 64×32 плащ PNG, пускатель һаҡлай һәм был исем уйнағанда уйынға бирелә. Уйын әлегә тиреләрҙе ғәҙәттәгесә тарта; ул был ҡуллана бер тапҡыр мөмкин. А Microsoft иҫәп яҙмаһының тиреһе һәм плащ: тиҙҙән.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Икенсе исем аҫтында офлайн уйнау, һәм өҫкө панелдән күсеү. Онлайн серверҙар офлайн исемдәрҙе алмай.",
"Report on Discord": "Discord буйынса отчет",
"Export": "Экспорт",
"Server": "Сервер",
@@ -384,7 +372,6 @@
"No version installed yet.": "Әлегә бер ниндәй ҙә версия ҡуйылмаған.",
"Release": "Релиз",
"Verified": "Тикшерелгән",
"Choose a skin…": "Тире һайлағыҙ...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} әлегә үҙенең туған модтарын уйнамай: улар менән уйын төҙөгөҙ.",
"Use jars from my instance…": "Минең миҫалдан банкалар ҡулланығыҙ...",
"Applications menu": "Ҡушымталар менюһы",
@@ -408,7 +395,6 @@
"Open backups": "Резерв копияларын асыу",
"The game is running: change packs in its own menus, or here once it is closed.": "Уйын эшләй: үҙ менюларында пакеттарҙы алмаштырыу, йәки бында бер тапҡыр ул ябыла.",
"Check now": "Хәҙер тикшерегеҙ",
"Choose a cape…": "Һайлағыҙ плащ...",
"Save": "Һаҡлау",
"Folder": "Папка",
"Searching…": "Эҙләү...",
@@ -422,7 +408,6 @@
"MangoHud": "МангоХуд",
"Sign out": "Сығыу",
"When it starts": "Ҡасан башлана .",
"{name}'s skin": "{name} тиреһе",
"Start": "Башланғыс",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft ҡуйыу кәрәкмәй: Horizon уны Mojang-нан һеҙҙең иҫәп яҙмаһына скачивает.",
"Logs": "Журналдар",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Һүҙ билдәһе, шул уҡ ваҡытта релиз исемлеге йөкләнә.",
"Playing offline": "Офлайн уйнау",
"Sign in to Tailscale": "Tailscale сайтына инергә",
"Offline names without an account": "Иҫәп яҙмаһы булмаған офлайн исемдәр",
"Help make Horizon faster and steadier?": "Horizon тиҙерәк һәм тотороҡлораҡ эшләргә ярҙам итегеҙме?",
"Sign in to play": "Уйнар өсөн инергә",
"Ported": "Портланған",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Был лаунчерҙы пакет менеджерығыҙ менән яңыртығыҙ.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Был лаунчерҙы ябығыҙ, уны {folder} папкаһына күсерегеҙ һәм яңыртыуҙарҙы ҡабыҙыу өсөн шунда асығыҙ.",
"Any MCP client": "Теләһә ниндәй MCP клиенты",
"{name}'s cape is kept.": "{name}-ның пласы һаҡлана.",
"Not reviewed by the Horizon registry": "Horizon реестры тарафынан тикшерелмәгән",
"Proxy": "Прокси",
"Checking": "Тикшереү",
"Updates": "Яңыртыуҙар",
"Asking Microsoft…": "Һорау Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Minecraft {version} өсөн әҙерләнгән, уның тауыштары булмаған: уйын тын буласаҡ. Яңынан әҙерләнергә, уларҙы күсерергә һеҙҙең Minecraft ҡуйыу.",
"Forget": "Онот .",
"Import a modpack…": "Модпакты импортлағыҙ...",
"Search versions": "Эҙләү версиялары",
"failed": "уңышһыҙлыҡҡа осраны",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Ҡалды: {line}.",
"Resource packs": "Ресурс пакеттары",
"yesterday": "кисә",
"No cape": "Плащ юҡ",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Һәр сессиянан һуң: кадр-ваҡыт процентилдәр һәм 14-биҙрә гистограмма, галочкой ваҡыт, пик хәтер һәм старт ваҡыт, һеҙҙең машина менән (ОС, процессор һәм уның ядролары һәм сәғәттәр, хәтер күләме, GPU, уның хәтере һәм драйверы, диск тибы, экран күләме һәм яңыртыу тиҙлеге, батарея йәки өҫтәл notttting, тип етештереүсәнлеге.",
"Make a token": "Жетон эшләү .",
"Added {names}: the game turns it on when the world opens.": "Өҫтәлде {names}: уйын донъя асылғанда уны ҡабыҙа.",
@@ -557,7 +538,6 @@
"Shared: {url}": "{url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Дуҫтар бер үк Wi-Fi: Мультиплеер, Сервер өҫтәү, һуңынан был адресты йәбештереү.",
"None yet: drop a .hshader or a shader pack .zip here.": "Әлегә бер ниндәй ҙә: бында .hshader йәки .zip шейдер пакетын ташлағыҙ.",
"Offline name · the game's own": "Офлайн исем · уйындың үҙ",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Туған модтар ҡом йәшниктәре түгел: улар һеҙҙең компьютерға тулы рөхсәт менән эшләй, теләһә ниндәй программа кеүек. Авторҙарына ышанған модтарҙы ғына ҡуйығыҙ. Бер уйнау өсөн, уйын төҙөү Mods битендә; беренсе төҙөү скачивает Rust һәм 20 30 минут ала.",
"Your selected version only changes if you were playing the newest one.": "Һеҙ һайлаған версия ғына үҙгәрә, әгәр һеҙ уйнаған иң яңы.",
"Multiplayer": "Күп уйынсылар",
@@ -587,7 +567,6 @@
"the port": "порт",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "{source} сығанағы. Уның релиз суднолар {file}, контент мод: ҡуйыу, уларҙы GitHub әлегә ярҙам итмәй.",
"Build anyway": "Барыбер төҙөү",
"A name, 3 to 16 letters": "Исем, 3-тән 16 хәрефкә тиклем",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "GitHub-нан {mods} ҡуйылған ({source}). Уны Модтар битендә төҙөгөҙ.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Көйләүҙәр, Асҡыстар, Генерациялау инеү маркеры. Ул был компьютерҙағы брелокта һаҡлана һәм Tailscale һанына ғына ебәрелә.",
"{id} is up to date.": "{id} заманса.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Мин уны уҡыным һәм ышанам: ҡуйырға",
"Close export": "Ябыҡ экспорт",
"Playing needs a prepared Horizon version (Play page).": "Уйнау өсөн әҙерләнгән Horizon версияһы кәрәк (Уйнау бите).",
"Offline, the game's name": "Офлайн, уйындың исеме",
"From Horizon's registry": "Horizon реестрынан",
"Sounds": "Тауыштар .",
"Edit…": "Мөхәррирләргә...",
@@ -635,12 +613,10 @@
"up to date": "заманса",
"← Newer": "← Яңыраҡ",
"Downloading from Mojang · {done} of {total} files": "Mojang · {done} {total} файлдарынан күсереп алыу",
"{name}'s skin is kept.": "{name} тиреһе һаҡлана.",
"Edit instance": "Данаһын мөхәррирләү",
"Remove shortcut": "Ярлыҡты алып ташлау",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} бында ҡуйылмаған (йәки PATH-та юҡ): уның урынына конфигты күсерергә.",
"No worlds to put in.": "Ҡуйырға донъялар юҡ.",
"Default skin": "Ғәҙәттәгесә тире",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Һылтанма һаҡлағысҡа (уның һуңғы релизы), релизға, тармаҡҡа йәки тегҡа йәки коммитҡа. Запускчик бер теүәл релиз файлы йәки коммит ҡуя, бер ҡасан да тармаҡ, тип күсә.",
"Sign in with GitHub to rate": "Баһа ҡуйыу өсөн GitHub менән инергә",
"Star on GitHub": "GitHub-та йондоҙ ҡуй",
@@ -1053,10 +1029,6 @@
"played by {names}": "{names} уйнай",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft иҫәп яҙмаһы · онлайн-серверҙар ҙа",
"Offline · single player and LAN worlds": "Офлайн · бер уйынсы һәм LAN донъялары",
"Offline names": "Офлайн исемдәр",
"Add a name": "Исем өҫтәү .",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3-тән 16-ға тиклем хәреф, һан йәки аҫтына һыҙыҡ. Өҫкө панелдән дә исемдәрҙе алмаштырығыҙ. Онлайн серверҙар офлайн исемдәрҙе алмай.",
"Play online with your Microsoft account": "Microsoft иҫәбегеҙ менән онлайн уйнағыҙ",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Minecraft: Java Баҫмаға эйә булған иҫәп яҙмаһы менән инергә. Һеҙҙең исем һәм тире менән бергә килә онлайн-серверҙар, башҡа стартерҙар кеүек.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Браузерығыҙҙа Microsoft үҙ бите асыла. Horizon бер ҡасан да һеҙҙең паролде күрмәй.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Выкананне этапу пасля зборкі для {name}",
"In use": "Ва ўжытку",
"Prepare": "Падрыхтаваць",
"Developer options": "Параметры распрацоўніка",
"{online} of {max} players": "{online} з {max} гульцоў",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (выданне Java). Play спампоўвае яго з Mojang для вашага ўліковага запісу ў першы раз, з патрэбнай Java.",
"Close": "Закрыць",
@@ -98,7 +97,6 @@
"From my install": "З маёй устаноўкі",
"the update failed: {error}": "абнаўленне не атрымалася: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 у Mesa, таму Vulkan выбірае іншую відэакарту.",
"New name": "Новая назва",
"Dark": "Цёмны",
"Not now": "Не цяпер",
"Use an access token…": "Выкарыстоўвайце маркер доступу…",
@@ -115,7 +113,6 @@
"Partly": "Часткова",
"All": "Усе",
"Instance": "Экземпляр",
"Classic arms": "Класічныя рукі",
"Versions": "Версіі",
"Release build: slower to build, slightly faster game": "Рэлізная зборка: збіраецца даўжэй, гульня працуе крыху хутчэй",
"Performance build": "Зборка для прадукцыйнасці",
@@ -172,7 +169,6 @@
"about a minute left": "засталося каля хвіліны",
"Cancel": "Адмяніць",
"Add to {client}": "Дадаць у {client}",
"Skin…": "Скін…",
"Environment": "Асяроддзе",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Яны часта ўсё яшчэ працуюць разам. Калі зборка не атрымаецца, усталюйце версіі, зробленыя для таго ж Nightly.",
"Import an instance folder…": "Імпартаваць тэчку экземпляра…",
@@ -184,7 +180,6 @@
"newest stable version": "апошняя стабільная версія",
"Choose image…": "Выберыце малюнак…",
"No worlds yet: they appear here once you play one.": "Светаў пакуль няма: яны з'яўляюцца тут, як толькі вы згуляеце ў адзін.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "З афлайн-імёнамі можна гуляць без уліковага запісу Microsoft, якому належыць гульня. Minecraft усё роўна бярэцца з вашай уласнай усталёўкі.",
"crash reports beside it": "справаздачы аб збоях побач",
"Install all": "Усталяваць усе",
"No group": "Няма групы",
@@ -202,7 +197,6 @@
"My instance": "Мой экземпляр",
"Snapshot": "Здымак",
"Gallery": "Галерэя",
"Offline name": "Пазасеткавае імя",
"Home": "Галоўная",
"Stopping": "Спыняецца",
"MSPT · tick time": "MSPT · час ціку",
@@ -304,8 +298,6 @@
"Patch notes": "Нататкі аб выпраўленнях",
"Your Minecraft server, {online}.": "Ваш сервер Minecraft, {online}.",
"Crash reports": "Справаздачы аб збоях",
"Offline name · the game's own · plays": "Афлайн-імя · уласнае імя ў гульні · гуляе",
"Slim arms": "Тонкія рукі",
"Asking GitHub about {owner}/{repo}…": "Запыт да GitHub пра {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Спампоўка Minecraft {version} з Mojang · {done} з {total} файлаў",
"Could not save your choice: {error}": "Немагчыма захаваць ваш выбар: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Пейзаж Horizon. Выберыце ўласную выяву ў фармаце PNG, JPEG або WebP.",
"Not needed": "Не трэба",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "У гэтай зборцы праграмы запуску няма ўваходу ў Microsoft (HORIZON_MSA_CLIENT_ID), таму яна не можа запусціць гульню.",
"Offline name · plays": "Пазасеткавае імя · гуляе",
"Run the game through": "Запускаць гульню праз",
"needed by another pack": "патрэбны іншы пакет",
"Older →": "Старэйшыя →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Не атрымалася запусціць {program}: {error}",
"Restart": "Перазапуск",
"Copied to the clipboard.": "Скапіравана ў буфер абмену.",
"Your worlds, offline names and settings stay where they are.": "Вашы светы, імёны ў аўтаномным рэжыме і налады застаюцца на месцы.",
"Send nothing": "Нічога не адпраўляць",
"Move to Trash": "Перамясціць у сметніцу",
"Start from": "Пачаць з",
"Asking Mojang for its versions…": "Запыт у Mojang аб яго версіях...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "PNG скіна 64×64 (або 64×32) і PNG плашча 64×32, якія захоўваюцца ў праграме запуску і перадаюцца гульні, калі пад гэтым імем гуляюць. На дадзены момант гульня малюе скіны па змаўчанні; яна будзе выкарыстоўваць іх, як толькі зможа. Скін і плашч уліковага запісу Microsoft: хутка.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Гуляйце ў аўтаномным рэжыме пад іншым імем і пераключайцеся з верхняй панэлі. Інтэрнэт-серверы не прымаюць афлайн-імёны.",
"Report on Discord": "Паведаміць у Discord",
"Export": "Экспарт",
"Server": "Сервер",
@@ -384,7 +372,6 @@
"No version installed yet.": "Версія яшчэ не ўсталявана.",
"Release": "Рэліз",
"Verified": "Праверана",
"Choose a skin…": "Выберыце скін…",
"{instance} doesn't play its native mods yet: build the game with them.": "Экземпляр {instance} яшчэ не выкарыстоўвае свае натыўныя моды: збярыце гульню разам з імі.",
"Use jars from my instance…": "Выкарыстаць jar-файлы з майго экземпляра…",
"Applications menu": "Меню прыкладанняў",
@@ -408,7 +395,6 @@
"Open backups": "Адкрыць рэзервовыя копіі",
"The game is running: change packs in its own menus, or here once it is closed.": "Гульня працуе: мяняйце пакеты ва ўласным меню або тут, калі яна закрыта.",
"Check now": "Праверце зараз",
"Choose a cape…": "Выберыце плашч…",
"Save": "Захаваць",
"Folder": "Тэчка",
"Searching…": "Пошук...",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Выйсці",
"When it starts": "Калі пачнецца",
"{name}'s skin": "Скін {name}",
"Start": "Пачаць",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft не патрабуецца ўсталёўваць: Horizon спампоўвае яго з Mojang для вашага ўліковага запісу.",
"Logs": "Лагі",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Лагатып, пакуль загружаецца спіс рэлізаў.",
"Playing offline": "Гульня ў аўтаномным рэжыме",
"Sign in to Tailscale": "Увайдзіце ў Tailscale",
"Offline names without an account": "Аўтаномныя імёны без уліковага запісу",
"Help make Horizon faster and steadier?": "Дапамажыце зрабіць Horizon больш хуткім і стабільным?",
"Sign in to play": "Увайдзіце, каб гуляць",
"Ported": "Партаваны",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Абнавіце гэты лаўнчар праз свой пакетны менеджар.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Закрыйце гэты лаўнчар, перамясціце яго ў {folder} і запусціце адтуль, каб уключыць абнаўленні.",
"Any MCP client": "Любы кліент MCP",
"{name}'s cape is kept.": "Захоўваецца плашч {name}.",
"Not reviewed by the Horizon registry": "Не разглядаецца рэестрам Horizon",
"Proxy": "Проксі",
"Checking": "Праверка",
"Updates": "Абнаўленні",
"Asking Microsoft…": "Запыт да Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Падрыхтавана для Minecraft {version}, без яго гукаў: гульня будзе бясшумнай. Падрыхтуйцеся зноў скапіяваць іх з усталяванай Minecraft.",
"Forget": "Забыць",
"Import a modpack…": "Імпартаваць пакет модаў…",
"Search versions": "Пошук версій",
"failed": "не атрымалася",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Пакінуты: {line}.",
"Resource packs": "Пакі рэсурсаў",
"yesterday": "учора",
"No cape": "Без плашча",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Пасля кожнага сеансу: працэнты часу кадраў і гістаграма з 14 інтэрваламі, час цікаў, пік памяці і час запуску з вашай машынай (АС, працэсар і яе ядра і тактавыя частоты, памер памяці, графічны працэсар, яго памяць і драйвер, тып дыска, памер экрана і частата абнаўлення, ноўтбук або настольны камп'ютар, працуе ад батарэі ці не) і налады, якія змяняюць прадукцыйнасць.",
"Make a token": "Стварыць токен",
"Added {names}: the game turns it on when the world opens.": "Дададзена {names}: гульня падключыць гэта пры адкрыцці свету.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Абагулены: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Сябры ў адной Wi-Fi: шматкарыстальніцкая гульня, дадаць сервер, затым устаўце гэты адрас.",
"None yet: drop a .hshader or a shader pack .zip here.": "Пакуль няма: перанясіце .hshader або пакет шэйдараў .zip сюды.",
"Offline name · the game's own": "Афлайн-імя · уласнае ў гульні",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Натыўныя моды не знаходзяцца ў «пясочніцы»: яны маюць поўны доступ да вашага камп'ютара, як і любая праграма. Усталёўвайце моды толькі ад правераных аўтараў. Каб гуляць з імі, збярыце гульню на старонцы «Моды»; першая зборка спампуе Rust і зойме ад 20 да 30 хвілін.",
"Your selected version only changes if you were playing the newest one.": "Выбраная вамі версія змяняецца толькі ў тым выпадку, калі вы гулялі ў самую новую.",
"Multiplayer": "Мультыплэер",
@@ -587,7 +567,6 @@
"the port": "порт",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Крыніца {source}. Яго рэліз пастаўляецца {file}, мод кантэнту: усталяванне з GitHub пакуль не падтрымліваецца.",
"Build anyway": "Усё роўна сабраць",
"A name, 3 to 16 letters": "Імя, ад 3 да 16 літар",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Усталяваны {mods} з GitHub ({source}). Стварыце яго на старонцы Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Налады, ключы, стварэнне маркера доступу. Ён захоўваецца ў бірульцы гэтага камп'ютара і адпраўляецца толькі ў Tailscale.",
"{id} is up to date.": "{id} актуальны.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Я прачытаў і давяраю: усталяваць",
"Close export": "Закрыць экспарт",
"Playing needs a prepared Horizon version (Play page).": "Для гульні патрэбна падрыхтаваная версія Horizon (старонка прайгравання).",
"Offline, the game's name": "Offline, назва гульні",
"From Horizon's registry": "З рэестра Horizon",
"Sounds": "Гукі",
"Edit…": "Рэдагаваць...",
@@ -635,12 +613,10 @@
"up to date": "у актуальным стане",
"← Newer": "← Навей",
"Downloading from Mojang · {done} of {total} files": "Спампоўка з Mojang · {done} з {total} файлаў",
"{name}'s skin is kept.": "Скін {name} захоўваецца.",
"Edit instance": "Рэдагаваць экземпляр",
"Remove shortcut": "Выдаліць ярлык",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} не ўсталяваны тут (або не ў PATH): замест гэтага скапіруйце канфігурацыю.",
"No worlds to put in.": "Няма светаў, каб змясціць.",
"Default skin": "Скін па змаўчанні",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Спасылка на рэпазітар (яго апошнюю версію), рэліз, галінку або тэг, або фіксацыю. Праграма запуску ўсталёўвае адзін дакладны файл выпуску або фіксацыю, а не галінку, якая рухаецца.",
"Sign in with GitHub to rate": "Увайдзіце праз GitHub, каб ацаніць",
"Star on GitHub": "Пазначыць зоркай на GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "гуляў {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Уліковы запіс Microsoft · Інтэрнэт-серверы таксама",
"Offline · single player and LAN worlds": "Пазасеткавы · светы для аднаго гульца і лакальнай сеткі",
"Offline names": "Афлайн імёны",
"Add a name": "Дадайце імя",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "Ад 3 да 16 літар, лічбаў або знакаў падкрэслівання. Таксама пераключайце імёны з верхняй панэлі. Інтэрнэт-серверы не прымаюць афлайн-імёны.",
"Play online with your Microsoft account": "Гуляйце ў інтэрнэце са сваім уліковым запісам Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Увайдзіце з уліковым запісам, які валодае Minecraft: Java Edition. Ваша імя і скін прыходзяць на анлайн-серверы, як і ў іншых праграмах запуску.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "У вашым браўзеры адкрыецца ўласная старонка Microsoft. Horizon ніколі не бачыць ваш пароль.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Изграждане на стъпка след изграждането на {name}",
"In use": "В употреба",
"Prepare": "Подгответе се",
"Developer options": "Опции за разработчици",
"{online} of {max} players": "{online} от {max} играчи",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). Play го изтегля от Mojang за вашия акаунт за първи път, с Java, от която се нуждае.",
"Close": "затвори",
@@ -98,7 +97,6 @@
"From my install": "От моята инсталация",
"the update failed: {error}": "актуализацията е неуспешна: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 на Mesa, така че Vulkan избира другата карта.",
"New name": "Ново име",
"Dark": "Тъмно",
"Not now": "Не сега",
"Use an access token…": "Използвайте токен за достъп...",
@@ -115,7 +113,6 @@
"Partly": "частично",
"All": "Всички",
"Instance": "Инстанция",
"Classic arms": "Класически оръжия",
"Versions": "Версии",
"Release build: slower to build, slightly faster game": "Изграждане на версията: по-бавна за изграждане, малко по-бърза игра",
"Performance build": "Изграждане на производителност",
@@ -172,7 +169,6 @@
"about a minute left": "остава около минута",
"Cancel": "Отказ",
"Add to {client}": "Добавяне към {client}",
"Skin…": "кожа...",
"Environment": "Околна среда",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Те често все още работят заедно. Ако изграждането е неуспешно, инсталирайте версии, направени за същия Nightly.",
"Import an instance folder…": "Импортиране на папка с екземпляр...",
@@ -184,7 +180,6 @@
"newest stable version": "най-новата стабилна версия",
"Choose image…": "Изберете изображение...",
"No worlds yet: they appear here once you play one.": "Все още няма светове: те се появяват тук, след като изиграете един.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Офлайн имена играят без акаунт в Microsoft, който притежава играта. Minecraft все още идва от вашата собствена инсталация.",
"crash reports beside it": "доклади за сривове до него",
"Install all": "Инсталирайте всички",
"No group": "Няма група",
@@ -202,7 +197,6 @@
"My instance": "Моят пример",
"Snapshot": "Моментна снимка",
"Gallery": "Галерия",
"Offline name": "Офлайн име",
"Home": "Начало",
"Stopping": "Спиране",
"MSPT · tick time": "MSPT · тик време",
@@ -305,8 +299,6 @@
"Patch notes": "Бележки за кръпка",
"Your Minecraft server, {online}.": "Вашият Minecraft сървър, {online}.",
"Crash reports": "Доклади за сривове",
"Offline name · the game's own · plays": "Офлайн име · собствена игра · играе",
"Slim arms": "Тънки ръце",
"Asking GitHub about {owner}/{repo}…": "Питане на GitHub за {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Изтегляне на Minecraft {version} от Mojang · {done} от {total} файла",
"Could not save your choice: {error}": "Вашият избор не можа да бъде запазен: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Пейзажът на Horizon. Изберете своя снимка във формат PNG, JPEG или WebP.",
"Not needed": "Не е необходимо",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Тази компилация на стартовия панел няма влизане в Microsoft (HORIZON_MSA_CLIENT_ID), така че не може да стартира играта.",
"Offline name · plays": "Офлайн име · играе",
"Run the game through": "Прокарайте играта",
"needed by another pack": "необходими за друг пакет",
"Older →": "По-стари →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "Не можа да се изпълни {program}: {error}",
"Restart": "Рестартирайте",
"Copied to the clipboard.": "Копирано в клипборда.",
"Your worlds, offline names and settings stay where they are.": "Вашите светове, офлайн имена и настройки остават там, където са.",
"Send nothing": "Не изпращайте нищо",
"Move to Trash": "Преместване в кошчето",
"Start from": "Започнете от",
"Asking Mojang for its versions…": "Питане на Mojang за неговите версии...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (или 64×32) PNG с кожа и 64×32 PNG с наметка, които се съхраняват от стартовия панел и се дават на играта, когато това име се играе. Играта рисува скинове по подразбиране за сега; използва ги, когато може. Кожа и наметка на акаунт в Microsoft: очаквайте скоро.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Играйте офлайн под друго име и превключете от горната лента. Онлайн сървърите не приемат офлайн имена.",
"Report on Discord": "Докладвайте за Discord",
"Export": "Експортиране",
"Server": "сървър",
@@ -385,7 +373,6 @@
"No version installed yet.": "Все още няма инсталирана версия.",
"Release": "Освобождаване",
"Verified": "Проверен",
"Choose a skin…": "Изберете кожа...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} все още не играе собствените си модове: изградете играта с тях.",
"Use jars from my instance…": "Използвайте буркани от моя екземпляр...",
"Applications menu": "Меню с приложения",
@@ -409,7 +396,6 @@
"Open backups": "Отворете резервни копия",
"The game is running: change packs in its own menus, or here once it is closed.": "Играта работи: сменете пакетите в нейните собствени менюта или тук, след като бъде затворена.",
"Check now": "Проверете сега",
"Choose a cape…": "Изберете пелерина...",
"Save": "Запазване",
"Folder": "Папка",
"Searching…": "Търсене...",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Излезте",
"When it starts": "Когато започне",
"{name}'s skin": "Кожата на {name}",
"Start": "Започнете",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Не е необходима инсталация на Minecraft: Horizon го изтегля от Mojang за вашия акаунт.",
"Logs": "трупи",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Думната марка, докато списъкът с версии се зарежда.",
"Playing offline": "Игра офлайн",
"Sign in to Tailscale": "Влезте в Tailscale",
"Offline names without an account": "Офлайн имена без акаунт",
"Help make Horizon faster and steadier?": "Помогнете да направим Horizon по-бърз и по-стабилен?",
"Sign in to play": "Влезте, за да играете",
"Ported": "Пренесено",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Актуализирайте този стартер с вашия мениджър на пакети.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Затворете този стартер, преместете го в {folder} и го отворете там, за да включите актуализациите.",
"Any MCP client": "Всеки MCP клиент",
"{name}'s cape is kept.": "Пелерината на {name} е запазена.",
"Not reviewed by the Horizon registry": "Не е прегледан от регистъра на Horizon",
"Proxy": "Прокси",
"Checking": "Проверка",
"Updates": "Актуализации",
"Asking Microsoft…": "Питане на Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Подготвен за Minecraft {version}, без неговите звуци: играта ще бъде безшумна. Подгответе се отново да ги копирате от вашата инсталация на Minecraft.",
"Forget": "Забравете",
"Import a modpack…": "Импортиране на модпакет...",
"Search versions": "Търсене на версии",
"failed": "неуспешно",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Прекъснато: {line}.",
"Resource packs": "Пакети с ресурси",
"yesterday": "вчера",
"No cape": "Без наметало",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "След всяка сесия: процентили за време на кадрите и 14-кофова хистограма, времена на отметка, пикова памет и времена за стартиране, с вашата машина (ОС, процесор и неговите ядра и часовници, размер на паметта, графичен процесор, неговата памет и драйвер, тип устройство, размер на екрана и честота на опресняване, лаптоп или настолен компютър, на батерия или не) и настройките, които променят производителността.",
"Make a token": "Направете жетон",
"Added {names}: the game turns it on when the world opens.": "Добавено {names}: играта го включва, когато светът се отвори.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Споделено: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Приятели в една и съща Wi-Fi: Групова игра, Добавяне на сървър, след което поставете този адрес.",
"None yet: drop a .hshader or a shader pack .zip here.": "Все още няма: пуснете .hshader или .zip пакет от шейдъри тук.",
"Offline name · the game's own": "Офлайн име · собствено на играта",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Родните модове не са затворени: те работят с пълен достъп до вашия компютър, като всяка програма. Инсталирайте само модове, на чиито автори имате доверие. За да играете с такъв, създайте играта на страницата Mods; първата компилация изтегля Rust и отнема 20 до 30 минути.",
"Your selected version only changes if you were playing the newest one.": "Избраната от вас версия се променя само ако сте играли най-новата.",
"Multiplayer": "Мултиплейър",
@@ -589,7 +569,6 @@
"the port": "пристанището",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Източникът на {source}. Изданието му доставя {file}, модифициране на съдържание: инсталирането на тези от GitHub все още не се поддържа.",
"Build anyway": "Изградете все пак",
"A name, 3 to 16 letters": "Име, от 3 до 16 букви",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Инсталирано {mods} от GitHub ({source}). Изградете го на страницата Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Настройки, ключове, генериране на маркер за достъп. Съхранява се в ключодържателя на този компютър и се изпраща само до Tailscale.",
"{id} is up to date.": "{id} е актуален.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Прочетох го и му вярвам: инсталирай",
"Close export": "Затворете експорта",
"Playing needs a prepared Horizon version (Play page).": "Играта изисква подготвена версия на Horizon (страница за възпроизвеждане).",
"Offline, the game's name": "Офлайн, името на играта",
"From Horizon's registry": "От регистъра на Horizon",
"Sounds": "Звуци",
"Edit…": "Редактиране...",
@@ -637,12 +615,10 @@
"up to date": "актуален",
"← Newer": "← По-нови",
"Downloading from Mojang · {done} of {total} files": "Изтегляне от Mojang · {done} от {total} файла",
"{name}'s skin is kept.": "Кожата на {name} се запазва.",
"Edit instance": "Редактиране на екземпляр",
"Remove shortcut": "Премахване на пряк път",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} не е инсталиран тук (или не е в PATH): вместо това копирайте конфигурацията.",
"No worlds to put in.": "Няма светове за поставяне.",
"Default skin": "Кожа по подразбиране",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Връзка към хранилище (последната му версия), издание, разклонение или етикет или ангажимент. Стартерът инсталира един точен файл за освобождаване или ангажимент, никога клон, който се движи.",
"Sign in with GitHub to rate": "Влезте с GitHub, за да оцените",
"Star on GitHub": "Дай звезда в GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "изигран от {names}",
"{day}, {time} UTC": "{day}, {time} часа UTC",
"Microsoft account · online servers too": "Акаунт в Microsoft · и онлайн сървъри",
"Offline · single player and LAN worlds": "Офлайн · игра за един играч и LAN светове",
"Offline names": "Офлайн имена",
"Add a name": "Добавяне на име",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "От 3 до 16 букви, цифри или долни черти. Можете да сменяте името и от горната лента. Онлайн сървърите не приемат офлайн имена.",
"Play online with your Microsoft account": "Играйте онлайн с акаунта си в Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Влезте с акаунта, който притежава Minecraft: Java Edition. Името и скинът ви остават с вас и в онлайн сървърите, както в другите лаунчери.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Собствената страница на Microsoft се отваря в браузъра ви. Horizon никога не вижда паролата ви.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Pazenn goude sevel ar savadur {name}",
"In use": "En implij",
"Prepare": "Prientiñ",
"Developer options": "Dibarzhioù an diorroer",
"{online} of {max} players": "{online} eus {max} c'hoarierien",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Embannadur). Play a bellgarg anezhañ eus Mojang evit ho kont ar wech kentañ, gant ar Java en deus ezhomm.",
"Close": "Serriñ",
@@ -98,7 +97,6 @@
"From my install": "Diwar ma staliadur",
"the update failed: {error}": "c'hwitet en deus an hizivadenn : {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 eo Mesa, setu Vulkan a zibab ar gartenn all.",
"New name": "Anv nevez",
"Dark": "Teñval",
"Not now": "N'eo ket bremañ",
"Use an access token…": "Implijit un arouezenn mont e-barzh...",
@@ -115,7 +113,6 @@
"Partly": "Evit ul lodenn",
"All": "An holl",
"Instance": "Staliadur",
"Classic arms": "Divrec'h klasel",
"Versions": "Stummoù",
"Release build: slower to build, slightly faster game": "Sevel embannadur : gorrekoc'h da sevel, c'hoari un tamm buanoc'h",
"Performance build": "Savadur ar perzhded",
@@ -172,7 +169,6 @@
"about a minute left": "ur vunutenn bennak a chom",
"Cancel": "Nullañ",
"Add to {client}": "Ouzhpennañ da {client}",
"Skin…": "Kroc'hen...",
"Environment": "Endro",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Alies e labouront asambles c'hoazh. Ma c'hwit ar sevel, staliañ stummoù savet evit an hevelep Nightly.",
"Import an instance folder…": "Enporzhiañ un teuliad skouerennoù...",
@@ -184,7 +180,6 @@
"newest stable version": "stumm stabil nevesañ",
"Choose image…": "Dibabit ar skeudenn...",
"No worlds yet: they appear here once you play one.": "Bed ebet c'hoazh : dont a reont war wel amañ ur wech c'hoariet unan.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "C'hoari a ra an anvioù ezlinenn hep ur gont Microsoft a zo perc'henn war ar c'hoari. Minecraft a zeu c'hoazh eus ho staliadur hoc'h-unan.",
"crash reports beside it": "danevelloù sac'hadenn e-kichen",
"Install all": "Staliañ an holl",
"No group": "Strollad ebet",
@@ -202,7 +197,6 @@
"My instance": "Ma skouer",
"Snapshot": "Stumm arnod",
"Gallery": "Palier",
"Offline name": "Anv ezlinenn",
"Home": "Ti",
"Stopping": "O serriñ",
"MSPT · tick time": "MSPT · amzer tik",
@@ -304,8 +298,6 @@
"Patch notes": "Notennoù patch",
"Your Minecraft server, {online}.": "Ho servijer Minecraft, {online}.",
"Crash reports": "Danevelloù sac'hadenn",
"Offline name · the game's own · plays": "Anv ezlinenn · hini ar c'hoari · c'hoari",
"Slim arms": "Divrec'h moan",
"Asking GitHub about {owner}/{repo}…": "Goulenn GitHub diwar-benn {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Pellgargañ Minecraft {version} diwar Mojang · {done} eus {total} restroù",
"Could not save your choice: {error}": "N'haller ket enrollañ ho tibab : {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "gweledva Horizon. Dibabit ur skeudenn PNG, JPEG pe WebP deoc'h-c'hwi.",
"Not needed": "N'eus ket ezhomm",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "N'eus Microsoft kennaskañ ebet gant ar stumm-mañ eus al lañser (HORIZON_MSA_CLIENT_ID), neuze ne c'hell ket kregiñ gant ar c'hoari.",
"Offline name · plays": "Anv ezlinenn · c'hoari",
"Run the game through": "Lakaat ar c'hoari da vont en-dro",
"needed by another pack": "ezhomm gant ur pakad all",
"Older →": "Koshoc'h →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "N'haller ket mont en-dro {program} : {error}",
"Restart": "Adloc'hañ",
"Copied to the clipboard.": "Eilet war ar c'hlipbord.",
"Your worlds, offline names and settings stay where they are.": "Chom a ra ho bedoù, ho anvioù ezlinenn hag ho arventennoù e-lec'h m'emaint.",
"Send nothing": "Ne gas netra",
"Move to Trash": "Dilec'hiañ d'al lastez",
"Start from": "Kregiñ gant",
"Asking Mojang for its versions…": "Goulenn Mojang evit e stummoù...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Ur skin PNG 64×64 (pe 64×32) hag ur PNG cape 64×32, miret gant al lañser ha roet d'ar c'hoari pa vez c'hoariet an anv-se. Ar c'hoari a denn ar skinoù dre ziouer evit ar mare ; implijout a ra anezho ur wech ma c'hell. Ur gont Microsoft kroc'hen ha vantell : a-benn nebeut.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "C'hoari ezlinenn dindan un anv all, ha tremen eus ar varrenn uhelañ. Ar servijerioù enlinenn ne gemeront ket anvioù ezlinenn.",
"Report on Discord": "Danevell war Discord",
"Export": "Ezporzhiañ",
"Server": "Dafariad",
@@ -384,7 +372,6 @@
"No version installed yet.": "Stumm ebet staliet c'hoazh.",
"Release": "Embann",
"Verified": "Gwiriekaet",
"Choose a skin…": "Dibabit ur c'hroc'hen...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} ne c'hoari ket e modoù orin c'hoazh : sevel ar c'hoari ganto.",
"Use jars from my instance…": "Implijit podoù eus ma skouer...",
"Applications menu": "Lañser arloadoù",
@@ -408,7 +395,6 @@
"Open backups": "Digeriñ an enrolladennoù",
"The game is running: change packs in its own menus, or here once it is closed.": "Emañ ar c'hoari o vont en-dro : cheñch pakadoù en e rolloù e-unan, pe amañ ur wech serret.",
"Check now": "Gwiriit bremañ",
"Choose a cape…": "Dibabit ur vantell...",
"Save": "Enrollañ",
"Folder": "Teuliad",
"Searching…": "O klask…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Dilemel",
"When it starts": "Pa grogo",
"{name}'s skin": "kroc'hen {name}",
"Start": "Kregiñ",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "N'eus ket ezhomm da staliañ Minecraft : Horizon a bellgarg anezhañ eus Mojang evit ho kont.",
"Logs": "Marilhoù",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Ar merk-gerioù, e-keit ma vez karget ar roll embannadurioù.",
"Playing offline": "C'hoari ezlinenn",
"Sign in to Tailscale": "Kevreañ ouzh Tailscale",
"Offline names without an account": "Anvioù ezlinenn hep kont",
"Help make Horizon faster and steadier?": "Sikour da lakaat Horizon da vezañ buanoc'h ha stabiloc'h ?",
"Sign in to play": "Kevreañ evit c'hoari",
"Ported": "Portet",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Hizivait al lañser-mañ gant ho merour pakadoù.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Serrit al lañser-mañ, dilec'hit anezhañ da {folder}, ha digorit anezhañ eno evit gweredekaat an hizivadennoù.",
"Any MCP client": "Ne vern peseurt kliant MCP",
"{name}'s cape is kept.": "{name} a zo miret.",
"Not reviewed by the Horizon registry": "N'eo ket bet adwelet gant ar marilh Horizon",
"Proxy": "Proksi",
"Checking": "O gwiriañ",
"Updates": "Hizivadennoù",
"Asking Microsoft…": "Goulenn Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Prest evit Minecraft {version}, hep e sonioù : sioul e vo ar c’hoari. Prientit en-dro da eilañ anezho diwar ho staliadur Minecraft.",
"Forget": "Ankounac'haat",
"Import a modpack…": "Enporzhiañ ur pakad mod...",
"Search versions": "Klask stummoù",
"failed": "c'hwitet",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Dilezet : {line}.",
"Resource packs": "Pakadoù danvezioù",
"yesterday": "dec'h",
"No cape": "Kab ebet",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Goude pep dalc'h : dregantadoù amzer-framm hag un histogramm 14-bucket, amzerioù tikedenn, amzerioù memor uhelañ ha loc'hañ, gant ho urzhiataer (OR, CPU hag e greizennoù hag e horolajoù, ment ar memor, GPU, e vemor hag e sturier, seurt lenner, ment ar skramm hag ar feur freskaat, urzhiataer pe burev, gant pilenn pe get) hag an arventennoù a cheñch ar perzhioù.",
"Make a token": "Ober un token",
"Added {names}: the game turns it on when the world opens.": "Ouzhpennet {names} : ar c'hoari a laka anezhañ da vont en-dro pa zigor ar bed.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Rannet : {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Mignoned war ar memes Wi-Fi : Liesc'hoarier, Ouzhpennañ ur servijer, ha goude-se pegañ ar chomlec'h-mañ.",
"None yet: drop a .hshader or a shader pack .zip here.": "Hini ebet c'hoazh : lakait ur .hshader pe ur pakad skeudenner .zip amañ.",
"Offline name · the game's own": "Anv ezlinenn · hini ar c'hoari",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "N'eo ket sandboxed ar modoù orin : mont a reont en-dro gant mont e darempred gant hoc'h urzhiataer, evel kement programm all. Staliañ ar c'hemmoù a fiziit en o aozerien hepken. Evit c'hoari gant unan, sevel ar c'hoari war ar bajenn Mods ; ar sevel kentañ a bellgarg Rust hag a bad 20 pe 30 munutenn.",
"Your selected version only changes if you were playing the newest one.": "Ne cheñcho ar stumm diuzet nemet ma oac'h o c'hoari gant an hini nevesañ.",
"Multiplayer": "Liesc'hoarier",
@@ -587,7 +567,6 @@
"the port": "ar porzh |",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Mammenn {source}. E embannadur a gas {file}, ur mod endalc'had : n'eo ket skoret staliañ ar re eus GitHub c'hoazh.",
"Build anyway": "Sevel koulskoude",
"A name, 3 to 16 letters": "Un anv, 3 da 16 lizherenn",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Staliet {mods} adalek GitHub ({source}). Sevel anezhañ war ar bajenn Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Arventennoù, Alc'hwezioù, Krouiñ token mont e-barzh. Miret e vez e-barzh alc'hwezioù an urzhiataer-mañ ha kaset eo da Tailscale hepken.",
"{id} is up to date.": "{id} a zo hizivaet.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Lennet em eus anezhañ ha fiziañs am eus ennañ : staliañ",
"Close export": "Serriñ an ezporzhiañ",
"Playing needs a prepared Horizon version (Play page).": "Evit c'hoari e ranker kaout ur stumm Horizon prientet (Pajenn c'hoari).",
"Offline, the game's name": "Ezlinenn, anv ar c'hoari",
"From Horizon's registry": "Eus marilh Horizon",
"Sounds": "Sonioù",
"Edit…": "Kemmañ...",
@@ -635,12 +613,10 @@
"up to date": "hizivaet",
"← Newer": "← Nevesoc'h",
"Downloading from Mojang · {done} of {total} files": "O pellgargañ diwar Mojang · {done} eus {total} restroù",
"{name}'s skin is kept.": "Miret eo kroc'hen {name}.",
"Edit instance": "Kemmañ skouer",
"Remove shortcut": "Dilemel ar berradennoù",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} n'eo ket staliet amañ (pe n'eo ket war an HENT) : eilañ ar c'hefluniadur kentoc'h.",
"No worlds to put in.": "Bed ebet da lakaat e-barzh.",
"Default skin": "Kroc'hen dre ziouer",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Ul liamm war-du un diaz (e embannadur diwezhañ), un embannadur, ur skourr pe un dikedenn, pe un emglev. Staliañ a ra al lañser ur restr embann pe un emglev rik, biskoazh ur skourr a zilec'h.",
"Sign in with GitHub to rate": "En em lugañ gant GitHub evit priziañ",
"Star on GitHub": "Reiñ ur steredenn war GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "c'hoariet gant {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft gont · servijerioù enlinenn ivez",
"Offline · single player and LAN worlds": "Ezlinenn · c'hoarier unvan ha bedoù LAN",
"Offline names": "Anvioù ezlinenn",
"Add a name": "Ouzhpennañ un anv",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 da 16 lizherenn, sifroù pe islinennoù. Cheñch anvioù adalek ar varrenn uhelañ ivez. Ar servijerioù enlinenn ne gemeront ket anvioù ezlinenn.",
"Play online with your Microsoft account": "C'hoari enlinenn gant ho kont Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "En em lugañ gant ar gont a zo perc'henn war Minecraft: Java Embannadur. Hoc'h anv hag ho kroc'hen a zeu war servijerioù enlinenn, evel e lañserioù all.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Pajenn Microsoft e-unan a zigor en ho merdeer. Horizon ne wel ket ho ker-tremen morse.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Korak izgradnje {name} nakon izgradnje",
"In use": "U upotrebi",
"Prepare": "Pripremite se",
"Developer options": "Opcije za programere",
"{online} of {max} players": "{online} od {max} igrača",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java izdanje). Play ga preuzima sa Mojang-a za vaš nalog prvi put, sa Javom koja joj je potrebna.",
"Close": "Zatvori",
@@ -98,7 +97,6 @@
"From my install": "Iz moje instalacije",
"the update failed: {error}": "ažuriranje nije uspjelo: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesin DRI_PRIME=1, tako da Vulkan bira drugu kartu.",
"New name": "Novo ime",
"Dark": "Tamno",
"Not now": "Ne sada",
"Use an access token…": "Koristite token za pristup…",
@@ -115,7 +113,6 @@
"Partly": "Djelomično",
"All": "Sve",
"Instance": "Instanca",
"Classic arms": "Klasične ruke",
"Versions": "Verzije",
"Release build: slower to build, slightly faster game": "Izrada izdanja: sporija za izgradnju, malo brža igra",
"Performance build": "Izgradnja performansi",
@@ -172,7 +169,6 @@
"about a minute left": "još otprilike minut",
"Cancel": "Otkaži",
"Add to {client}": "Dodaj u {client}",
"Skin…": "Koža…",
"Environment": "Životna sredina",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Često i dalje rade zajedno. Ako izgradnja ne uspije, instalirajte verzije napravljene za isti Nightly.",
"Import an instance folder…": "Uvezite folder instance…",
@@ -184,7 +180,6 @@
"newest stable version": "najnovija stabilna verzija",
"Choose image…": "Odaberite sliku…",
"No worlds yet: they appear here once you play one.": "Još uvijek nema svjetova: pojavljuju se ovdje kada igrate jedan.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline imena igraju se bez Microsoft naloga koji je vlasnik igre. Minecraft i dalje dolazi iz vaše vlastite instalacije.",
"crash reports beside it": "izveštaji o padovima pored njega",
"Install all": "Instalirajte sve",
"No group": "Nema grupe",
@@ -202,7 +197,6 @@
"My instance": "Moj primer",
"Snapshot": "Snapshot verzija",
"Gallery": "Galerija",
"Offline name": "Ime van mreže",
"Home": "Dom",
"Stopping": "Zaustavljanje",
"MSPT · tick time": "MSPT · vrijeme tika",
@@ -304,8 +298,6 @@
"Patch notes": "Bilješke o zakrpama",
"Your Minecraft server, {online}.": "Vaš Minecraft server, {online}.",
"Crash reports": "Izvještaji o padu",
"Offline name · the game's own · plays": "Offline ime · igra vlastito · igra",
"Slim arms": "Tanke ruke",
"Asking GitHub about {owner}/{repo}…": "Pitam GitHub o {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Preuzimanje Minecrafta {version} iz Mojanga · {done} od {total} fajlova",
"Could not save your choice: {error}": "Nije moguće sačuvati vaš izbor: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "pejzaž Horizon. Odaberite svoju sliku u PNG, JPEG ili WebP formatu.",
"Not needed": "Nije potrebno",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Ova verzija pokretača nema Microsoft prijavu (HORIZON_MSA_CLIENT_ID), tako da ne može pokrenuti igru.",
"Offline name · plays": "Vanmrežno ime · reprod",
"Run the game through": "Provedite igru",
"needed by another pack": "potreban drugom paketu",
"Older →": "Stariji →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Nije moguće pokrenuti {program}: {error}",
"Restart": "Ponovo pokreni",
"Copied to the clipboard.": "Kopirano u međuspremnik.",
"Your worlds, offline names and settings stay where they are.": "Vaši svjetovi, vanmrežna imena i postavke ostaju tamo gdje jesu.",
"Send nothing": "Ne šalji ništa",
"Move to Trash": "Premjesti u Otpad",
"Start from": "Počni od",
"Asking Mojang for its versions…": "Pitajući Mojang za njegove verzije…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (ili 64×32) skin PNG i 64×32 ogrtač PNG, koje čuva pokretač i daje igri kada se ovo ime igra. Igra za sada crta zadane skinove; koristi ih kad god može. Koža i ogrtač Microsoft naloga: uskoro.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Igrajte van mreže pod drugim imenom i prebacite se s gornje trake. Online serveri ne preuzimaju offline imena.",
"Report on Discord": "Izvještaj o Discordu",
"Export": "Izvoz",
"Server": "Server",
@@ -384,7 +372,6 @@
"No version installed yet.": "Još nije instalirana verzija.",
"Release": "Izdanje",
"Verified": "Provjereno",
"Choose a skin…": "Odaberite kožu…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} još ne igra svoje izvorne modove: izgradite igru s njima.",
"Use jars from my instance…": "Koristite tegle iz mog primjera…",
"Applications menu": "Meni aplikacija",
@@ -408,7 +395,6 @@
"Open backups": "Otvorite sigurnosne kopije",
"The game is running: change packs in its own menus, or here once it is closed.": "Igra je pokrenuta: promijenite pakete u vlastitim menijima ili ovdje kada se zatvori.",
"Check now": "Provjerite sada",
"Choose a cape…": "Odaberite ogrtač…",
"Save": "Sačuvaj",
"Folder": "Folder",
"Searching…": "Pretraživanje…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Odjavi se",
"When it starts": "Kada počne",
"{name}'s skin": "skin {name}",
"Start": "Počni",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft instalacija nije potrebna: Horizon preuzima ga sa Mojanga za vaš nalog.",
"Logs": "Dnevnici",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Riječni znak, dok se lista izdanja učitava.",
"Playing offline": "Igranje van mreže",
"Sign in to Tailscale": "Prijavite se na Tailscale",
"Offline names without an account": "Offline imena bez naloga",
"Help make Horizon faster and steadier?": "Pomozite da Horizon bude brži i stabilniji?",
"Sign in to play": "Prijavite se da igrate",
"Ported": "Preneseno",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Ažurirajte ovaj pokretač pomoću svog upravitelja paketa.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Zatvorite ovaj pokretač, premjestite ga u {folder} i otvorite ga tamo da biste omogućili ažuriranja.",
"Any MCP client": "Bilo koji MCP klijent",
"{name}'s cape is kept.": "{name} ogrtač je zadržan.",
"Not reviewed by the Horizon registry": "Nije pregledan od strane Horizon registra",
"Proxy": "Proxy",
"Checking": "Provjeravam",
"Updates": "Ažuriranja",
"Asking Microsoft…": "Pitam Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Pripremljeno za Minecraft {version}, bez zvukova: igra će biti tiha. Pripremite se ponovo da ih kopirate iz svoje Minecraft instalacije.",
"Forget": "Zaboravi",
"Import a modpack…": "Uvezite modpack…",
"Search versions": "Pretražite verzije",
"failed": "nije uspjelo",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Zaustavljeno: {line}.",
"Resource packs": "Paketi resursa",
"yesterday": "juče",
"No cape": "Bez ogrtača",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Nakon svake sesije: procentili vremena kadra i histogram od 14 kantica, vremena otkucaja, vršna memorija i vremena pokretanja, sa vašom mašinom (OS, CPU i njegove jezgre i taktovi, veličina memorije, GPU, njegova memorija i drajver, tip pogona, veličina ekrana i brzina osvježavanja, laptop ili desktop, na bateriji ili ne) i postavkama koje mijenjaju performanse.",
"Make a token": "Napravite žeton",
"Added {names}: the game turns it on when the world opens.": "Dodano {names}: igra se uključuje kada se svijet otvori.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Podijeljeno: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Prijatelji na istoj Wi-Fi mreži: Multiplayer, Add Server, a zatim zalijepite ovu adresu.",
"None yet: drop a .hshader or a shader pack .zip here.": "Još ništa: ovdje ispustite .hshader ili paket shadera .zip.",
"Offline name · the game's own": "Offline naziv · igra je vlastita",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Izvorni modovi nisu zaštićeni: oni rade sa punim pristupom vašem računaru, kao i svaki program. Instalirajte samo modove čijim autorima vjerujete. Da biste igrali s jednim, napravite igru na stranici Mods; prva verzija preuzima Rust i traje 20 do 30 minuta.",
"Your selected version only changes if you were playing the newest one.": "Vaša odabrana verzija se mijenja samo ako ste igrali najnoviju.",
"Multiplayer": "Više igrača",
@@ -587,7 +567,6 @@
"the port": "luka",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Izvor {source}. Njegovo izdanje isporučuje {file}, mod za sadržaj: instaliranje onih sa GitHub-a još nije podržano.",
"Build anyway": "Ipak izgradite",
"A name, 3 to 16 letters": "Ime, od 3 do 16 slova",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Instalirano {mods} sa GitHub-a ({source}). Napravite ga na stranici Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Postavke, Ključevi, Generiraj pristupni token. Čuva se u privjesku za ključeve ovog računara i šalje se samo u Tailscale.",
"{id} is up to date.": "{id} je ažuriran.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Pročitao sam ga i vjerujem mu: instalirajte",
"Close export": "Zatvori izvoz",
"Playing needs a prepared Horizon version (Play page).": "Za igranje je potrebna pripremljena Horizon verzija (stranica za igranje).",
"Offline, the game's name": "Offline, ime igre",
"From Horizon's registry": "Iz registra Horizon",
"Sounds": "Zvuci",
"Edit…": "Uredi…",
@@ -635,12 +613,10 @@
"up to date": "ažurno",
"← Newer": "← Novije",
"Downloading from Mojang · {done} of {total} files": "Preuzimanje sa Mojanga · {done} od {total} fajlova",
"{name}'s skin is kept.": "Koža {name} je zadržana.",
"Edit instance": "Uredi instancu",
"Remove shortcut": "Uklonite prečicu",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} nije instaliran ovdje (ili nije na PATH): umjesto toga kopirajte konfiguraciju.",
"No worlds to put in.": "Nema svjetova za ubacivanje.",
"Default skin": "Podrazumijevana koža",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Veza na spremište (njegovo najnovije izdanje), izdanje, granu ili oznaku ili urezivanje. Pokretač instalira jednu tačnu datoteku izdanja ili urezivanje, nikada granu koja se pomiče.",
"Sign in with GitHub to rate": "Prijavite se na GitHub da biste ocijenili",
"Star on GitHub": "Daj zvjezdicu na GitHubu",
@@ -1053,10 +1029,6 @@
"played by {names}": "igra {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft nalog · i serveri na mreži",
"Offline · single player and LAN worlds": "Offline · Svijet za jednog igrača i LAN",
"Offline names": "Offline imena",
"Add a name": "Dodajte ime",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 do 16 slova, brojeva ili donjih crta. Promijenite imena također sa gornje trake. Online serveri ne preuzimaju offline imena.",
"Play online with your Microsoft account": "Igrajte na mreži sa svojim Microsoft nalogom",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Prijavite se sa nalogom koji poseduje Minecraft: Java Edition. Vaše ime i koža dolaze na mrežne servere, kao u drugim lanserima.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsoftova vlastita stranica se otvara u vašem pretraživaču. Horizon nikada ne vidi vašu lozinku.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Creació del pas posterior a la creació de {name}",
"In use": "En ús",
"Prepare": "Prepara't",
"Developer options": "Opcions de desenvolupador",
"{online} of {max} players": "{online} de {max} jugadors",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (edició Java). Play el descarrega de Mojang per al teu compte la primera vegada, amb el Java que necessita.",
"Close": "Tancar",
@@ -98,7 +97,6 @@
"From my install": "De la meva instal·lació",
"the update failed: {error}": "l'actualització ha fallat: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 de Mesa, de manera que Vulkan tria l'altra carta.",
"New name": "Nou nom",
"Dark": "Fosc",
"Not now": "Ara no",
"Use an access token…": "Utilitza un testimoni d'accés...",
@@ -115,7 +113,6 @@
"Partly": "En part",
"All": "Tots",
"Instance": "Instància",
"Classic arms": "Braços clàssics",
"Versions": "Versions",
"Release build: slower to build, slightly faster game": "Construcció de llançament: joc més lent de construcció i una mica més ràpid",
"Performance build": "Construcció de rendiment",
@@ -172,7 +169,6 @@
"about a minute left": "queda aproximadament un minut",
"Cancel": "Cancel·la",
"Add to {client}": "Afegeix a {client}",
"Skin…": "Pell…",
"Environment": "Medi ambient",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Sovint encara treballen junts. Si la compilació falla, instal·leu versions fetes per al mateix Nightly.",
"Import an instance folder…": "Importa una carpeta d'instància...",
@@ -184,7 +180,6 @@
"newest stable version": "versió estable més recent",
"Choose image…": "Tria la imatge...",
"No worlds yet: they appear here once you play one.": "Encara no hi ha mons: apareixen aquí quan en jugueu un.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Els noms fora de línia juguen sense un compte de Microsoft propietari del joc. Minecraft encara prové de la teva pròpia instal·lació.",
"crash reports beside it": "informes de fallades al costat",
"Install all": "Instal·leu-ho tot",
"No group": "Cap grup",
@@ -202,7 +197,6 @@
"My instance": "La meva instància",
"Snapshot": "Instantània",
"Gallery": "Galeria",
"Offline name": "Nom fora de línia",
"Home": "a casa",
"Stopping": "Aturant",
"MSPT · tick time": "MSPT · temps per tick",
@@ -304,8 +298,6 @@
"Patch notes": "Notes del pedaç",
"Your Minecraft server, {online}.": "El teu servidor de Minecraft, {online}.",
"Crash reports": "Informes de fallades",
"Offline name · the game's own · plays": "Nom fora de línia · jugades pròpies del joc",
"Slim arms": "Braços prims",
"Asking GitHub about {owner}/{repo}…": "Preguntant a GitHub sobre {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Baixant Minecraft {version} de Mojang · {done} de {total} fitxers",
"Could not save your choice: {error}": "No s'ha pogut desar la teva elecció: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "El paisatge d'Horizon. Tria una imatge PNG, JPEG o WebP pròpia.",
"Not needed": "No cal",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Aquesta versió del llançador no té cap inici de sessió de Microsoft (HORIZON_MSA_CLIENT_ID), de manera que no pot iniciar el joc.",
"Offline name · plays": "Nom fora de línia · juga",
"Run the game through": "Executeu el joc",
"needed by another pack": "necessari per un altre paquet",
"Older →": "Més vell →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "No s'ha pogut executar {program}: {error}",
"Restart": "Reinicieu",
"Copied to the clipboard.": "S'ha copiat al porta-retalls.",
"Your worlds, offline names and settings stay where they are.": "Els vostres mons, noms fora de línia i configuració es mantenen on són.",
"Send nothing": "No envieu res",
"Move to Trash": "Mou a la paperera",
"Start from": "Comença des de",
"Asking Mojang for its versions…": "Demanant a Mojang les seves versions...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Una pell PNG de 64×64 (o 64×32) i una capa PNG de 64×32, conservada pel llançador i donada al joc quan es juga aquest nom. El joc dibuixa els aspectes predeterminats de moment; els fa servir una vegada que pot. La pell i la capa d'un compte de Microsoft: properament.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Juga fora de línia amb un altre nom i canvia des de la barra superior. Els servidors en línia no prenen noms fora de línia.",
"Report on Discord": "Informe sobre Discord",
"Export": "Exporta",
"Server": "Servidor",
@@ -384,7 +372,6 @@
"No version installed yet.": "Encara no hi ha cap versió instal·lada.",
"Release": "Versió estable",
"Verified": "Verificat",
"Choose a skin…": "Tria una pell...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} encara no juga als seus mods natius: crea el joc amb ells.",
"Use jars from my instance…": "Utilitzeu pots de la meva instància...",
"Applications menu": "Menú d'aplicacions",
@@ -408,7 +395,6 @@
"Open backups": "Obre còpies de seguretat",
"The game is running: change packs in its own menus, or here once it is closed.": "El joc s'està executant: canvieu els paquets als seus propis menús, o aquí un cop estigui tancat.",
"Check now": "Comproveu ara",
"Choose a cape…": "Tria una capa...",
"Save": "Desa",
"Folder": "Carpeta",
"Searching…": "S'està cercant…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Tanca la sessió",
"When it starts": "Quan comença",
"{name}'s skin": "la pell de {name}",
"Start": "Comença",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "No cal instal·lar Minecraft: Horizon el descarrega des de Mojang per al vostre compte.",
"Logs": "Registres",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "La paraula marca, mentre es carrega la llista de llançaments.",
"Playing offline": "Jugant fora de línia",
"Sign in to Tailscale": "Inicieu la sessió a Tailscale",
"Offline names without an account": "Noms fora de línia sense un compte",
"Help make Horizon faster and steadier?": "Ajudeu a fer que Horizon sigui més ràpid i estable?",
"Sign in to play": "Inicia sessió per jugar",
"Ported": "Portat",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Actualitza aquest llançador amb el teu gestor de paquets.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Tanca aquest llançador, mou-lo a {folder} i obre'l allà per habilitar les actualitzacions.",
"Any MCP client": "Qualsevol client MCP",
"{name}'s cape is kept.": "Es manté la capa de {name}.",
"Not reviewed by the Horizon registry": "No revisat pel registre d'Horizon",
"Proxy": "Proxy",
"Checking": "Comprovació",
"Updates": "Actualitzacions",
"Asking Microsoft…": "Preguntant a Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Preparat per a Minecraft {version}, sense els seus sons: el joc estarà en silenci. Prepareu-vos de nou per copiar-los de la vostra instal·lació de Minecraft.",
"Forget": "Oblida't",
"Import a modpack…": "Importa un modpack...",
"Search versions": "Cerca versions",
"failed": "fracassat",
@@ -504,7 +486,6 @@
"Left off: {line}.": "S'ha deixat: {line}.",
"Resource packs": "Paquets de recursos",
"yesterday": "ahir",
"No cape": "Sense capa",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Després de cada sessió: percentils de temps de fotograma i un histograma de 14 dipòsits, temps de tick, memòria màxima i temps d'inici, amb la vostra màquina (SO, CPU i els seus nuclis i rellotges, mida de memòria, GPU, la seva memòria i controlador, tipus de unitat, mida de pantalla i freqüència d'actualització, portàtil o escriptori, amb bateria o no) i la configuració que canvia el rendiment.",
"Make a token": "Fes un testimoni",
"Added {names}: the game turns it on when the world opens.": "S'ha afegit {names}: el joc l'encén quan s'obre el món.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Compartit: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Amics a la mateixa xarxa Wi-Fi: Multijugador, Afegeix servidor i enganxeu aquesta adreça.",
"None yet: drop a .hshader or a shader pack .zip here.": "Cap encara: deixeu anar un .hshader o un paquet de shader .zip aquí.",
"Offline name · the game's own": "Nom fora de línia · el propi del joc",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Les modificacions natives no són sandbox: s'executen amb accés complet al vostre ordinador, com qualsevol programa. Instal·leu només modificacions en els autors dels quals confieu. Per jugar amb un, crea el joc a la pàgina Mods; la primera versió descarrega Rust i triga entre 20 i 30 minuts.",
"Your selected version only changes if you were playing the newest one.": "La versió seleccionada només canvia si estàveu jugant a la més nova.",
"Multiplayer": "Multijugador",
@@ -587,7 +567,6 @@
"the port": "el port",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "La font de {source}. El seu llançament inclou {file}, un mod de contingut: la instal·lació de GitHub encara no és compatible.",
"Build anyway": "Construeix de totes maneres",
"A name, 3 to 16 letters": "Un nom, de 3 a 16 lletres",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "S'ha instal·lat {mods} des de GitHub ({source}). Creeu-lo a la pàgina de modificacions.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Configuració, claus, generar testimoni d'accés. Es guarda al clauer d'aquest ordinador i només s'envia a Tailscale.",
"{id} is up to date.": "{id} està actualitzat.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Ho llegeixo i hi confio: instal·lar",
"Close export": "Tanca l'exportació",
"Playing needs a prepared Horizon version (Play page).": "Per jugar necessita una versió d'Horizon preparada (pàgina de reproducció).",
"Offline, the game's name": "Fora de línia, el nom del joc",
"From Horizon's registry": "Del registre d'Horizon",
"Sounds": "Sons",
"Edit…": "Edita...",
@@ -635,12 +613,10 @@
"up to date": "al dia",
"← Newer": "← Més recent",
"Downloading from Mojang · {done} of {total} files": "Descàrrega de Mojang · {done} de {total} fitxers",
"{name}'s skin is kept.": "La pell de {name} es manté.",
"Edit instance": "Edita la instància",
"Remove shortcut": "Elimina la drecera",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} no està instal·lat aquí (o no al PATH): copieu la configuració.",
"No worlds to put in.": "No hi ha mons per posar-hi.",
"Default skin": "Aspecte per defecte",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Un enllaç a un repositori (la seva darrera versió), una versió, una branca o etiqueta o una confirmació. El llançador instal·la un fitxer de llançament o commit exacte, mai una branca que es mou.",
"Sign in with GitHub to rate": "Inicia la sessió amb GitHub per puntuar",
"Star on GitHub": "Dona una estrella a GitHub",
@@ -1055,9 +1031,7 @@
"1 hour": "1 hora",
"1 hour ago": "fa 1 hora",
"1 line": "1 línia",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "De 3 a 16 lletres, números o guions baixos. També pots canviar de nom des de la barra superior. Els servidors en línia no accepten noms fora de línia.",
"Accent colour, glass, blur, language and the options above go back to how Horizon ships.": "El color d'accent, el vidre, el desenfocament, la llengua i les opcions de dalt tornen als valors amb què ve Horizon.",
"Add a name": "Afegeix un nom",
"Colours the buttons, the switches and the sky. Pick one, or type any hex colour.": "Acoloreix els botons, els interruptors i el cel. Tria'n un o escriu qualsevol color hexadecimal.",
"Copied the picture": "S'ha copiat la imatge",
"Copied {text}": "S'ha copiat {text}",
@@ -1084,8 +1058,6 @@
"Native mods": "Mods natius",
"Nightly": "Nocturna",
"Nothing matches “{query}”.": "Res no coincideix amb «{query}».",
"Offline names": "Noms fora de línia",
"Offline · single player and LAN worlds": "Fora de línia · un jugador i mons LAN",
"Open the game folder": "Obre la carpeta del joc",
"Open {page}": "Obre {page}",
"Opened {path}": "S'ha obert {path}",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Krok sestavení {name} po sestavení",
"In use": "Používá se",
"Prepare": "Připravit",
"Developer options": "Možnosti vývojáře",
"{online} of {max} players": "{online} z {max} hráčů",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). Play si ji poprvé stáhne z Mojangu pro váš účet s Javou, kterou potřebuje.",
"Close": "Zavřít",
@@ -98,7 +97,6 @@
"From my install": "Z mé instalace",
"the update failed: {error}": "aktualizace se nezdařila: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesa má DRI_PRIME=1, takže Vulkan vybere jinou kartu.",
"New name": "Nové jméno",
"Dark": "Tmavý",
"Not now": "Teď ne",
"Use an access token…": "Použijte přístupový token…",
@@ -115,7 +113,6 @@
"Partly": "Částečně",
"All": "Vše",
"Instance": "Instance",
"Classic arms": "Klasické paže",
"Versions": "Verze",
"Release build: slower to build, slightly faster game": "Sestavení vydání: pomalejší sestavení, o něco rychlejší hra",
"Performance build": "Sestavení výkonu",
@@ -172,7 +169,6 @@
"about a minute left": "zbývá asi minuta",
"Cancel": "Zrušit",
"Add to {client}": "Přidat do {client}",
"Skin…": "Vzhled…",
"Environment": "Životní prostředí",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Často spolu stále spolupracují. Pokud sestavení selže, nainstalujte verze vytvořené pro stejný Nightly.",
"Import an instance folder…": "Importovat složku instance…",
@@ -184,7 +180,6 @@
"newest stable version": "nejnovější stabilní verze",
"Choose image…": "Vyberte obrázek…",
"No worlds yet: they appear here once you play one.": "Zatím žádné světy: objeví se zde, jakmile nějaký zahrajete.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline jména hrají bez účtu Microsoft, který hru vlastní. Minecraft stále pochází z vaší vlastní instalace.",
"crash reports beside it": "zprávy o havárii vedle ní",
"Install all": "Nainstalujte vše",
"No group": "Žádná skupina",
@@ -202,7 +197,6 @@
"My instance": "Moje instance",
"Snapshot": "Snímek",
"Gallery": "Galerie",
"Offline name": "Offline jméno",
"Home": "Domů",
"Stopping": "Zastavení",
"MSPT · tick time": "MSPT · čas tikání",
@@ -305,8 +299,6 @@
"Patch notes": "Poznámky k záplatám",
"Your Minecraft server, {online}.": "Váš Minecraft server, {online}.",
"Crash reports": "Zprávy o pádu",
"Offline name · the game's own · plays": "Offline název · vlastní hra · hraje",
"Slim arms": "Štíhlé paže",
"Asking GitHub about {owner}/{repo}…": "Ptát se GitHubu na {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Stahování Minecraft {version} od Mojangu · {done} z {total} souborů",
"Could not save your choice: {error}": "Vaši volbu nelze uložit: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Krajina Horizonu. Vyberte si vlastní obrázek PNG, JPEG nebo WebP.",
"Not needed": "Není potřeba",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Toto sestavení spouštěče nemá žádné přihlášení k Microsoftu (HORIZON_MSA_CLIENT_ID), takže nemůže spustit hru.",
"Offline name · plays": "Název offline · přehraje",
"Run the game through": "Spustit hru přes",
"needed by another pack": "potřebuje další balíček",
"Older →": "Starší →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "Nelze spustit {program}: {error}",
"Restart": "Restartovat",
"Copied to the clipboard.": "Zkopírováno do schránky.",
"Your worlds, offline names and settings stay where they are.": "Vaše světy, offline názvy a nastavení zůstanou tam, kde jsou.",
"Send nothing": "Neposílejte nic",
"Move to Trash": "Přesunout do koše",
"Start from": "Začít od",
"Asking Mojang for its versions…": "Ptát se Mojangu na jeho verze…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (nebo 64×32) skin PNG a 64×32 plášť PNG, které si ponechal spouštěč a které se do hry přidávají při hraní tohoto jména. Hra zatím kreslí výchozí vzhledy; jakmile to bude možné, použije je. Vzhled a plášť účtu Microsoft: již brzy.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Hrajte offline pod jiným jménem a přepněte z horní lišty. Online servery neberou názvy offline.",
"Report on Discord": "Zpráva o Discordu",
"Export": "Exportovat",
"Server": "Server",
@@ -385,7 +373,6 @@
"No version installed yet.": "Zatím není nainstalována žádná verze.",
"Release": "Vydání",
"Verified": "Ověřeno",
"Choose a skin…": "Vyberte si skin…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} zatím nehraje své nativní mody: sestavte hru s nimi.",
"Use jars from my instance…": "Použijte JAR soubory z mé instance…",
"Applications menu": "Nabídka aplikací",
@@ -409,7 +396,6 @@
"Open backups": "Otevřít zálohy",
"The game is running: change packs in its own menus, or here once it is closed.": "Hra běží: vyměňte balíčky ve vlastních nabídkách nebo zde, jakmile je zavřena.",
"Check now": "Zkontrolovat nyní",
"Choose a cape…": "Vyberte si plášť…",
"Save": "Uložit",
"Folder": "Složka",
"Searching…": "Vyhledávání…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Odhlaste se",
"When it starts": "Když to začne",
"{name}'s skin": "Kůže {name}",
"Start": "Spustit",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Není potřeba žádná instalace Minecraftu: Horizon si jej stáhne z Mojangu pro váš účet.",
"Logs": "Protokoly",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Slovní značka, zatímco se načítá seznam vydání.",
"Playing offline": "Hraní offline",
"Sign in to Tailscale": "Přihlaste se do Tailscale",
"Offline names without an account": "Offline jména bez účtu",
"Help make Horizon faster and steadier?": "Pomůžete udělat Horizon rychlejší a stabilnější?",
"Sign in to play": "Chcete-li hrát, přihlaste se",
"Ported": "Přeneseno",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Aktualizujte tento launcher pomocí správce balíčků.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Pro zapnutí aktualizací zavřete tento launcher, přesuňte jej do {folder} a tam jej znovu otevřete.",
"Any MCP client": "Jakýkoli klient MCP",
"{name}'s cape is kept.": "{name} plášť je zachován.",
"Not reviewed by the Horizon registry": "Nekontrolováno registrem Horizon",
"Proxy": "Proxy",
"Checking": "Kontrola",
"Updates": "Aktualizace",
"Asking Microsoft…": "Dotaz Microsoftu…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Připraveno pro Minecraft {version}, bez jeho zvuků: hra bude tichá. Znovu se připravte na jejich zkopírování z instalace Minecraftu.",
"Forget": "Zapomenout",
"Import a modpack…": "Importujte modpack…",
"Search versions": "Hledat verze",
"failed": "nepodařilo",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Vlevo: {line}.",
"Resource packs": "Balíčky zdrojů",
"yesterday": "včera",
"No cape": "Bez pláštěnky",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Po každé relaci: percentily frame-time a 14-segmentový histogram, časy ticků, špičková paměť a časy spuštění, s vaším počítačem (OS, CPU a jeho jádra a takty, velikost paměti, GPU, jeho paměť a ovladač, typ disku, velikost obrazovky a obnovovací frekvence, notebook nebo stolní počítač, na baterii nebo bez) a nastavení, která mění výkon.",
"Make a token": "Udělejte si žeton",
"Added {names}: the game turns it on when the world opens.": "Přidáno {names}: hra se zapne, když se otevře svět.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Sdíleno: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Přátelé na stejné Wi-Fi: Hra pro více hráčů, Přidat server a poté vložte tuto adresu.",
"None yet: drop a .hshader or a shader pack .zip here.": "Zatím žádné: sem pusťte soubor .hshader nebo shader pack .zip.",
"Offline name · the game's own": "Název offline · vlastní hra",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Nativní mody nejsou v sandboxu: běží s plným přístupem k vašemu počítači, jako každý program. Instalujte pouze mody, jejichž autorům důvěřujete. Chcete-li hrát s jedním, vytvořte hru na stránce Mods; první sestavení stáhne Rust a trvá 20 až 30 minut.",
"Your selected version only changes if you were playing the newest one.": "Vámi vybraná verze se změní pouze v případě, že jste hráli nejnovější verzi.",
"Multiplayer": "Multiplayer",
@@ -589,7 +569,6 @@
"the port": "port",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Zdroj {source}. Jeho vydání se dodává {file}, modifikace obsahu: instalace těch z GitHubu zatím není podporována.",
"Build anyway": "Přesto sestavit",
"A name, 3 to 16 letters": "Jméno, 3 až 16 písmen",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Nainstalováno {mods} z GitHubu ({source}). Vytvořte jej na stránce Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Nastavení, Klíče, Generovat přístupový token. Je uložen v klíčence tohoto počítače a odeslán pouze do Tailscale.",
"{id} is up to date.": "{id} je aktuální.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Četl jsem to a věřím tomu: nainstalovat",
"Close export": "Zavřít export",
"Playing needs a prepared Horizon version (Play page).": "Hraní vyžaduje připravenou verzi Horizon (stránka Play).",
"Offline, the game's name": "Offline, název hry",
"From Horizon's registry": "Z registru Horizonu",
"Sounds": "Zvuky",
"Edit…": "Upravit…",
@@ -637,12 +615,10 @@
"up to date": "aktuální",
"← Newer": "← Novější",
"Downloading from Mojang · {done} of {total} files": "Stahování od Mojangu · {done} z {total} souborů",
"{name}'s skin is kept.": "Kůže {name} je zachována.",
"Edit instance": "Upravit instanci",
"Remove shortcut": "Odebrat zástupce",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} zde není nainstalováno (nebo není na PATH): místo toho zkopírujte konfiguraci.",
"No worlds to put in.": "Žádné světy k vložení.",
"Default skin": "Výchozí vzhled",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Odkaz na úložiště (jeho nejnovější vydání), vydání, větev nebo značku nebo commit. Spouštěč nainstaluje přesně jeden soubor vydání nebo commit, nikdy se nepohybuje větev.",
"Sign in with GitHub to rate": "Chcete-li hodnotit, přihlaste se pomocí GitHubu",
"Star on GitHub": "Dát hvězdu na GitHubu",
@@ -1055,10 +1031,6 @@
"played by {names}": "hraje {names}",
"{day}, {time} UTC": "{day} v {time} UTC",
"Microsoft account · online servers too": "Účet Microsoft · i online servery",
"Offline · single player and LAN worlds": "Offline · hra pro jednoho hráče a světy v LAN",
"Offline names": "Offline jména",
"Add a name": "Přidat jméno",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 až 16 písmen, číslic nebo podtržítek. Jméno můžete přepnout i v horní liště. Online servery offline jména nepřijímají.",
"Play online with your Microsoft account": "Hrajte online se svým účtem Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Přihlaste se účtem, který vlastní Minecraft: Java Edition. Vaše jméno a skin vás doprovázejí na online servery, stejně jako v jiných launcherech.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Vlastní stránka Microsoftu se otevře ve vašem prohlížeči. Horizon vaše heslo nikdy nevidí.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Ҫурт {name} тунӑ хыҫҫӑнхи утӑм",
"In use": "Усӑ курать",
"Prepare": "Хатӗрленӗр",
"Developer options": "Разработчик опцийӗсем",
"{online} of {max} players": "{online} {max} вылякансенчен",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Издание). Play ӑна сирӗн аккаунт валли пӗрремӗш хут Mojang-ран скачать тӑвать, ӑна кирлӗ Java-па.",
"Close": "Хуп",
@@ -98,7 +97,6 @@
"From my install": "Манӑн установкӑран",
"the update failed: {error}": "ҫӗнетӳ ӑнӑҫсӑр пулнӑ: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Меса DRI_PRIME=1, ҫавӑнпа та Vulkan тепӗр карттӑна суйласа илет.",
"New name": "Çӗнӗ ят",
"Dark": "Тӗттӗм",
"Not now": "Халӗ мар",
"Use an access token…": "Кӗмелли маркерпа усӑ курӑр...",
@@ -115,7 +113,6 @@
"Partly": "Пӗр пайӗпе",
"All": "Пурте",
"Instance": "Инстанци",
"Classic arms": "Классика хӗҫпӑшалӗсем",
"Versions": "Версисем",
"Release build: slower to build, slightly faster game": "Релиз строительстви: ерипенрех строительство, кӑштах хӑвӑртрах вӑйӑ",
"Performance build": "Ӗҫ тухӑҫлӑхӗн строительстви",
@@ -172,7 +169,6 @@
"about a minute left": "минута яхӑн юлчӗ",
"Cancel": "Пӑрахӑҫла",
"Add to {client}": "{client} ҫине хушӑр",
"Skin…": "Скин…",
"Environment": "Тавралӑх",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Чылай чухне вӗсем халӗ те пӗрле ӗҫлеҫҫӗ. Енчен те сборка ӑнӑҫсӑр пулсан, ҫав Nightly валли тунӑ версисене вырнаҫтарӑр.",
"Import an instance folder…": "Экземпляр папкине импортла...",
@@ -184,7 +180,6 @@
"newest stable version": "чи ҫӗнӗ стабильлӗ верси",
"Choose image…": "Сӑнӳкерчӗке суйласа илӗр...",
"No worlds yet: they appear here once you play one.": "Тӗнчесем ҫук-ха: вӗсем кунта пӗрре вылясан курӑнаҫҫӗ.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Офлайн ятсем вӑйӑ хуҫи Microsoft аккаунтсӑр выляҫҫӗ. Minecraft ҫаплах сирӗн хӑвӑрӑн установкӑран килет.",
"crash reports beside it": "унпа юнашар авари ҫинчен пӗлтернисем",
"Install all": "Пурне те вырнаҫтар",
"No group": "Ушкӑн ҫук",
@@ -202,7 +197,6 @@
"My instance": "Манӑн тӗслӗх",
"Snapshot": "Снапшот",
"Gallery": "Галерея",
"Offline name": "Офлайн ят",
"Home": "Килте",
"Stopping": "Чарӑнни",
"MSPT · tick time": "MSPT · тик вӑхӑчӗ",
@@ -304,8 +298,6 @@
"Patch notes": "Патч заметки",
"Your Minecraft server, {online}.": "Сирӗн Minecraft сервер, {online}.",
"Crash reports": "Авари ҫинчен пӗлтернисем",
"Offline name · the game's own · plays": "Офлайн ят · вӑйӑ хӑйӗн · вылять",
"Slim arms": "Ҫинҫе алӑсем",
"Asking GitHub about {owner}/{repo}…": "GitHub ҫинчен {owner}/{repo} ҫинчен ыйтатӑп...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Minecraft {version} из Mojang · {done} из {total} файлов",
"Could not save your choice: {error}": "Суйласа илнине упраса хӑвараймарӑмӑр: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizon пейзажӗ. Хӑвӑрӑн PNG, JPEG е WebP ӳкерчӗке суйласа илӗр.",
"Not needed": "Кирлӗ мар",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Ку лаунчерӑн Microsoft логин ҫук (HORIZON_MSA_CLIENT_ID), ҫавӑнпа та вӑл вӑййа пуҫлаймасть.",
"Offline name · plays": "Офлайн ят · вылять",
"Run the game through": "Вӑййа вӗҫне ҫитермелле",
"needed by another pack": "тепӗр ушкӑна кирлӗ",
"Older →": "Ватӑрах →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Чупма май килмерӗ {program}: {error}",
"Restart": "Ҫӗнӗрен пуҫла",
"Copied to the clipboard.": "Буфера копиленӗ.",
"Your worlds, offline names and settings stay where they are.": "Сирӗн тӗнчесем, офлайн ятсем тата настройкӑсем хӑйсем ӑҫта пулнӑ, ҫавӑнтах юлаҫҫӗ.",
"Send nothing": "Нимӗн те ан ярӑр",
"Move to Trash": "Ҫӳп-ҫап ҫине куҫар",
"Start from": "Пуҫласа",
"Asking Mojang for its versions…": "Унӑн версийӗсемшӗн Mojang ыйтатӑп...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (е 64×32) тир PNG тата 64×32 плащ PNG, вӗсене пускавҫӑ тытса тӑрать тата ҫак ят вылянӑ чухне вӑййа парать. Вӑйӑ хальлӗхе стандартлӑ тирсене ӳкерет; вӑл ҫаксемпе пӗрре усӑ курать. Microsoft аккаунтӑн тирӗпе плащӗ: часах пулать.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Офлайн урӑх ятпа выляса илӗр те ҫӳлти йӗртен куҫӑр. Интернетри серверсем офлайн ятсене йышӑнмаҫҫӗ.",
"Report on Discord": "Отчет на Discord",
"Export": "Экспорт",
"Server": "Сервер",
@@ -384,7 +372,6 @@
"No version installed yet.": "Хальлӗхе верси лартман-ха.",
"Release": "Релиз",
"Verified": "Тӗрӗсленӗ",
"Choose a skin…": "Тир суйласа илӗр...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} хӑйӗн тӑван модӗсемпе вылямасть-ха: вӗсемпе вӑйӑ тӑвӑр.",
"Use jars from my instance…": "Манӑн экземплярти банкӑсемпе усӑ курӑр...",
"Applications menu": "Приложенисен меню",
@@ -408,7 +395,6 @@
"Open backups": "Резерв копийӗсене уҫӑр",
"The game is running: change packs in its own menus, or here once it is closed.": "Вӑйӑ ӗҫлет: хӑйӗн менюсенче пакетсене улӑштарӑр, е хупӑнсан кунта.",
"Check now": "Халех тӗрӗслӗр",
"Choose a cape…": "Плащ суйласа ил...",
"Save": "Упра",
"Folder": "Папка",
"Searching…": "Шырав...",
@@ -422,7 +408,6 @@
"MangoHud": "МангоХуд",
"Sign out": "Тухса кайӑр",
"When it starts": "Вӑл хӑҫан пуҫланать",
"{name}'s skin": "{name} тирӗ",
"Start": "Пуҫла",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft лартма кирлӗ мар: Horizon ӑна Mojang-ран сирӗн аккаунт валли скачать тӑвать.",
"Logs": "Журналсем",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Сӑмах палли, ҫав вӑхӑтрах релиз списокӗ ҫӗкленет.",
"Playing offline": "Офлайн выляни",
"Sign in to Tailscale": "Tailscale ҫине кӗрӗр",
"Offline names without an account": "Аккаунтсӑр офлайн ятсем",
"Help make Horizon faster and steadier?": "Horizon хӑвӑртрах та ҫирӗпрех тума пулӑшӑр-и?",
"Sign in to play": "Выляма кӗрӗр",
"Ported": "Портланӑ",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Ку лаунчера сирӗн пакет менеджерӗпе ҫӗнетӗр.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Ку лаунчера хупӑр, ӑна {folder} патне куҫарӑр тата ҫӗнетӳсене ҫутатма унта уҫӑр.",
"Any MCP client": "Кирек мӗнле MCP клиент",
"{name}'s cape is kept.": "{name} плащне упраҫҫӗ.",
"Not reviewed by the Horizon registry": "Horizon реестрӗнче пӑхса тухман",
"Proxy": "Прокси",
"Checking": "Тӗрӗслев",
"Updates": "Ҫӗнӗлӗхсем",
"Asking Microsoft…": "Microsoft ыйтатӑп…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Minecraft {version} валли хатӗрленӗ, унӑн сассисемсӗр: вӑйӑ шӑп пулать. Вӗсене хӑвӑрӑн Minecraft установкӑран копилеме тепӗр хут хатӗрленӗр.",
"Forget": "Манӑр",
"Import a modpack…": "Модпак импортла...",
"Search versions": "Версисене шыраса тупӑр",
"failed": "ӑнӑҫсӑр",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Пӑрахнӑ: {line}.",
"Resource packs": "Ресурс пакетӗсем",
"yesterday": "ӗнер",
"No cape": "Плащ ҫук",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Кашни сеанс хыҫҫӑн: кадр вӑхӑчӗн процентилӗсем тата 14-бакетлӑ гистограмма, тик вӑхӑчӗсем, пик асӑнӑвӗ тата пуҫламӑш вӑхӑчӗсем, сирӗн машинӑпа (ОС, процессор тата унӑн ядросемпе сехечӗсем, асӑну калӑпӑшӗ, GPU, унӑн асӑнӑвӗпе драйверӗ, диск тӗсӗ, экран калӑпӑшӗ тата ҫӗнетӳ хӑвӑртлӑхӗ, ноутбук е ӗҫ сӗтелӗ, батарейӑра е ҫук) тата ӗҫ тухӑҫлӑхне улӑштаракан настройкӑсем.",
"Make a token": "Токен тӑвӑр",
"Added {names}: the game turns it on when the world opens.": "{names} хушнӑ: тӗнче уҫӑлсан вӑйӑ ӑна ҫутать.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Пӗрле: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Пӗр Wi-Fi ҫинчи туссем: Мультиплеер, Сервер хушӑр, унтан ҫак адреса ҫыпӑҫтарӑр.",
"None yet: drop a .hshader or a shader pack .zip here.": "Хальлӗхе ҫук-ха: кунта .hshader е .zip шейдер пакетне пӑрахӑр.",
"Offline name · the game's own": "Офлайн ят · вӑйӑ хӑйӗн",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Тӑван модсем хӑйӑр ещӗкӗ мар: вӗсем, кирек мӗнле программа пекех, сирӗн компьютера туллин кӗрсе ӗҫлеҫҫӗ. Эсир шанса тӑракан авторсене ҫеҫ лартӑр. Пӗринпе выляс тесен, вӑййа Mods страницинче йӗркелӗр; пӗрремӗш сборка Rust скачать тӑвать те 20-30 минут хушши пырать.",
"Your selected version only changes if you were playing the newest one.": "Эсир суйласа илнӗ верси ҫӗнӗ версипе вылянӑ чухне ҫеҫ улшӑнать.",
"Multiplayer": "Нумай ҫынлӑ",
@@ -587,7 +567,6 @@
"the port": "порт",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "{source} ҫӑлкуҫӗ. Унӑн кӑларӑмӗ {file} ярса парать, контент-мод: GitHub-рисене вырнаҫтарасси хальлӗхе пулӑшмасть.",
"Build anyway": "Пурпӗрех тӑвӑр",
"A name, 3 to 16 letters": "Ят, 3-16 саспалли",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Установлен {mods} от GitHub ({source}). Ӑна Модсен страницинче тӑвӑр.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Настройкӑсем, Ҫӑраҫҫисем, Ҫыхӑну маркерне генерацилесси. Вӑл ҫак компьютерӑн брелокӗнче упранать, Tailscale ҫине ҫеҫ ярса парать.",
"{id} is up to date.": "{id} ҫӗнӗлле.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Эпӗ ӑна вуласа тухрӑм та ӗненетӗп: вырнаҫтар",
"Close export": "Экспорта хуп",
"Playing needs a prepared Horizon version (Play page).": "Выляма хатӗрленӗ Horizon верси кирлӗ (Выля страници).",
"Offline, the game's name": "Офлайн, вӑйӑ ячӗ",
"From Horizon's registry": "Horizon реестрӗнчен",
"Sounds": "Сасӑсем",
"Edit…": "Тӳрлет...",
@@ -635,12 +613,10 @@
"up to date": "ҫӗнӗ",
"← Newer": "← Ҫӗнӗрех",
"Downloading from Mojang · {done} of {total} files": "Mojang · {done} {total} файлсенчен скачать туни",
"{name}'s skin is kept.": "{name} тирне упраҫҫӗ.",
"Edit instance": "Тӳрлетӳ экземплярне",
"Remove shortcut": "Кӗске ҫула кӑларса пӑрахӑр",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} кунта вырнаҫтарман (е PATH ҫинче мар): ун вырӑнне конфигурацие копилӗр.",
"No worlds to put in.": "Тӗнчесем ҫук.",
"Default skin": "Стандартлӑ тир",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Репозитори (унӑн юлашки кӑларӑмӗ), кӑларӑм, турат е тег е коммит ҫине ссылка. Запускник пӗр тӗрӗс релиз файлне е коммита вырнаҫтарать, нихӑҫан та куҫакан турат мар.",
"Sign in with GitHub to rate": "Хаклама GitHub ҫине кӗрӗр",
"Star on GitHub": "GitHub-ра ҫӑлтӑр пар",
@@ -1053,10 +1029,6 @@
"played by {names}": "вылянӑ {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft аккаунт · онлайн-серверсем те",
"Offline · single player and LAN worlds": "Офлайн · пӗр вылякан тата LAN тӗнчисем",
"Offline names": "Офлайн ятсем",
"Add a name": "Ят хушӑр",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3-16 саспалли, цифрӑсем е аялти йӗрсем. Ҫӳлти йӗртен ятсене те улӑштарӑр. Интернетри серверсем офлайн ятсене йышӑнмаҫҫӗ.",
"Play online with your Microsoft account": "Хӑвӑрӑн Microsoft аккаунтпа онлайн выляса пӑхӑр",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Minecraft: Java Издание тытса тӑракан аккаунтпа кӗрӗр. Сирӗн ятӑрпа тир ытти лаунчерсенчи пекех онлайн-серверсем ҫине кӗреҫҫӗ.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Сирӗн браузерта Microsoft хӑйӗн страници уҫӑлать. Horizon сирӗн паролье нихӑҫан та курмасть.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Adeiladu {name} cam ôl-adeiladu",
"In use": "Mewn defnydd",
"Prepare": "Paratoi",
"Developer options": "Opsiynau datblygwr",
"{online} of {max} players": "{online} o {max} chwaraewr",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Argraffiad Java). Mae Chwarae yn ei lawrlwytho o Mojang ar gyfer eich cyfrif y tro cyntaf, gyda'r Java sydd ei angen arno.",
"Close": "Cau",
@@ -98,7 +97,6 @@
"From my install": "O fy gosod",
"the update failed: {error}": "methodd y diweddariad: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 Mesa, felly Vulkan sy'n dewis y cerdyn arall.",
"New name": "Enw newydd",
"Dark": "Tywyll",
"Not now": "Ddim nawr",
"Use an access token…": "Defnyddiwch docyn mynediad…",
@@ -115,7 +113,6 @@
"Partly": "Yn rhannol",
"All": "Pawb",
"Instance": "Enghraifft",
"Classic arms": "Breichiau clasurol",
"Versions": "Fersiynau",
"Release build: slower to build, slightly faster game": "Rhyddhau adeiladu: arafach i adeiladu, gêm ychydig yn gyflymach",
"Performance build": "Adeiladu perfformiad",
@@ -172,7 +169,6 @@
"about a minute left": "tua munud ar ôl",
"Cancel": "Canslo",
"Add to {client}": "Ychwanegu at {client}",
"Skin…": "Croen…",
"Environment": "Amgylchedd",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Maent yn aml yn dal i weithio gyda'i gilydd. Os bydd yr adeiladwaith yn methu, gosodwch fersiynau wedi'u gwneud ar gyfer yr un Nightly.",
"Import an instance folder…": "Mewnforio ffolder enghraifft…",
@@ -184,7 +180,6 @@
"newest stable version": "fersiwn sefydlog diweddaraf",
"Choose image…": "Dewiswch ddelwedd…",
"No worlds yet: they appear here once you play one.": "Dim bydoedd eto: maen nhw'n ymddangos yma unwaith y byddwch chi'n chwarae un.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Mae enwau all-lein yn chwarae heb gyfrif Microsoft sy'n berchen ar y gêm. Mae Minecraft yn dal i ddod o'ch gosodiad eich hun.",
"crash reports beside it": "adroddiadau chwalu wrth ei ymyl",
"Install all": "Gosod i gyd",
"No group": "Dim grŵp",
@@ -202,7 +197,6 @@
"My instance": "Fy enghraifft",
"Snapshot": "Ciplun",
"Gallery": "Oriel",
"Offline name": "Enw all-lein",
"Home": "Cartref",
"Stopping": "Stopio",
"MSPT · tick time": "MSPT · amser tic",
@@ -304,8 +298,6 @@
"Patch notes": "Nodiadau patch",
"Your Minecraft server, {online}.": "Eich gweinydd Minecraft, {online}.",
"Crash reports": "Adroddiadau chwalu",
"Offline name · the game's own · plays": "Enw all-lein · gêm y gêm ei hun · chwarae",
"Slim arms": "Breichiau fain",
"Asking GitHub about {owner}/{repo}…": "Yn holi GitHub am {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Lawrlwytho Minecraft {version} o Mojang · {done} o {total} ffeil",
"Could not save your choice: {error}": "Methu cadw eich dewis: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "tirwedd Horizon. Dewiswch lun PNG, JPEG neu WebP eich hun.",
"Not needed": "Dim angen",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Nid oes gan y llun hwn o'r lansiwr unrhyw mewngofnodi Microsoft (HORIZON_MSA_CLIENT_ID), felly ni all ddechrau'r gêm.",
"Offline name · plays": "Enw all-lein · dramâu",
"Run the game through": "Rhedeg y gêm drwodd",
"needed by another pack": "angen pecyn arall",
"Older →": "Hyn →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Methu rhedeg {program}: {error}",
"Restart": "Ailgychwyn",
"Copied to the clipboard.": "Wedi'i gopïo i'r clipfwrdd.",
"Your worlds, offline names and settings stay where they are.": "Mae eich bydoedd, eich enwau all-lein a'ch gosodiadau yn aros lle maen nhw.",
"Send nothing": "Anfon dim",
"Move to Trash": "Symud i'r Sbwriel",
"Start from": "Cychwyn o",
"Asking Mojang for its versions…": "Yn gofyn i Mojang am ei fersiynau…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "PNG croen 64 × 64 (neu 64 × 32) a cape PNG 64 × 32, a gedwir gan y lansiwr a'i roi i'r gêm pan fydd yr enw hwn yn chwarae. Mae'r gêm yn tynnu'r crwyn rhagosodedig am y tro; mae'n defnyddio'r rhain unwaith y gall. Croen a chlogyn cyfrif Microsoft: yn dod yn fuan.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Chwarae all-lein o dan enw arall, a newid o'r bar uchaf. Nid yw gweinyddwyr ar-lein yn cymryd enwau all-lein.",
"Report on Discord": "Adrodd ar Discord",
"Export": "Allforio",
"Server": "Gweinydd",
@@ -384,7 +372,6 @@
"No version installed yet.": "Dim fersiwn wedi'i osod eto.",
"Release": "Rhyddhad",
"Verified": "Wedi'i wirio",
"Choose a skin…": "Dewiswch groen…",
"{instance} doesn't play its native mods yet: build the game with them.": "Nid yw {instance} yn chwarae ei mods brodorol eto: adeiladwch y gêm gyda nhw.",
"Use jars from my instance…": "Defnyddiwch jariau o fy achos i…",
"Applications menu": "Dewislen ceisiadau",
@@ -408,7 +395,6 @@
"Open backups": "Agor copïau wrth gefn",
"The game is running: change packs in its own menus, or here once it is closed.": "Mae'r gêm yn rhedeg: newidiwch becynnau yn ei fwydlenni ei hun, neu yma unwaith y bydd ar gau.",
"Check now": "Gwiriwch nawr",
"Choose a cape…": "Dewiswch fantell…",
"Save": "Arbed",
"Folder": "Ffolder",
"Searching…": "Wrthi'n chwilio…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Arwyddo allan",
"When it starts": "Pan fydd yn dechrau",
"{name}'s skin": "croen {name}",
"Start": "Cychwyn",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Nid oes angen gosod Minecraft: Horizon mae'n ei lawrlwytho o Mojang ar gyfer eich cyfrif.",
"Logs": "Logiau",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Y gairnod, tra bod y rhestr rhyddhau yn llwytho.",
"Playing offline": "Chwarae all-lein",
"Sign in to Tailscale": "Mewngofnodwch i Tailscale",
"Offline names without an account": "Enwau all-lein heb gyfrif",
"Help make Horizon faster and steadier?": "Helpu i wneud Horizon yn gyflymach ac yn fwy cyson?",
"Sign in to play": "Mewngofnodwch i chwarae",
"Ported": "Wedi'i gludo",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Diweddarwch y lansiwr hwn gyda'ch rheolwr pecynnau.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Caewch y lansiwr hwn, symudwch ef i {folder}, ac agorwch ef yno i alluogi diweddariadau.",
"Any MCP client": "Unrhyw gleient MCP",
"{name}'s cape is kept.": "Mae clogyn {name} yn cael ei gadw.",
"Not reviewed by the Horizon registry": "Heb ei adolygu gan y gofrestrfa Horizon",
"Proxy": "Dirprwy",
"Checking": "Gwirio",
"Updates": "Diweddariadau",
"Asking Microsoft…": "Wrth ofyn i Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Wedi'i baratoi ar gyfer Minecraft {version}, heb ei synau: bydd y gêm yn dawel. Paratowch eto i'w copïo o'ch gosodiad Minecraft.",
"Forget": "Anghofiwch",
"Import a modpack…": "Mewnforio modpack…",
"Search versions": "Chwilio fersiynau",
"failed": "methu",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Chwith i ffwrdd: {line}.",
"Resource packs": "Pecynnau adnoddau",
"yesterday": "ddoe",
"No cape": "Dim clogyn",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Ar ôl pob sesiwn: canraddau amser ffrâm a histogram 14 bwced, amseroedd ticio, cof brig ac amseroedd cychwyn, gyda'ch peiriant (OS, CPU a'i greiddiau a chlociau, maint cof, GPU, ei gof a gyrrwr, math o yriant, maint y sgrin a chyfradd adnewyddu, gliniadur neu benbwrdd, ar fatri ai peidio) a'r gosodiadau sy'n newid perfformiad.",
"Make a token": "Gwnewch tocyn",
"Added {names}: the game turns it on when the world opens.": "Ychwanegwyd {names}: mae'r gêm yn ei throi ymlaen pan fydd y byd yn agor.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Wedi'i rannu: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Cyfeillion ar yr un Wi-Fi: Multiplayer, Ychwanegu Gweinyddwr, yna gludwch y cyfeiriad hwn.",
"None yet: drop a .hshader or a shader pack .zip here.": "Dim eto: gollwng .hshader neu becyn shader .zip yma.",
"Offline name · the game's own": "Enw all-lein · y gêm ei hun",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Nid yw mods brodorol yn cael eu sandboxed: maent yn rhedeg gyda mynediad llawn i'ch cyfrifiadur, fel unrhyw raglen. Gosod dim ond mods y mae eu hawduron yr ydych yn ymddiried ynddynt. I chwarae gydag un, adeiladwch y gêm ar y dudalen Mods; mae'r adeilad cyntaf yn lawrlwytho Rust ac yn cymryd 20 i 30 munud.",
"Your selected version only changes if you were playing the newest one.": "Dim ond os oeddech chi'n chwarae'r un mwyaf newydd y bydd y fersiwn rydych chi wedi'i dewis yn newid.",
"Multiplayer": "Aml-chwaraewr",
@@ -587,7 +567,6 @@
"the port": "y porthladd",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Ffynhonnell {source}. Mae ei longau rhyddhau {file}, mod cynnwys: nid yw gosod y rhai o GitHub yn cael ei gefnogi eto.",
"Build anyway": "Adeiladu beth bynnag",
"A name, 3 to 16 letters": "Enw, 3 i 16 llythyren",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Wedi'i osod {mods} o GitHub ({source}). Adeiladwch ef ar y dudalen Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Gosodiadau, Allweddi, Cynhyrchu tocyn mynediad. Mae'n cael ei gadw yng nghadwyni'r cyfrifiadur hwn a'i anfon at Tailscale yn unig.",
"{id} is up to date.": "Mae {id} yn gyfredol.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Rwy'n ei ddarllen ac yn ymddiried ynddo: gosod",
"Close export": "Cau allforio",
"Playing needs a prepared Horizon version (Play page).": "Mae angen fersiwn Horizon parod (tudalen chwarae).",
"Offline, the game's name": "All-lein, enw'r gêm",
"From Horizon's registry": "O gofrestrfa Horizon",
"Sounds": "Swnio",
"Edit…": "Golygu…",
@@ -635,12 +613,10 @@
"up to date": "yn gyfoes",
"← Newer": "← Newyddach",
"Downloading from Mojang · {done} of {total} files": "Llwytho i lawr o Mojang · {done} o {total} ffeil",
"{name}'s skin is kept.": "Mae croen {name} yn cael ei gadw.",
"Edit instance": "Golygu enghraifft",
"Remove shortcut": "Dileu llwybr byr",
"{program} is not installed here (or not on the PATH): copy the config instead.": "Nid yw {program} wedi'i osod yma (neu ddim ar y PATH): copïwch y ffurfwedd yn lle hynny.",
"No worlds to put in.": "Dim bydoedd i'w rhoi i mewn.",
"Default skin": "Croen diofyn",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Dolen i gadwrfa (ei datganiad diweddaraf), datganiad, cangen neu dag, neu ymrwymiad. Mae'r lansiwr yn gosod un ffeil rhyddhau neu ymrwymiad union, byth yn gangen sy'n symud.",
"Sign in with GitHub to rate": "Mewngofnodwch gyda GitHub i raddio",
"Star on GitHub": "Rhoi seren ar GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "chwarae gan {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Cyfrif Microsoft · gweinyddwyr ar-lein hefyd",
"Offline · single player and LAN worlds": "All-lein · chwaraewr sengl a byd LAN",
"Offline names": "Enwau all-lein",
"Add a name": "Ychwanegu enw",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 i 16 llythyren, rhif neu danlinellu. Newidiwch enwau o'r bar uchaf hefyd. Nid yw gweinyddwyr ar-lein yn cymryd enwau all-lein.",
"Play online with your Microsoft account": "Chwarae ar-lein gyda'ch cyfrif Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Mewngofnodwch gyda'r cyfrif sy'n berchen ar Minecraft: Java Edition. Daw eich enw a'ch croen i weinyddion ar-lein, fel mewn lanswyr eraill.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Mae tudalen Microsoft ei hun yn agor yn eich porwr. Nid yw Horizon byth yn gweld eich cyfrinair.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Bygning af {name}s post-build trin",
"In use": "I brug",
"Prepare": "Forbered dig",
"Developer options": "Udvikler muligheder",
"{online} of {max} players": "{online} af {max} spillere",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). Play downloader det fra Mojang til din konto første gang med den Java, den har brug for.",
"Close": "Luk",
@@ -98,7 +97,6 @@
"From my install": "Fra min installation",
"the update failed: {error}": "opdateringen mislykkedes: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesa's DRI_PRIME=1, så Vulkan vælger det andet kort.",
"New name": "Nyt navn",
"Dark": "Mørk",
"Not now": "Ikke nu",
"Use an access token…": "Brug et adgangstoken...",
@@ -115,7 +113,6 @@
"Partly": "Dels",
"All": "Alle",
"Instance": "Forekomst",
"Classic arms": "Klassiske arme",
"Versions": "Versioner",
"Release build: slower to build, slightly faster game": "Release build: langsommere at bygge, lidt hurtigere spil",
"Performance build": "Opbygning af ydeevne",
@@ -172,7 +169,6 @@
"about a minute left": "omkring et minut tilbage",
"Cancel": "Annuller",
"Add to {client}": "Føj til {client}",
"Skin…": "Hud...",
"Environment": "Miljø",
"They often still work together. If the build fails, install versions made for the same Nightly.": "De arbejder ofte stadig sammen. Hvis bygningen mislykkes, skal du installere versioner lavet til den samme Nightly.",
"Import an instance folder…": "Importer en forekomstmappe...",
@@ -184,7 +180,6 @@
"newest stable version": "nyeste stabile version",
"Choose image…": "Vælg billede...",
"No worlds yet: they appear here once you play one.": "Ingen verdener endnu: de vises her, når du spiller en.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline navne spiller uden en Microsoft-konto, der ejer spillet. Minecraft kommer stadig fra din egen installation.",
"crash reports beside it": "nedbrudsrapporter ved siden af",
"Install all": "Installer alle",
"No group": "Ingen gruppe",
@@ -202,7 +197,6 @@
"My instance": "Mit eksempel",
"Snapshot": "Snapshot",
"Gallery": "Galleri",
"Offline name": "Offline navn",
"Home": "Hjem",
"Stopping": "Stopper",
"MSPT · tick time": "MSPT · kryds tid",
@@ -305,8 +299,6 @@
"Patch notes": "Patch-noter",
"Your Minecraft server, {online}.": "Din Minecraft-server, {online}.",
"Crash reports": "Nedbrudsrapporter",
"Offline name · the game's own · plays": "Offline navn · spillets egne · afspilninger",
"Slim arms": "Slanke arme",
"Asking GitHub about {owner}/{repo}…": "Spørger GitHub om {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Downloader Minecraft {version} fra Mojang · {done} af {total} filer",
"Could not save your choice: {error}": "Kunne ikke gemme dit valg: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizons landskab. Vælg dit eget billede i PNG, JPEG eller WebP.",
"Not needed": "Ikke nødvendigt",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Denne build af launcheren har ikke noget Microsoft-logon (HORIZON_MSA_CLIENT_ID), så det kan ikke starte spillet.",
"Offline name · plays": "Offline navn · spiller",
"Run the game through": "Kør spillet igennem",
"needed by another pack": "brug for en anden pakke",
"Older →": "Ældre →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "Kunne ikke køre {program}: {error}",
"Restart": "Genstart",
"Copied to the clipboard.": "Kopieret til udklipsholderen.",
"Your worlds, offline names and settings stay where they are.": "Dine verdener, offline navne og indstillinger forbliver, hvor de er.",
"Send nothing": "Send intet",
"Move to Trash": "Flyt til papirkurven",
"Start from": "Start fra",
"Asking Mojang for its versions…": "Beder Mojang om dens versioner...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "En 64×64 (eller 64×32) skin PNG og en 64×32 cape PNG, opbevaret af launcheren og givet til spillet, når dette navn spiller. Spillet tegner standard skins for nu; den bruger disse, når den kan. En Microsoft-kontos skin and cape: kommer snart.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Spil offline under et andet navn, og skift fra den øverste bjælke. Onlineservere tager ikke offline navne.",
"Report on Discord": "Rapport om Discord",
"Export": "Eksporter",
"Server": "Server",
@@ -385,7 +373,6 @@
"No version installed yet.": "Ingen version installeret endnu.",
"Release": "Slip",
"Verified": "Verificeret",
"Choose a skin…": "Vælg et skin...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} spiller ikke sine oprindelige mods endnu: byg spillet med dem.",
"Use jars from my instance…": "Brug krukker fra min instans...",
"Applications menu": "Applikationsmenu",
@@ -409,7 +396,6 @@
"Open backups": "Åbn sikkerhedskopier",
"The game is running: change packs in its own menus, or here once it is closed.": "Spillet kører: Skift pakker i sine egne menuer, eller her, når det er lukket.",
"Check now": "Tjek nu",
"Choose a cape…": "Vælg en kappe...",
"Save": "Gem",
"Folder": "Mappe",
"Searching…": "Søger...",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Log ud",
"When it starts": "Når det starter",
"{name}'s skin": "{name}s hud",
"Start": "Start",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Ingen Minecraft-installation nødvendig: Horizon downloader det fra Mojang til din konto.",
"Logs": "Logfiler",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Ordmærket, mens udgivelseslisten indlæses.",
"Playing offline": "Spiller offline",
"Sign in to Tailscale": "Log ind på Tailscale",
"Offline names without an account": "Offline navne uden en konto",
"Help make Horizon faster and steadier?": "Hjælp med at gøre Horizon hurtigere og mere stabil?",
"Sign in to play": "Log ind for at spille",
"Ported": "Porteret",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Opdater denne launcher med din pakkehåndtering.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Luk denne launcher, flyt den til {folder}, og åbn den der for at aktivere opdateringer.",
"Any MCP client": "Enhver MCP-klient",
"{name}'s cape is kept.": "{name}s kappe beholdes.",
"Not reviewed by the Horizon registry": "Ikke gennemgået af Horizon-registret",
"Proxy": "Fuldmagt",
"Checking": "Tjekker",
"Updates": "Opdateringer",
"Asking Microsoft…": "Spørger Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Forberedt til Minecraft {version}, uden dens lyde: spillet vil være stille. Forbered dig igen på at kopiere dem fra din Minecraft-installation.",
"Forget": "Glem",
"Import a modpack…": "Importer en modpack...",
"Search versions": "Søg efter versioner",
"failed": "mislykkedes",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Sluttede: {line}.",
"Resource packs": "Ressourcepakker",
"yesterday": "i går",
"No cape": "Ingen kappe",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Efter hver session: frame-time percentiler og et 14-bucket histogram, tick-tider, peak-hukommelse og starttider, med din maskine (OS, CPU og dens kerner og ure, hukommelsesstørrelse, GPU, dens hukommelse og driver, drevtype, skærmstørrelse og opdateringshastighed, bærbar eller desktop, på batteri eller ej) og de indstillinger, der ændrer ydeevnen.",
"Make a token": "Lav en token",
"Added {names}: the game turns it on when the world opens.": "Tilføjet {names}: spillet tænder det, når verden åbner.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Delt: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Venner på samme Wi-Fi: Multiplayer, Tilføj server, og indsæt derefter denne adresse.",
"None yet: drop a .hshader or a shader pack .zip here.": "Ingen endnu: Smid en .hshader eller en shader-pakke .zip her.",
"Offline name · the game's own": "Offline navn · spillets eget",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Native mods er ikke sandboxed: de kører med fuld adgang til din computer, som ethvert program. Installer kun mods, hvis forfattere du stoler på. For at spille med en, skal du bygge spillet på Mods-siden; den første build downloader Rust og tager 20 til 30 minutter.",
"Your selected version only changes if you were playing the newest one.": "Din valgte version ændres kun, hvis du spillede den nyeste.",
"Multiplayer": "Multiplayer",
@@ -589,7 +569,6 @@
"the port": "havnen",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Kilden til {source}. Dens udgivelse leveres {file}, en indholdsmod: installation af dem fra GitHub understøttes endnu ikke.",
"Build anyway": "Byg alligevel",
"A name, 3 to 16 letters": "Et navn, 3 til 16 bogstaver",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Installeret {mods} fra GitHub ({source}). Byg det på Mods-siden.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Indstillinger, Nøgler, Generer adgangstoken. Den opbevares i denne computers nøglering og sendes kun til Tailscale.",
"{id} is up to date.": "{id} er opdateret.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Jeg læser det og stoler på det: installer",
"Close export": "Luk eksport",
"Playing needs a prepared Horizon version (Play page).": "At spille kræver en forberedt Horizon-version (Play-side).",
"Offline, the game's name": "Offline, spillets navn",
"From Horizon's registry": "Fra Horizons register",
"Sounds": "Lyde",
"Edit…": "Rediger...",
@@ -637,12 +615,10 @@
"up to date": "opdateret",
"← Newer": "← Nyere",
"Downloading from Mojang · {done} of {total} files": "Downloader fra Mojang · {done} af {total} filer",
"{name}'s skin is kept.": "{name}s hud bevares.",
"Edit instance": "Rediger forekomst",
"Remove shortcut": "Fjern genvej",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} er ikke installeret her (eller ikke på PATH): kopier konfigurationen i stedet for.",
"No worlds to put in.": "Ingen verdener at sætte ind.",
"Default skin": "Standard skin",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Et link til et lager (dets seneste udgivelse), en udgivelse, en filial eller tag eller en commit. Starteren installerer én nøjagtig udgivelsesfil eller commit, aldrig en gren, der bevæger sig.",
"Sign in with GitHub to rate": "Log ind med GitHub for at bedømme",
"Star on GitHub": "Giv en stjerne på GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "spillet af {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft-konto · også onlineservere",
"Offline · single player and LAN worlds": "Offline · singleplayer og LAN-verdener",
"Offline names": "Offline navne",
"Add a name": "Tilføj et navn",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 til 16 bogstaver, tal eller understregninger. Du kan også skifte navn fra topbjælken. Onlineservere accepterer ikke offline navne.",
"Play online with your Microsoft account": "Spil online med din Microsoft-konto",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Log ind med den konto, der ejer Minecraft: Java Edition. Dit navn og dit skin følger med til onlineservere, ligesom i andre launchere.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsofts egen side åbner i din browser. Horizon ser aldrig din adgangskode.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Post-Build-Schritt von {name} wird gebaut",
"In use": "In Verwendung",
"Prepare": "Vorbereiten",
"Developer options": "Entwickleroptionen",
"{online} of {max} players": "{online} von {max} Spielern",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). Beim ersten Mal lädt „Spielen“ es für dein Konto von Mojang herunter, mit dem Java, das es braucht.",
"Close": "Schließen",
@@ -98,7 +97,6 @@
"From my install": "Aus meiner Installation",
"the update failed: {error}": "das Update ist fehlgeschlagen: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesas DRI_PRIME=1, damit Vulkan die andere Karte wählt.",
"New name": "Neuer Name",
"Dark": "Dunkel",
"Not now": "Nicht jetzt",
"Use an access token…": "Zugriffstoken verwenden…",
@@ -115,7 +113,6 @@
"Partly": "Teilweise",
"All": "Alle",
"Instance": "Instanz",
"Classic arms": "Klassische Arme",
"Versions": "Versionen",
"Release build: slower to build, slightly faster game": "Release-Build: dauert länger, das Spiel ist etwas schneller",
"Performance build": "Performance-Build",
@@ -172,7 +169,6 @@
"about a minute left": "noch etwa eine Minute",
"Cancel": "Abbrechen",
"Add to {client}": "Zu {client} hinzufügen",
"Skin…": "Skin…",
"Environment": "Umgebung",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Oft funktionieren sie trotzdem zusammen. Schlägt der Build fehl, installiere Versionen für dieselbe Nightly.",
"Import an instance folder…": "Instanzordner importieren…",
@@ -184,7 +180,6 @@
"newest stable version": "neueste stabile Version",
"Choose image…": "Bild wählen…",
"No worlds yet: they appear here once you play one.": "Noch keine Welten: Sie erscheinen hier, sobald du eine spielst.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline-Namen spielen ohne ein Microsoft-Konto, das das Spiel besitzt. Minecraft stammt weiterhin aus deiner eigenen Installation.",
"crash reports beside it": "absturzberichte daneben",
"Install all": "Alle installieren",
"No group": "Keine Gruppe",
@@ -202,7 +197,6 @@
"My instance": "Meine Instanz",
"Snapshot": "Snapshot",
"Gallery": "Galerie",
"Offline name": "Offline-Name",
"Home": "Startseite",
"Stopping": "Stoppt",
"MSPT · tick time": "MSPT · Tick-Zeit",
@@ -305,8 +299,6 @@
"Patch notes": "Versionshinweise",
"Your Minecraft server, {online}.": "Dein Minecraft-Server, {online}.",
"Crash reports": "Absturzberichte",
"Offline name · the game's own · plays": "Offline-Name · vom Spiel vergeben · spielt",
"Slim arms": "Schmale Arme",
"Asking GitHub about {owner}/{repo}…": "GitHub wird zu {owner}/{repo} abgefragt…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Minecraft {version} wird von Mojang heruntergeladen · {done} von {total} Dateien",
"Could not save your choice: {error}": "Deine Auswahl konnte nicht gespeichert werden: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizons Landschaft. Wähle ein eigenes PNG-, JPEG- oder WebP-Bild aus.",
"Not needed": "Nicht nötig",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Diese Version des Launchers hat keine Microsoft-Anmeldung (HORIZON_MSA_CLIENT_ID). Das Spiel kann daher nicht gestartet werden.",
"Offline name · plays": "Offline-Name · spielt",
"Run the game through": "Spiel starten über",
"needed by another pack": "von einem anderen Paket benötigt",
"Older →": "Ältere →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "{program} konnte nicht ausgeführt werden: {error}",
"Restart": "Neu starten",
"Copied to the clipboard.": "In die Zwischenablage kopiert.",
"Your worlds, offline names and settings stay where they are.": "Deine Welten, Offline-Namen und Einstellungen bleiben erhalten.",
"Send nothing": "Nichts senden",
"Move to Trash": "In den Papierkorb",
"Start from": "Starten mit",
"Asking Mojang for its versions…": "Mojang wird nach den Versionen gefragt…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Ein 64×64-Skin-PNG (oder 64×32) und ein 64×32-Umhang-PNG, die vom Launcher gespeichert und dem Spiel übergeben werden, wenn dieser Name spielt. Das Spiel zeigt vorerst die Standard-Skins an; es wird diese verwenden, sobald es möglich ist. Skin und Umhang eines Microsoft-Kontos: demnächst verfügbar.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Spiele offline unter einem anderen Namen und wechsel über die obere Leiste. Online-Server akzeptieren keine Offline-Namen.",
"Report on Discord": "Auf Discord melden",
"Export": "Exportieren",
"Server": "Server",
@@ -385,7 +373,6 @@
"No version installed yet.": "Noch keine Version installiert.",
"Release": "Release",
"Verified": "Verifiziert",
"Choose a skin…": "Skin auswählen…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} spielt seine nativen Mods noch nicht: baue das Spiel mit ihnen.",
"Use jars from my instance…": "JARs aus meiner Instanz verwenden…",
"Applications menu": "Anwendungsmenü",
@@ -409,7 +396,6 @@
"Open backups": "Sicherungen öffnen",
"The game is running: change packs in its own menus, or here once it is closed.": "Das Spiel läuft: Ändere Pakete in den Spielmenüs oder hier, sobald es beendet ist.",
"Check now": "Jetzt prüfen",
"Choose a cape…": "Umhang auswählen…",
"Save": "Speichern",
"Folder": "Ordner",
"Searching…": "Suche…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Abmelden",
"When it starts": "Beim Start",
"{name}'s skin": "{name}s Skin",
"Start": "Starten",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Keine Minecraft-Installation nötig: Horizon lädt es für dein Konto von Mojang herunter.",
"Logs": "Protokolle",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Das Logo, während die Versionsliste lädt.",
"Playing offline": "Offline spielen",
"Sign in to Tailscale": "Bei Tailscale anmelden",
"Offline names without an account": "Offline-Namen ohne Konto",
"Help make Horizon faster and steadier?": "Hilf mit, Horizon schneller und stabiler zu machen?",
"Sign in to play": "Zum Spielen anmelden",
"Ported": "Portiert",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Aktualisiere diesen Launcher mit deiner Paketverwaltung.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Schließe diesen Launcher, verschiebe ihn nach {folder} und öffne ihn dort, um Updates zu ermöglichen.",
"Any MCP client": "Jeder MCP-Client",
"{name}'s cape is kept.": "{name}s Umhang wird beibehalten.",
"Not reviewed by the Horizon registry": "Nicht vom Horizon-Verzeichnis geprüft",
"Proxy": "Proxy",
"Checking": "Prüfe",
"Updates": "Aktualisierungen",
"Asking Microsoft…": "Frage Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Für Minecraft {version} ohne Sound vorbereitet: das Spiel bleibt stumm. Bereite es erneut vor, um die Sounds von deiner Minecraft-Installation zu kopieren.",
"Forget": "Vergessen",
"Import a modpack…": "Ein Modpack importieren…",
"Search versions": "Versionen suchen",
"failed": "fehlgeschlagen",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Ausgelassen: {line}.",
"Resource packs": "Ressourcenpakete",
"yesterday": "gestern",
"No cape": "Kein Umhang",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Nach jeder Sitzung: Perzentile der Frame-Zeiten und ein Histogramm mit 14 Klassen, Tick-Zeiten, Spitzenarbeitsspeicher und Startzeiten, mit deinem Rechner (Betriebssystem, CPU mit Kernen und Taktraten, Arbeitsspeichergröße, GPU mit Speicher und Treiber, Laufwerkstyp, Bildschirmgröße und Bildwiederholrate, Laptop oder Desktop, Akkubetrieb oder nicht) und den Einstellungen, die die Leistung beeinflussen.",
"Make a token": "Token erstellen",
"Added {names}: the game turns it on when the world opens.": "{names} hinzugefügt: Das Spiel schaltet es beim Öffnen der Welt ein.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Geteilt: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Freunde im selben WLAN: Mehrspieler, Server hinzufügen und dann diese Adresse einfügen.",
"None yet: drop a .hshader or a shader pack .zip here.": "Noch keine: Ziehe eine .hshader-Datei oder ein Shader-Paket als .zip hierher.",
"Offline name · the game's own": "Offline-Name · vom Spiel vergeben",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Native Mods laufen nicht in einer Sandbox: Sie haben vollen Zugriff auf deinen Computer, wie jedes Programm. Installiere nur Mods, deren Autoren du vertraust. Um mit einer zu spielen, baue das Spiel auf der Mods-Seite; der erste Build lädt Rust herunter und dauert 20 bis 30 Minuten.",
"Your selected version only changes if you were playing the newest one.": "Deine ausgewählte Version ändert sich nur, wenn du die neueste gespielt hast.",
"Multiplayer": "Mehrspieler",
@@ -589,7 +569,6 @@
"the port": "der Port",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Der Quellcode von {source}. Das Release enthält {file}, eine Inhalts-Mod: Die Installation solcher Mods von GitHub wird noch nicht unterstützt.",
"Build anyway": "Trotzdem bauen",
"A name, 3 to 16 letters": "Name, 3 bis 16 Buchstaben",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "{mods} von GitHub ({source}) installiert. Kompiliere es auf der Seite Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Settings, Keys, Generate access token. Es wird im Schlüsselbund dieses Computers gespeichert und nur an Tailscale gesendet.",
"{id} is up to date.": "{id} ist aktuell.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Ich habe ihn gelesen und vertraue ihm: installieren",
"Close export": "Export schließen",
"Playing needs a prepared Horizon version (Play page).": "Zum Spielen braucht es eine vorbereitete Horizon-Version (Seite Spielen).",
"Offline, the game's name": "Offline-Spiel",
"From Horizon's registry": "Aus der eigenen geprüften Registry",
"Sounds": "Geräusche",
"Edit…": "Bearbeiten…",
@@ -637,12 +615,10 @@
"up to date": "aktuell",
"← Newer": "← Neuere",
"Downloading from Mojang · {done} of {total} files": "Download von Mojang · {done} von {total} Dateien",
"{name}'s skin is kept.": "{name}s Skin wird beibehalten.",
"Edit instance": "Instanz bearbeiten",
"Remove shortcut": "Verknüpfung entfernen",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} ist hier nicht installiert (oder nicht im PATH): Kopiere stattdessen die Konfiguration.",
"No worlds to put in.": "Keine Welten zum Einfügen vorhanden.",
"Default skin": "Standard-Skin",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Ein Link zu einem Repository (dessen neuestem Release), einem Release, einem Branch oder Tag oder einem Commit. Der Launcher installiert eine genaue Release-Datei oder einen genauen Commit, niemals einen beweglichen Branch.",
"Sign in with GitHub to rate": "Mit GitHub anmelden, um zu bewerten",
"Star on GitHub": "Auf GitHub mit Stern markieren",
@@ -1055,10 +1031,6 @@
"played by {names}": "gespielt von {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft-Konto · auch Online-Server",
"Offline · single player and LAN worlds": "Offline · Einzelspieler- und LAN-Welten",
"Offline names": "Offline-Namen",
"Add a name": "Namen hinzufügen",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 bis 16 Buchstaben, Ziffern oder Unterstriche. Namen wechselst du auch in der oberen Leiste. Online-Server nehmen keine Offline-Namen an.",
"Play online with your Microsoft account": "Mit deinem Microsoft-Konto online spielen",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Melde dich mit dem Konto an, dem Minecraft: Java Edition gehört. Dein Name und Skin kommen mit auf Online-Server, wie in anderen Launchern.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsofts eigene Seite öffnet sich in deinem Browser. Horizon sieht dein Passwort nie.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Κατασκευή του βήματος μετά την κατασκευή του {name}",
"In use": "Σε χρήση",
"Prepare": "Προετοιμαστείτε",
"Developer options": "Επιλογές προγραμματιστή",
"{online} of {max} players": "{online} από {max} παίκτες",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Έκδοση Java). Το Play το κατεβάζει από το Mojang για τον λογαριασμό σας την πρώτη φορά, με την Java που χρειάζεται.",
"Close": "Κλείσιμο",
@@ -98,7 +97,6 @@
"From my install": "Από την εγκατάσταση μου",
"the update failed: {error}": "η ενημέρωση απέτυχε: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Το DRI_PRIME=1 του Mesa, οπότε ο Vulkan διαλέγει το άλλο φύλλο.",
"New name": "Νέο όνομα",
"Dark": "Σκοτεινό",
"Not now": "Όχι τώρα",
"Use an access token…": "Χρησιμοποιήστε ένα διακριτικό πρόσβασης…",
@@ -115,7 +113,6 @@
"Partly": "Εν μέρει",
"All": "Όλα",
"Instance": "Παράδειγμα",
"Classic arms": "Κλασικά μπράτσα",
"Versions": "εκδόσεις",
"Release build: slower to build, slightly faster game": "Έκδοση έκδοσης: πιο αργό στην κατασκευή, ελαφρώς πιο γρήγορο παιχνίδι",
"Performance build": "Κατασκευή απόδοσης",
@@ -172,7 +169,6 @@
"about a minute left": "περίπου ένα λεπτό απομένει",
"Cancel": "Ακύρωση",
"Add to {client}": "Προσθήκη στο {client}",
"Skin…": "Δέρμα…",
"Environment": "Περιβάλλον",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Συχνά εξακολουθούν να συνεργάζονται. Εάν η κατασκευή αποτύχει, εγκαταστήστε εκδόσεις που έχουν δημιουργηθεί για το ίδιο Nightly.",
"Import an instance folder…": "Εισαγωγή φακέλου παρουσίας…",
@@ -184,7 +180,6 @@
"newest stable version": "η πιο πρόσφατη σταθερή έκδοση",
"Choose image…": "Επιλέξτε εικόνα…",
"No worlds yet: they appear here once you play one.": "Δεν υπάρχουν ακόμη κόσμοι: εμφανίζονται εδώ μόλις παίξετε έναν.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Τα ονόματα εκτός σύνδεσης παίζουν χωρίς λογαριασμό Microsoft στον οποίο ανήκει το παιχνίδι. Το Minecraft εξακολουθεί να προέρχεται από τη δική σας εγκατάσταση.",
"crash reports beside it": "αναφορές σύγκρουσης δίπλα του",
"Install all": "Εγκαταστήστε όλα",
"No group": "Καμία ομάδα",
@@ -202,7 +197,6 @@
"My instance": "Η δική μου περίπτωση",
"Snapshot": "Στιγμιότυπο",
"Gallery": "Γκαλερί",
"Offline name": "Όνομα εκτός σύνδεσης",
"Home": "Σπίτι",
"Stopping": "Σταματώντας",
"MSPT · tick time": "MSPT · χρόνος τικ",
@@ -305,8 +299,6 @@
"Patch notes": "Patch σημειώσεις",
"Your Minecraft server, {online}.": "Ο διακομιστής σας Minecraft, {online}.",
"Crash reports": "Αναφορές σφαλμάτων",
"Offline name · the game's own · plays": "Όνομα εκτός σύνδεσης · το δικό του παιχνίδι · παίζει",
"Slim arms": "Λεπτά μπράτσα",
"Asking GitHub about {owner}/{repo}…": "Ερώτηση στο GitHub για {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Λήψη του Minecraft {version} από το Mojang · {done} από {total} αρχεία",
"Could not save your choice: {error}": "Δεν ήταν δυνατή η αποθήκευση της επιλογής σας: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Τοπίο του Horizon. Επιλέξτε μια δική σας εικόνα PNG, JPEG ή WebP.",
"Not needed": "Δεν χρειάζεται",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Αυτή η έκδοση του προγράμματος εκκίνησης δεν έχει σύνδεση στη Microsoft (HORIZON_MSA_CLIENT_ID), επομένως δεν μπορεί να ξεκινήσει το παιχνίδι.",
"Offline name · plays": "Όνομα εκτός σύνδεσης · παίζει",
"Run the game through": "Τρέξτε το παιχνίδι",
"needed by another pack": "χρειάζεται ένα άλλο πακέτο",
"Older →": "Παλαιότερο →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "Δεν ήταν δυνατή η εκτέλεση {program}: {error}",
"Restart": "Επανεκκίνηση",
"Copied to the clipboard.": "Αντιγράφηκε στο πρόχειρο.",
"Your worlds, offline names and settings stay where they are.": "Οι κόσμοι σας, τα ονόματα και οι ρυθμίσεις εκτός σύνδεσης παραμένουν εκεί που είναι.",
"Send nothing": "Στείλτε τίποτα",
"Move to Trash": "Μετακίνηση στον Κάδο απορριμμάτων",
"Start from": "Ξεκινήστε από",
"Asking Mojang for its versions…": "Ζητώντας από την Mojang τις εκδόσεις της…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Ένα 64×64 (ή 64×32) skin PNG και ένα 64×32 cape PNG, που κρατά ο εκτοξευτής και δίνεται στο παιχνίδι όταν παίζει αυτό το όνομα. Το παιχνίδι σχεδιάζει τα προεπιλεγμένα skins προς το παρόν. τα χρησιμοποιεί όταν μπορεί. Το δέρμα και η κάπα ενός λογαριασμού Microsoft: προσεχώς.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Παίξτε εκτός σύνδεσης με άλλο όνομα και κάντε εναλλαγή από την επάνω γραμμή. Οι διαδικτυακοί διακομιστές δεν παίρνουν ονόματα εκτός σύνδεσης.",
"Report on Discord": "Έκθεση για τη διχόνοια",
"Export": "Εξαγωγή",
"Server": "Διακομιστής",
@@ -385,7 +373,6 @@
"No version installed yet.": "Καμία έκδοση δεν έχει εγκατασταθεί ακόμα.",
"Release": "Απελευθέρωση",
"Verified": "Επαληθεύτηκε",
"Choose a skin…": "Επιλέξτε δέρμα…",
"{instance} doesn't play its native mods yet: build the game with them.": "Το {instance} δεν παίζει ακόμα τα εγγενή του mods: φτιάξτε το παιχνίδι με αυτά.",
"Use jars from my instance…": "Χρησιμοποιήστε βάζα από την περίπτωσή μου…",
"Applications menu": "Μενού εφαρμογών",
@@ -409,7 +396,6 @@
"Open backups": "Ανοίξτε τα αντίγραφα ασφαλείας",
"The game is running: change packs in its own menus, or here once it is closed.": "Το παιχνίδι τρέχει: αλλάξτε πακέτα στα δικά του μενού ή εδώ μόλις κλείσει.",
"Check now": "Ελέγξτε τώρα",
"Choose a cape…": "Επιλέξτε μια κάπα…",
"Save": "Αποθήκευση",
"Folder": "Φάκελος",
"Searching…": "Αναζήτηση…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Αποσυνδεθείτε",
"When it starts": "Όταν ξεκινάει",
"{name}'s skin": "δέρμα {name}",
"Start": "Έναρξη",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Δεν απαιτείται εγκατάσταση Minecraft: Το Horizon το κατεβάζει από το Mojang για τον λογαριασμό σας.",
"Logs": "κούτσουρα",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Το λεκτικό σήμα, ενώ φορτώνεται η λίστα έκδοσης.",
"Playing offline": "Παίζει εκτός σύνδεσης",
"Sign in to Tailscale": "Συνδεθείτε στο Tailscale",
"Offline names without an account": "Ονόματα εκτός σύνδεσης χωρίς λογαριασμό",
"Help make Horizon faster and steadier?": "Βοηθήστε το Horizon να γίνει πιο γρήγορο και σταθερό;",
"Sign in to play": "Συνδεθείτε για να παίξετε",
"Ported": "Μεταφερόμενος",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Ενημερώστε αυτό το πρόγραμμα εκκίνησης με τον διαχειριστή πακέτων σας.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Κλείστε αυτό το πρόγραμμα εκκίνησης, μετακινήστε το στο {folder} και ανοίξτε το εκεί για να ενεργοποιήσετε τις ενημερώσεις.",
"Any MCP client": "Οποιοσδήποτε πελάτης MCP",
"{name}'s cape is kept.": "Το ακρωτήρι του {name} διατηρείται.",
"Not reviewed by the Horizon registry": "Δεν έχει ελεγχθεί από το μητρώο Horizon",
"Proxy": "Αντιπρόσωπος",
"Checking": "Έλεγχος",
"Updates": "Ενημερώσεις",
"Asking Microsoft…": "Ρωτώντας τη Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Προετοιμάστηκε για το Minecraft {version}, χωρίς τους ήχους του: το παιχνίδι θα είναι αθόρυβο. Προετοιμαστείτε ξανά για να τα αντιγράψετε από την εγκατάσταση του Minecraft.",
"Forget": "Ξεχάστε",
"Import a modpack…": "Εισαγωγή modpack…",
"Search versions": "Αναζήτηση εκδόσεων",
"failed": "απέτυχε",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Έφυγε: {line}.",
"Resource packs": "Πακέτα πόρων",
"yesterday": "χθες",
"No cape": "Χωρίς κάπα",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Μετά από κάθε συνεδρία: εκατοστημόρια χρόνου καρέ και ιστόγραμμα 14 κουβάδων, χρόνοι επιλογής, ώρες αιχμής μνήμης και εκκίνησης, με το μηχάνημά σας (OS, CPU και πυρήνες και ρολόγια, μέγεθος μνήμης, GPU, μνήμη και πρόγραμμα οδήγησης, τύπος μονάδας, μέγεθος οθόνης και ρυθμός ανανέωσης, φορητός υπολογιστής ή επιτραπέζιος υπολογιστής, σε μπαταρία ή όχι) και τις ρυθμίσεις που αλλάζουν την απόδοση.",
"Make a token": "Κάντε μια μάρκα",
"Added {names}: the game turns it on when the world opens.": "Προστέθηκε {names}: το παιχνίδι το ενεργοποιεί όταν ανοίγει ο κόσμος.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Κοινή χρήση: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Φίλοι στο ίδιο Wi-Fi: Multiplayer, Προσθήκη διακομιστή και, στη συνέχεια, επικολλήστε αυτήν τη διεύθυνση.",
"None yet: drop a .hshader or a shader pack .zip here.": "Κανένα ακόμα: ρίξτε ένα .hshader ή ένα πακέτο shader .zip εδώ.",
"Offline name · the game's own": "Όνομα εκτός σύνδεσης · το δικό του παιχνιδιού",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Τα εγγενή mods δεν είναι sandbox: εκτελούνται με πλήρη πρόσβαση στον υπολογιστή σας, όπως κάθε πρόγραμμα. Εγκαταστήστε μόνο mods των οποίων τους δημιουργούς εμπιστεύεστε. Για να παίξετε με ένα, δημιουργήστε το παιχνίδι στη σελίδα Mods. η πρώτη έκδοση κατεβάζει το Rust και διαρκεί 20 έως 30 λεπτά.",
"Your selected version only changes if you were playing the newest one.": "Η επιλεγμένη έκδοση αλλάζει μόνο εάν παίζατε την πιο πρόσφατη.",
"Multiplayer": "Multiplayer",
@@ -589,7 +569,6 @@
"the port": "το λιμάνι",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Η πηγή του {source}. Η κυκλοφορία του αποστέλλεται {file}, μια τροποποίηση περιεχομένου: η εγκατάσταση αυτών από το GitHub δεν υποστηρίζεται ακόμη.",
"Build anyway": "Χτίστε πάντως",
"A name, 3 to 16 letters": "Ένα όνομα, 3 έως 16 γράμματα",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Εγκαταστάθηκε {mods} από το GitHub ({source}). Δημιουργήστε το στη σελίδα Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Ρυθμίσεις, Κλειδιά, Δημιουργία διακριτικού πρόσβασης. Διατηρείται στο κλειδί αυτού του υπολογιστή και αποστέλλεται μόνο στο Tailscale.",
"{id} is up to date.": "Το {id} είναι ενημερωμένο.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Το διάβασα και το εμπιστεύομαι: εγκατάσταση",
"Close export": "Κλείσιμο εξαγωγής",
"Playing needs a prepared Horizon version (Play page).": "Η αναπαραγωγή χρειάζεται μια προετοιμασμένη έκδοση Horizon (σελίδα αναπαραγωγής).",
"Offline, the game's name": "Εκτός σύνδεσης, το όνομα του παιχνιδιού",
"From Horizon's registry": "Από το μητρώο του Horizon",
"Sounds": "Ήχοι",
"Edit…": "Επεξεργασία…",
@@ -637,12 +615,10 @@
"up to date": "ενημερωμένο",
"← Newer": "← Νεότερο",
"Downloading from Mojang · {done} of {total} files": "Λήψη από το Mojang · {done} από {total} αρχεία",
"{name}'s skin is kept.": "Το δέρμα του {name} διατηρείται.",
"Edit instance": "Επεξεργασία παρουσίας",
"Remove shortcut": "Κατάργηση συντόμευσης",
"{program} is not installed here (or not on the PATH): copy the config instead.": "Το {program} δεν είναι εγκατεστημένο εδώ (ή όχι στο PATH): αντιγράψτε το config.",
"No worlds to put in.": "Δεν υπάρχουν κόσμοι για να βάλετε μέσα.",
"Default skin": "Προεπιλεγμένο δέρμα",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Ένας σύνδεσμος προς ένα αποθετήριο (την πιο πρόσφατη κυκλοφορία του), μια κυκλοφορία, ένα υποκατάστημα ή μια ετικέτα ή μια δέσμευση. Το πρόγραμμα εκκίνησης εγκαθιστά ένα αρχείο ή δέσμευση ακριβούς έκδοσης, ποτέ ένα υποκατάστημα που μετακινείται.",
"Sign in with GitHub to rate": "Συνδεθείτε με το GitHub για να βαθμολογήσετε",
"Star on GitHub": "Δώστε αστέρι στο GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "παίζεται από {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Λογαριασμός Microsoft · και διαδικτυακοί διακομιστές",
"Offline · single player and LAN worlds": "Εκτός σύνδεσης · ένας παίκτης και κόσμοι LAN",
"Offline names": "Ονόματα εκτός σύνδεσης",
"Add a name": "Προσθήκη ονόματος",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 έως 16 γράμματα, αριθμοί ή κάτω παύλες. Μπορείτε επίσης να αλλάξετε όνομα από την επάνω γραμμή. Οι διαδικτυακοί διακομιστές δεν δέχονται ονόματα εκτός σύνδεσης.",
"Play online with your Microsoft account": "Παίξτε online με τον λογαριασμό σας Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Συνδεθείτε με τον λογαριασμό που κατέχει το Minecraft: Java Edition. Το όνομα και το skin σας σας ακολουθούν στους διαδικτυακούς διακομιστές, όπως και σε άλλους launchers.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Η σελίδα της ίδιας της Microsoft ανοίγει στο πρόγραμμα περιήγησής σας. Το Horizon δεν βλέπει ποτέ τον κωδικό πρόσβασής σας.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Konstruado de la postkonstrua paŝo de {name}",
"In use": "En uzo",
"Prepare": "Preparu",
"Developer options": "Opcioj por programistoj",
"{online} of {max} players": "{online} el {max} ludantoj",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Eldono). Play elŝutas ĝin de Mojang por via konto la unuan fojon, kun la Java kiun ĝi bezonas.",
"Close": "Fermu",
@@ -98,7 +97,6 @@
"From my install": "De mia instalo",
"the update failed: {error}": "la ĝisdatigo malsukcesis: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 de Mesa, do Vulkan elektas la alian karton.",
"New name": "Nova nomo",
"Dark": "Mallumo",
"Not now": "Ne nun",
"Use an access token…": "Uzu alirĵetonon...",
@@ -115,7 +113,6 @@
"Partly": "Parte",
"All": "Ĉiuj",
"Instance": "Instanco",
"Classic arms": "Klasikaj brakoj",
"Versions": "Versioj",
"Release build: slower to build, slightly faster game": "Liberiga konstruo: pli malrapida por konstrui, iomete pli rapida ludo",
"Performance build": "Efikeco-konstruo",
@@ -172,7 +169,6 @@
"about a minute left": "restas proksimume minuto",
"Cancel": "Nuligi",
"Add to {client}": "Aldoni al {client}",
"Skin…": "Haŭto…",
"Environment": "Medio",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Ili ofte ankoraŭ laboras kune. Se la konstruo malsukcesas, instalu versiojn faritajn por la sama Nokto.",
"Import an instance folder…": "Importi kazon-dosierujon...",
@@ -184,7 +180,6 @@
"newest stable version": "plej nova stabila versio",
"Choose image…": "Elektu bildon...",
"No worlds yet: they appear here once you play one.": "Ankoraŭ neniuj mondoj: ili aperas ĉi tie post kiam vi ludas unu.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Senretaj nomoj ludas sen Microsoft konto kiu posedas la ludon. Minecraft ankoraŭ venas de via propra instalo.",
"crash reports beside it": "kraŝraportoj apud ĝi",
"Install all": "Instalu ĉion",
"No group": "Neniu grupo",
@@ -202,7 +197,6 @@
"My instance": "Mia ekzemplo",
"Snapshot": "Antaŭversio",
"Gallery": "Galerio",
"Offline name": "Senkonekta nomo",
"Home": "Hejmo",
"Stopping": "Haltante",
"MSPT · tick time": "MSPT · tiktempo",
@@ -304,8 +298,6 @@
"Patch notes": "Patch notoj",
"Your Minecraft server, {online}.": "Via Minecraft servilo, {online}.",
"Crash reports": "Kraŝraportoj",
"Offline name · the game's own · plays": "Senkonekta nomo · la propra · ludoj de la ludo",
"Slim arms": "Sveltaj brakoj",
"Asking GitHub about {owner}/{repo}…": "Demandante GitHub pri {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Elŝutante Minecraft {version} el Mojang · {done} el {total} dosieroj",
"Could not save your choice: {error}": "Ne eblis konservi vian elekton: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "La pejzaĝo de Horizon. Elektu vian propran bildon PNG, JPEG aŭ WebP.",
"Not needed": "Ne necesas",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Ĉi tiu konstruo de la lanĉilo ne havas Microsoft ensaluti (HORIZON_MSA_CLIENT_ID), do ĝi ne povas komenci la ludon.",
"Offline name · plays": "Senreta nomo · ludas",
"Run the game through": "Kuru la ludon tra",
"needed by another pack": "bezonata de alia pako",
"Older →": "Pli malnova →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Ne eblis ruliĝi {program}: {error}",
"Restart": "Rekomencu",
"Copied to the clipboard.": "Kopiita al la tondujo.",
"Your worlds, offline names and settings stay where they are.": "Viaj mondoj, eksterretaj nomoj kaj agordoj restas kie ili estas.",
"Send nothing": "Sendu nenion",
"Move to Trash": "Movu al Rubujo",
"Start from": "Komencu de",
"Asking Mojang for its versions…": "Demandante Mojang pri ĝiaj versioj...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (aŭ 64×32) haŭto PNG kaj 64×32 kabo PNG, konservita de la lanĉilo kaj donita al la ludo kiam ĉi tiu nomo ludas. La ludo desegnas la defaŭltajn haŭtojn nuntempe; ĝi uzas ĉi tiujn unufoje ĝi povas. Haŭto kaj kabo de Microsoft konto: baldaŭ venos.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Ludu eksterrete sub alia nomo, kaj ŝanĝu de la supra trinkejo. Retaj serviloj ne prenas eksterretajn nomojn.",
"Report on Discord": "Raportu pri Discord",
"Export": "Eksporto",
"Server": "Servilo",
@@ -384,7 +372,6 @@
"No version installed yet.": "Ankoraŭ neniu versio instalita.",
"Release": "Eldono",
"Verified": "Kontrolita",
"Choose a skin…": "Elektu haŭton...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} ankoraŭ ne ludas siajn denaskajn modifojn: konstruu la ludon kun ili.",
"Use jars from my instance…": "Uzu kruĉojn de mia kazo...",
"Applications menu": "Menuo de Aplikoj",
@@ -408,7 +395,6 @@
"Open backups": "Malfermu sekurkopiojn",
"The game is running: change packs in its own menus, or here once it is closed.": "La ludo funkcias: ŝanĝu pakojn en siaj propraj menuoj, aŭ ĉi tie post kiam ĝi estas fermita.",
"Check now": "Kontrolu nun",
"Choose a cape…": "Elektu kabon...",
"Save": "Konservu",
"Folder": "Dosierujo",
"Searching…": "Serĉante…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Elsaluti",
"When it starts": "Kiam ĝi komenciĝas",
"{name}'s skin": "La haŭto de {name}",
"Start": "Komencu",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Ne necesas instali Minecraft: Horizon elŝutas ĝin de Mojang por via konto.",
"Logs": "Ŝtipoj",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "La vortmarko, dum la eldonolisto ŝarĝas.",
"Playing offline": "Ludante eksterrete",
"Sign in to Tailscale": "Ensalutu al Tailscale",
"Offline names without an account": "Senkonektaj nomoj sen konto",
"Help make Horizon faster and steadier?": "Ĉu helpi fari Horizon pli rapidan kaj stabilan?",
"Sign in to play": "Ensalutu por ludi",
"Ported": "Portita",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Ĝisdatigu ĉi tiun lanĉilon per via paka administrilo.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Fermu ĉi tiun lanĉilon, movu ĝin al {folder} kaj malfermu ĝin tie por ebligi ĝisdatigojn.",
"Any MCP client": "Ajna MCP-kliento",
"{name}'s cape is kept.": "La kabo de {name} estas konservita.",
"Not reviewed by the Horizon registry": "Ne reviziita de la Horizon registro",
"Proxy": "Prokurilo",
"Checking": "Kontrolado",
"Updates": "Ĝisdatigoj",
"Asking Microsoft…": "Demandante Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Preta por Minecraft {version}, sen ĝiaj sonoj: la ludo silentos. Preparu denove kopii ilin de via Minecraft instalo.",
"Forget": "Forgesu",
"Import a modpack…": "Importu modpakaĵon...",
"Search versions": "Serĉu versiojn",
"failed": "malsukcesis",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Forlasita: {line}.",
"Resource packs": "Pakoj de rimedoj",
"yesterday": "hieraŭ",
"No cape": "Neniu mantelo",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Post ĉiu sesio: kadrotempaj procentoj kaj 14-buketo histogramo, tick-tempoj, pinta memoro kaj starttempoj, kun via maŝino (OS, CPU kaj ĝiaj kernoj kaj horloĝoj, memorgrandeco, GPU, ĝia memoro kaj ŝoforo, veturtipo, ekrangrandeco kaj refreŝiga indico, tekkomputilo aŭ labortablo, sur baterio aŭ ne) kaj la agordoj kiuj ŝanĝas rendimenton.",
"Make a token": "Faru ĵetonon",
"Added {names}: the game turns it on when the world opens.": "Aldonita {names}: la ludo ŝaltas ĝin kiam la mondo malfermiĝas.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Kunhavita: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Amikoj sur la sama Wifi: Multiludanto, Aldonu Servilon, tiam algluu ĉi tiun adreson.",
"None yet: drop a .hshader or a shader pack .zip here.": "Ankoraŭ neniu: faligu .hshader aŭ shader-pakaĵon .zip ĉi tie.",
"Offline name · the game's own": "Senreta nomo · propra de la ludo",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Denaskaj modoj ne estas sablokesitaj: ili funkcias kun plena aliro al via komputilo, kiel iu ajn programo. Instalu nur modifojn, kies aŭtorojn vi fidas. Por ludi kun unu, konstruu la ludon sur la Mods-paĝo; la unua konstruo elŝutas Rust kaj daŭras 20 ĝis 30 minutojn.",
"Your selected version only changes if you were playing the newest one.": "Via elektita versio ŝanĝiĝas nur se vi ludis la plej novan.",
"Multiplayer": "Plurludanto",
@@ -587,7 +567,6 @@
"the port": "la haveno",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "La fonto de {source}. Ĝia eldonaĵo ekspedas {file}, enhavmodilon: instali tiujn de GitHub ankoraŭ ne estas subtenata.",
"Build anyway": "Konstruu ĉiukaze",
"A name, 3 to 16 letters": "Nomo, 3 ĝis 16 literoj",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Instalita {mods} de GitHub ({source}). Konstruu ĝin sur la paĝo Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Agordoj, Ŝlosiloj, Generu alirĵetonon. Ĝi estas konservita en la ŝlosilĉeno de ĉi tiu komputilo kaj nur sendita al Tailscale.",
"{id} is up to date.": "{id} estas ĝisdatigita.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Mi legas ĝin kaj fidas ĝin: instali",
"Close export": "Fermu eksporton",
"Playing needs a prepared Horizon version (Play page).": "Ludado bezonas pretan Horizon version (Ludpaĝo).",
"Offline, the game's name": "Senrete, la nomo de la ludo",
"From Horizon's registry": "El la registro de Horizon",
"Sounds": "Sonoj",
"Edit…": "Redaktu…",
@@ -635,12 +613,10 @@
"up to date": "ĝisdatigita",
"← Newer": "← Pli nova",
"Downloading from Mojang · {done} of {total} files": "Elŝuto de Mojang · {done} el {total} dosieroj",
"{name}'s skin is kept.": "La haŭto de {name} estas konservita.",
"Edit instance": "Redaktu ekzemplon",
"Remove shortcut": "Forigi ŝparvojon",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} ne estas instalita ĉi tie (aŭ ne sur la PATH): kopiu la agordon anstataŭe.",
"No worlds to put in.": "Neniuj mondoj por enmeti.",
"Default skin": "Defaŭlta haŭto",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Ligo al deponejo (ĝia lasta eldono), eldono, branĉo aŭ etikedo aŭ kommit. La lanĉilo instalas unu precizan eldondosieron aŭ kommit, neniam branĉon kiu moviĝas.",
"Sign in with GitHub to rate": "Ensalutu per GitHub por taksi",
"Star on GitHub": "Stelumi ĉe GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "ludita de {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft konto · interretaj serviloj ankaŭ",
"Offline · single player and LAN worlds": "Senrete · ununura ludanto kaj LAN-mondoj",
"Offline names": "Senkonektaj nomoj",
"Add a name": "Aldonu nomon",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 ĝis 16 literoj, ciferoj aŭ substrekoj. Ŝanĝu nomojn ankaŭ de la supra trinkejo. Retaj serviloj ne prenas eksterretajn nomojn.",
"Play online with your Microsoft account": "Ludu interrete per via Microsoft konto",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Ensalutu kun la konto, kiu posedas Minecraft: Java Eldono. Via nomo kaj haŭto venas al interretaj serviloj, kiel en aliaj lanĉiloj.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "La propra paĝo de Microsoft malfermiĝas en via retumilo. Horizon neniam vidas vian pasvorton.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Compilando el paso posterior a la compilación de {name}",
"In use": "En uso",
"Prepare": "Preparar",
"Developer options": "Opciones de desarrollador",
"{online} of {max} players": "{online} de {max} jugadores",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). La primera vez, Jugar lo descarga de Mojang para tu cuenta, junto con el Java que necesita.",
"Close": "Cerrar",
@@ -98,7 +97,6 @@
"From my install": "Desde mi instalación",
"the update failed: {error}": "la actualización falló: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 de Mesa, para que Vulkan elija la otra tarjeta.",
"New name": "Nuevo nombre",
"Dark": "Oscuro",
"Not now": "Ahora no",
"Use an access token…": "Usar un token de acceso…",
@@ -115,7 +113,6 @@
"Partly": "Parcial",
"All": "Todos",
"Instance": "Instancia",
"Classic arms": "Brazos clásicos",
"Versions": "Versiones",
"Release build: slower to build, slightly faster game": "Compilación release: tarda más, el juego va algo más rápido",
"Performance build": "Compilación de rendimiento",
@@ -172,7 +169,6 @@
"about a minute left": "queda un minuto aprox.",
"Cancel": "Cancelar",
"Add to {client}": "Añadir a {client}",
"Skin…": "Aspecto…",
"Environment": "Entorno",
"They often still work together. If the build fails, install versions made for the same Nightly.": "A menudo funcionan juntos de todos modos. Si la compilación falla, instala versiones hechas para la misma Nightly.",
"Import an instance folder…": "Importar una carpeta de instancia…",
@@ -184,7 +180,6 @@
"newest stable version": "última versión estable",
"Choose image…": "Elegir imagen…",
"No worlds yet: they appear here once you play one.": "Aún no hay mundos: aparecerán aquí cuando juegues en uno.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Los nombres sin conexión permiten jugar sin una cuenta de Microsoft que posea el juego. Minecraft sigue proviniendo de tu propia instalación.",
"crash reports beside it": "informes de fallos al lado",
"Install all": "Instalar todos",
"No group": "Sin grupo",
@@ -202,7 +197,6 @@
"My instance": "Mi instancia",
"Snapshot": "Instantánea",
"Gallery": "Galería",
"Offline name": "Nombre sin conexión",
"Home": "Inicio",
"Stopping": "Deteniendo",
"MSPT · tick time": "MSPT · tiempo de tick",
@@ -305,8 +299,6 @@
"Patch notes": "Notas de la versión",
"Your Minecraft server, {online}.": "Tu servidor de Minecraft, {online}.",
"Crash reports": "Informes de fallos",
"Offline name · the game's own · plays": "Nombre sin conexión · propio del juego · en uso",
"Slim arms": "Brazos delgados",
"Asking GitHub about {owner}/{repo}…": "Consultando a GitHub sobre {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Descargando Minecraft {version} de Mojang · {done} de {total} archivos",
"Could not save your choice: {error}": "No se pudo guardar tu elección: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "El paisaje de Horizon. Elige tu propia imagen en PNG, JPEG o WebP.",
"Not needed": "No necesarios",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Esta compilación del lanzador no tiene inicio de sesión con Microsoft (HORIZON_MSA_CLIENT_ID), por lo que no puede iniciar el juego.",
"Offline name · plays": "Nombre sin conexión · jugando",
"Run the game through": "Ejecutar el juego a través de",
"needed by another pack": "necesario para otro paquete",
"Older →": "Anteriores →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "No se pudo ejecutar {program}: {error}",
"Restart": "Reiniciar",
"Copied to the clipboard.": "Copiado al portapapeles.",
"Your worlds, offline names and settings stay where they are.": "Tus mundos, nombres sin conexión y ajustes se mantienen en su lugar.",
"Send nothing": "No enviar nada",
"Move to Trash": "Mover a la papelera",
"Start from": "Empezar desde",
"Asking Mojang for its versions…": "Pidiendo a Mojang sus versiones…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Un PNG de aspecto de 64×64 (o 64×32) y un PNG de capa de 64×32, guardados por el lanzador y proporcionados al juego cuando juega con este nombre. Por ahora el juego muestra los aspectos por defecto; usará estos en cuanto sea posible. El aspecto y capa de una cuenta de Microsoft estarán disponibles pronto.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Juega sin conexión con otro nombre y cámbialo desde la barra superior. Los servidores en línea no aceptan nombres sin conexión.",
"Report on Discord": "Reportar en Discord",
"Export": "Exportar",
"Server": "Servidor",
@@ -385,7 +373,6 @@
"No version installed yet.": "Aún no hay ninguna versión instalada.",
"Release": "Versión",
"Verified": "Verificado",
"Choose a skin…": "Elegir un aspecto…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} aún no juega con sus mods nativos: compila el juego con ellos.",
"Use jars from my instance…": "Usar jars de mi instancia…",
"Applications menu": "Menú de aplicaciones",
@@ -409,7 +396,6 @@
"Open backups": "Abrir copias de seguridad",
"The game is running: change packs in its own menus, or here once it is closed.": "El juego está en ejecución: cambia los paquetes en sus propios menús o aquí cuando lo cierres.",
"Check now": "Comprobar ahora",
"Choose a cape…": "Elegir una capa…",
"Save": "Guardar",
"Folder": "Carpeta",
"Searching…": "Buscando…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Cerrar sesión",
"When it starts": "Al iniciar",
"{name}'s skin": "Aspecto de {name}",
"Start": "Iniciar",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "No hace falta tener Minecraft instalado: Horizon lo descarga de Mojang para tu cuenta.",
"Logs": "Registros",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "El logotipo mientras carga la lista de versiones.",
"Playing offline": "Jugando sin conexión",
"Sign in to Tailscale": "Iniciar sesión en Tailscale",
"Offline names without an account": "Nombres sin conexión sin cuenta",
"Help make Horizon faster and steadier?": "¿Nos ayudas a hacer Horizon más rápido y estable?",
"Sign in to play": "Inicia sesión para jugar",
"Ported": "Portados",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Actualiza este lanzador con tu gestor de paquetes.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Cierra este lanzador, muévelo a {folder} y ábrelo allí para permitir las actualizaciones.",
"Any MCP client": "Cualquier cliente MCP",
"{name}'s cape is kept.": "Se conserva la capa de {name}.",
"Not reviewed by the Horizon registry": "No revisado por el registro de Horizon",
"Proxy": "Proxy",
"Checking": "Comprobando",
"Updates": "Actualizaciones",
"Asking Microsoft…": "Consultando a Microsoft…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Preparado para Minecraft {version}, sin sonidos: el juego estará en silencio. Prepara de nuevo para copiarlos desde tu instalación de Minecraft.",
"Forget": "Olvidar",
"Import a modpack…": "Importar un modpack…",
"Search versions": "Buscar versiones",
"failed": "fallaron",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Omitido: {line}.",
"Resource packs": "Paquetes de recursos",
"yesterday": "ayer",
"No cape": "Sin capa",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Después de cada sesión: percentiles de tiempo de fotograma y un histograma de 14 intervalos, tiempos de tick, pico de memoria y tiempos de inicio, junto con tu equipo (SO, CPU con sus núcleos y frecuencias, tamaño de memoria, GPU con su memoria y controlador, tipo de disco, tamaño y tasa de refresco de pantalla, portátil o sobremesa, con batería o no) y los ajustes que afectan al rendimiento.",
"Make a token": "Crear un token",
"Added {names}: the game turns it on when the world opens.": "Se añadió {names}: el juego lo activa al abrir el mundo.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Compartido: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Amigos en el mismo Wi-Fi: Multijugador, Añadir servidor y pega esta dirección.",
"None yet: drop a .hshader or a shader pack .zip here.": "Aún no hay ninguno: suelta aquí un archivo .hshader o un paquete de shaders .zip.",
"Offline name · the game's own": "Nombre sin conexión · propio del juego",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Los mods nativos no están aislados: se ejecutan con acceso total a tu ordenador, como cualquier programa. Instala solo mods de autores en los que confíes. Para jugar con uno, compila el juego en la página Mods; la primera compilación descarga Rust y tarda de 20 a 30 minutos.",
"Your selected version only changes if you were playing the newest one.": "Tu versión seleccionada solo cambia si estabas jugando a la más reciente.",
"Multiplayer": "Multijugador",
@@ -589,7 +569,6 @@
"the port": "el puerto",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "El código fuente de {source}. Su versión incluye {file}, un mod de contenido: aún no se admite instalarlos desde GitHub.",
"Build anyway": "Compilar de todos modos",
"A name, 3 to 16 letters": "Un nombre, de 3 a 16 letras",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Se instaló {mods} desde GitHub ({source}). Compílalo en la página Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Settings, Keys, Generate access token. Se guarda en el llavero de este equipo y solo se envía a Tailscale.",
"{id} is up to date.": "{id} está actualizado.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Lo he leído y confío en él: instalar",
"Close export": "Cerrar exportación",
"Playing needs a prepared Horizon version (Play page).": "Para jugar se necesita una versión de Horizon preparada (página Inicio).",
"Offline, the game's name": "Sin conexión, el nombre en el juego",
"From Horizon's registry": "Del registro de Horizon",
"Sounds": "Sonidos",
"Edit…": "Editar…",
@@ -637,12 +615,10 @@
"up to date": "actualizado",
"← Newer": "← Más recientes",
"Downloading from Mojang · {done} of {total} files": "Descargando de Mojang · {done} de {total} archivos",
"{name}'s skin is kept.": "Se conserva el aspecto de {name}.",
"Edit instance": "Editar instancia",
"Remove shortcut": "Eliminar acceso directo",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} no está instalado aquí (o no está en el PATH): copia la configuración en su lugar.",
"No worlds to put in.": "No hay mundos para incluir.",
"Default skin": "Aspecto por defecto",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Un enlace a un repositorio (su última versión), una versión, una rama o etiqueta, o un commit. El lanzador instala un archivo de versión o commit exacto, nunca una rama cambiante.",
"Sign in with GitHub to rate": "Inicia sesión con GitHub para valorar",
"Star on GitHub": "Dar una estrella en GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "la juega {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Cuenta de Microsoft · también servidores en línea",
"Offline · single player and LAN worlds": "Sin conexión · un jugador y mundos LAN",
"Offline names": "Nombres sin conexión",
"Add a name": "Añadir un nombre",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "De 3 a 16 letras, números o guiones bajos. También puedes cambiar de nombre en la barra superior. Los servidores en línea no aceptan nombres sin conexión.",
"Play online with your Microsoft account": "Juega en línea con tu cuenta de Microsoft",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Inicia sesión con la cuenta que tiene Minecraft: Java Edition. Tu nombre y tu skin te acompañan a los servidores en línea, como en otros launchers.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "La propia página de Microsoft se abre en tu navegador. Horizon nunca ve tu contraseña.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Ehituse {name} ehitusjärgne samm",
"In use": "Kasutuses",
"Prepare": "Valmistage ette",
"Developer options": "Arendaja valikud",
"{online} of {max} players": "{online} {max} mängijast",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java väljaanne). Play laadib selle teie konto jaoks Mojangist esimest korda alla koos vajaliku Javaga.",
"Close": "Sule",
@@ -98,7 +97,6 @@
"From my install": "Minu installist",
"the update failed: {error}": "värskendamine ebaõnnestus: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesa DRI_PRIME=1, nii et Vulkan valib teise kaardi.",
"New name": "Uus nimi",
"Dark": "Tume",
"Not now": "Mitte praegu",
"Use an access token…": "Kasutage juurdepääsuluba…",
@@ -115,7 +113,6 @@
"Partly": "Osaliselt",
"All": "Kõik",
"Instance": "Eksemplar",
"Classic arms": "Klassikalised käed",
"Versions": "Versioonid",
"Release build: slower to build, slightly faster game": "Väljalaske ehitamine: aeglasem ehitamine, veidi kiirem mäng",
"Performance build": "Jõudluse ehitamine",
@@ -172,7 +169,6 @@
"about a minute left": "umbes minut jäänud",
"Cancel": "Tühista",
"Add to {client}": "Lisa {client}",
"Skin…": "Nahk…",
"Environment": "Keskkond",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Sageli töötavad nad endiselt koos. Kui ehitamine ebaõnnestub, installige sama Nightly jaoks loodud versioonid.",
"Import an instance folder…": "Eksemplari kausta importimine…",
@@ -184,7 +180,6 @@
"newest stable version": "uusim stabiilne versioon",
"Choose image…": "Vali pilt…",
"No worlds yet: they appear here once you play one.": "Pole veel maailmu: need ilmuvad siia, kui seda mängite.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Võrguühenduseta nimesid mängitakse ilma Microsofti kontota, millele mäng kuulub. Minecraft pärineb ikkagi teie enda installist.",
"crash reports beside it": "selle kõrval krahhiaruanded",
"Install all": "Installige kõik",
"No group": "Gruppi pole",
@@ -202,7 +197,6 @@
"My instance": "Minu näide",
"Snapshot": "Hetktõmmis",
"Gallery": "Galerii",
"Offline name": "Võrguühenduseta nimi",
"Home": "Kodu",
"Stopping": "Peatub",
"MSPT · tick time": "MSPT · tiksu aeg",
@@ -304,8 +298,6 @@
"Patch notes": "Patch märkmed",
"Your Minecraft server, {online}.": "Teie Minecrafti server, {online}.",
"Crash reports": "Krahhiaruanded",
"Offline name · the game's own · plays": "Võrguühenduseta nimi · mängu enda · mängib",
"Slim arms": "Õhukesed käed",
"Asking GitHub about {owner}/{repo}…": "GitHubi küsimine {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Minecrafti {version} allalaadimine Mojangist · {done} {total} failist",
"Could not save your choice: {error}": "Teie valikut ei saanud salvestada: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizoni maastik. Valige oma PNG-, JPEG- või WebP-pilt.",
"Not needed": "Pole vaja",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Sellel käivitusprogrammi järgul pole Microsofti sisselogimist (HORIZON_MSA_CLIENT_ID), seega ei saa see mängu käivitada.",
"Offline name · plays": "Võrguühenduseta nimi · mängib",
"Run the game through": "Käivitage mäng läbi",
"needed by another pack": "vajab teine pakk",
"Older →": "Vanem →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Ei saanud käivitada {program}: {error}",
"Restart": "Taaskäivitage",
"Copied to the clipboard.": "Kopeeritud lõikelauale.",
"Your worlds, offline names and settings stay where they are.": "Teie maailmad, võrguühenduseta nimed ja seaded jäävad sinna, kus nad on.",
"Send nothing": "Mitte midagi saata",
"Move to Trash": "Teisalda prügikasti",
"Start from": "Alustage alates",
"Asking Mojang for its versions…": "Mojangilt selle versioonide küsimine…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64 × 64 (või 64 × 32) skin PNG ja 64 × 32 cape PNG, mida hoiab kanderakett ja mis antakse mängule, kui see nimi mängib. Mäng loob praegu vaikenahad; ta kasutab neid, kui saab. Microsofti konto nahk ja keeb: peagi.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Mängige võrguühenduseta teise nime all ja lülituge ülevalt ribalt. Võrguserverid ei võta võrguühenduseta nimesid.",
"Report on Discord": "Raport Discordist",
"Export": "Ekspordi",
"Server": "Server",
@@ -384,7 +372,6 @@
"No version installed yet.": "Versiooni pole veel installitud.",
"Release": "Väljalase",
"Verified": "Kinnitatud",
"Choose a skin…": "Vali nahk…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} ei mängi veel oma algversioone: looge mäng nendega.",
"Use jars from my instance…": "Kasuta minu näite purke…",
"Applications menu": "Rakenduste menüü",
@@ -408,7 +395,6 @@
"Open backups": "Avage varukoopiad",
"The game is running: change packs in its own menus, or here once it is closed.": "Mäng töötab: muutke pakendeid oma menüüdes või siin, kui see on suletud.",
"Check now": "Kontrollige kohe",
"Choose a cape…": "Vali keep…",
"Save": "Salvesta",
"Folder": "Kaust",
"Searching…": "Otsimine…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Logi välja",
"When it starts": "Kui see algab",
"{name}'s skin": "{name} nahk",
"Start": "Alusta",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecrafti installi pole vaja: Horizon laadib selle teie konto jaoks alla Mojangist.",
"Logs": "Palgid",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Sõnamärk väljaannete loendi laadimise ajal.",
"Playing offline": "Mängib võrguühenduseta",
"Sign in to Tailscale": "Logige sisse Tailscale",
"Offline names without an account": "Võrguühenduseta nimed ilma kontota",
"Help make Horizon faster and steadier?": "Kas aidata muuta Horizon kiiremaks ja stabiilsemaks?",
"Sign in to play": "Mängimiseks logige sisse",
"Ported": "Teisaldatud",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Värskendage seda käivitajat oma paketihalduriga.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Sulgege see käivitaja, liigutage see kausta {folder} ja avage see seal, et värskendused sisse lülitada.",
"Any MCP client": "Iga MCP klient",
"{name}'s cape is kept.": "{name} keep on alles.",
"Not reviewed by the Horizon registry": "Horizoni register pole üle vaadanud",
"Proxy": "Puhverserver",
"Checking": "Kontrollimine",
"Updates": "Värskendused",
"Asking Microsoft…": "Microsoftilt küsides…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Ettevalmistatud Minecrafti jaoks {version}, ilma selle helideta: mäng vaikib. Valmistuge uuesti nende kopeerimiseks oma Minecrafti installist.",
"Forget": "Unusta",
"Import a modpack…": "Impordi modpack…",
"Search versions": "Otsige versioone",
"failed": "ebaõnnestunud",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Jäi välja: {line}.",
"Resource packs": "Ressursipaketid",
"yesterday": "eile",
"No cape": "Keebita",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Pärast iga seanssi: kaadriaja protsentiilid ja 14 salga histogramm, märkimisajad, tippmälu ja käivitusajad teie masinaga (OS, CPU ja selle tuumad ja kellad, mälu suurus, GPU, selle mälu ja draiver, draivi tüüp, ekraani suurus ja värskendussagedus, sülearvuti või lauaarvuti, akuga või mitte) ning jõudlust muutvad seaded.",
"Make a token": "Tee märk",
"Added {names}: the game turns it on when the world opens.": "Lisatud {names}: mäng lülitab selle sisse, kui maailm avaneb.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Jagatud: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Sõbrad samas WiFi-võrgus: mitmikmäng, lisa server, seejärel kleepige see aadress.",
"None yet: drop a .hshader or a shader pack .zip here.": "Veel pole: pukseerige siia .hshader või shaderi pakk.",
"Offline name · the game's own": "Võrguühenduseta nimi · mängu enda nimi",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Natiivsed modifikatsioonid ei ole liivakastis: need töötavad täieliku juurdepääsuga teie arvutile, nagu iga programm. Installige ainult modifikatsioonid, mille autoreid usaldate. Ühega mängimiseks ehitage mäng Modifikatsioonide lehele; esimene versioon laadib alla Rusti ja võtab aega 20–30 minutit.",
"Your selected version only changes if you were playing the newest one.": "Teie valitud versioon muutub ainult siis, kui mängisite uusimat versiooni.",
"Multiplayer": "Mitmikmäng",
@@ -587,7 +567,6 @@
"the port": "sadamasse",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "{source} allikas. Selle väljalase tarnitakse sisu modi {file}: nende installimist GitHubist veel ei toetata.",
"Build anyway": "Ehitage ikkagi",
"A name, 3 to 16 letters": "Nimi, 3 kuni 16 tähte",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Installitud {mods} GitHubist ({source}). Ehitage see lehel Modifikatsioonid.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Seaded, Võtmed, Loo juurdepääsuluba. Seda hoitakse selle arvuti võtmehoidjas ja saadetakse ainult Tailscale'ile.",
"{id} is up to date.": "{id} on ajakohane.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Lugesin seda ja usaldan: installige",
"Close export": "Sule eksport",
"Playing needs a prepared Horizon version (Play page).": "Mängimiseks on vaja ettevalmistatud Horizoni versiooni (leht Mängi).",
"Offline, the game's name": "Võrguühenduseta, mängu nimi",
"From Horizon's registry": "Horizoni registrist",
"Sounds": "Helid",
"Edit…": "Muuda…",
@@ -635,12 +613,10 @@
"up to date": "ajakohane",
"← Newer": "← Uuem",
"Downloading from Mojang · {done} of {total} files": "Mojangist allalaadimine · {done} {total} failist",
"{name}'s skin is kept.": "{name} nahk jääb alles.",
"Edit instance": "Redigeeri eksemplari",
"Remove shortcut": "Eemalda otsetee",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} pole siia installitud (või mitte PATH-le): kopeerige selle asemel konfiguratsioon.",
"No worlds to put in.": "Pole maailmu, mida sisse panna.",
"Default skin": "Vaikimisi nahk",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Link hoidlale (selle uusimale väljalasele), väljalasele, harule või märgendile või kohustusele. Käivitaja installib ühe täpse väljalaskefaili või commit, mitte kunagi liigutavat haru.",
"Sign in with GitHub to rate": "Hindamiseks logige GitHubiga sisse",
"Star on GitHub": "Anna GitHubis täht",
@@ -1055,9 +1031,7 @@
"1 hour": "1 tund",
"1 hour ago": "1 tund tagasi",
"1 line": "1 rida",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 kuni 16 tähte, numbrit või alakriipsu. Nime saab vahetada ka ülaribalt. Võrguserverid võrguühenduseta nimesid ei võta.",
"Accent colour, glass, blur, language and the options above go back to how Horizon ships.": "Aktsentvärv, klaas, hägu, keel ja ülaltoodud valikud lähevad tagasi Horizoni algseadetele.",
"Add a name": "Lisage nimi",
"Colours the buttons, the switches and the sky. Pick one, or type any hex colour.": "Värvib nupud, lülitid ja taeva. Valige üks või sisestage mis tahes hex-värv.",
"Copied the picture": "Pilt kopeeritud",
"Copied {text}": "Kopeeritud: {text}",
@@ -1084,8 +1058,6 @@
"Native mods": "Natiivsed modifikatsioonid",
"Nightly": "Öine järk",
"Nothing matches “{query}”.": "Päringule „{query}” ei vasta midagi.",
"Offline names": "Võrguühenduseta nimed",
"Offline · single player and LAN worlds": "Võrguühenduseta · üksikmäng ja LAN-maailmad",
"Open the game folder": "Ava mängu kaust",
"Open {page}": "Ava {page}",
"Opened {path}": "Avatud: {path}",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "{name}-ren eraikuntza osteko urratsa eraikitzea",
"In use": "Erabiltzen",
"Prepare": "Prestatu",
"Developer options": "Garatzaileen aukerak",
"{online} of {max} players": "{max} jokalarietatik {online}",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edizioa). Play-k Mojang-etik deskargatzen du zure konturako lehen aldiz, behar duen Java-rekin.",
"Close": "Itxi",
@@ -98,7 +97,6 @@
"From my install": "Nire instalaziotik",
"the update failed: {error}": "eguneratzeak huts egin du: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesaren DRI_PRIME=1, beraz, Vulkan-ek beste karta hautatzen du.",
"New name": "Izen berria",
"Dark": "Iluna",
"Not now": "Orain ez",
"Use an access token…": "Erabili sarbide-token bat...",
@@ -115,7 +113,6 @@
"Partly": "Neurri batean",
"All": "Denak",
"Instance": "Instantzia",
"Classic arms": "Beso klasikoak",
"Versions": "Bertsioak",
"Release build: slower to build, slightly faster game": "Askatu eraikitzea: eraikitzeko motelagoa, joko apur bat azkarragoa",
"Performance build": "Errendimenduaren eraikuntza",
@@ -172,7 +169,6 @@
"about a minute left": "minutu bat inguru geratzen da",
"Cancel": "Utzi",
"Add to {client}": "Gehitu {client}",
"Skin…": "Azala...",
"Environment": "Ingurumena",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Askotan oraindik elkarrekin lan egiten dute. Eraikuntzak huts egiten badu, instalatu Nightly berdinerako egindako bertsioak.",
"Import an instance folder…": "Inportatu instantzia karpeta bat...",
@@ -184,7 +180,6 @@
"newest stable version": "bertsio egonkor berriena",
"Choose image…": "Aukeratu irudia…",
"No worlds yet: they appear here once you play one.": "Oraindik ez dago mundurik: bat jokatzen duzunean hemen agertzen dira.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Lineaz kanpoko izenak jokoaren jabea den Microsoft konturik gabe jokatzen dute. Minecraft oraindik zure instalaziotik dator.",
"crash reports beside it": "kraskadura-txostenak ondoan",
"Install all": "Instalatu guztiak",
"No group": "Talderik ez",
@@ -202,7 +197,6 @@
"My instance": "Nire kasua",
"Snapshot": "Aurrebertsioa",
"Gallery": "Galeria",
"Offline name": "Lineaz kanpoko izena",
"Home": "Hasiera",
"Stopping": "Gelditzen",
"MSPT · tick time": "MSPT · tick denbora",
@@ -304,8 +298,6 @@
"Patch notes": "Adabaki oharrak",
"Your Minecraft server, {online}.": "Zure Minecraft zerbitzaria, {online}.",
"Crash reports": "Kraskaduren txostenak",
"Offline name · the game's own · plays": "Lineaz kanpoko izena · jokoaren · antzezlanak",
"Slim arms": "Beso argalak",
"Asking GitHub about {owner}/{repo}…": "GitHub-i {owner}/{repo} buruz galdetzen…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Minecraft {version} deskargatzen Mojang-etik · {done} {total} fitxategietatik",
"Could not save your choice: {error}": "Ezin izan da zure aukera gorde: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizonren paisaia. Aukeratu PNG, JPEG edo WebP irudi bat.",
"Not needed": "Ez da beharrezkoa",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Abiarazlearen eraikuntza honek ez du Microsoft-en saioa hasteko (HORIZON_MSA_CLIENT_ID), beraz, ezin du jokoa hasi.",
"Offline name · plays": "Lineaz kanpoko izena · antzezlanak",
"Run the game through": "Exekutatu jokoa",
"needed by another pack": "beste pakete batek behar du",
"Older →": "Zaharragoak →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Ezin izan da exekutatu {program}: {error}",
"Restart": "Berrabiarazi",
"Copied to the clipboard.": "Arbelean kopiatu da.",
"Your worlds, offline names and settings stay where they are.": "Zure munduak, lineaz kanpoko izenak eta ezarpenak dauden lekuan geratzen dira.",
"Send nothing": "Ezer bidali",
"Move to Trash": "Eraman zaborrontzira",
"Start from": "Hasi",
"Asking Mojang for its versions…": "Mojang-i bere bertsioak galdetzen...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64×64 (edo 64×32) azala PNG eta 64×32 kapa PNG bat, abiarazleak gordeta eta izen hori jokatzen denean jokoari ematen zaiona. Jokoak azal lehenetsiak marrazten ditu oraingoz; horiek ahal duenean erabiltzen ditu. Microsoft kontu baten azala eta kapa: laster egongo da.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Jokatu lineaz kanpo beste izen batekin eta aldatu goiko barratik. Lineako zerbitzariek ez dituzte lineaz kanpoko izenak hartzen.",
"Report on Discord": "Discord-i buruzko txostena",
"Export": "Esportatu",
"Server": "Zerbitzaria",
@@ -384,7 +372,6 @@
"No version installed yet.": "Oraindik ez dago bertsiorik instalatu.",
"Release": "Argitalpena",
"Verified": "Egiaztatuta",
"Choose a skin…": "Aukeratu azala...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} oraindik ez ditu bere jatorrizko modak jokatzen: sortu jokoa haiekin.",
"Use jars from my instance…": "Erabili nire instantziako poteak...",
"Applications menu": "Aplikazioen menua",
@@ -408,7 +395,6 @@
"Open backups": "Ireki babeskopiak",
"The game is running: change packs in its own menus, or here once it is closed.": "Jokoa martxan dago: aldatu paketeak bere menuetan, edo hemen itxitakoan.",
"Check now": "Egiaztatu orain",
"Choose a cape…": "Aukeratu kapa bat...",
"Save": "Gorde",
"Folder": "Karpeta",
"Searching…": "Bilatzen…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Amaitu saioa",
"When it starts": "Hasten denean",
"{name}'s skin": "{name}ren azala",
"Start": "Hasi",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Ez da Minecraft instalatu behar: Horizon-k Mojang-etik deskargatzen du zure konturako.",
"Logs": "Erregistroak",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Hitz-marka, kaleratze-zerrenda kargatzen den bitartean.",
"Playing offline": "Lineaz kanpo jolasten",
"Sign in to Tailscale": "Hasi saioa Tailscale-n",
"Offline names without an account": "Lineaz kanpoko izenak konturik gabe",
"Help make Horizon faster and steadier?": "Horizon azkarrago eta egonkorrago egiten lagundu?",
"Sign in to play": "Hasi saioa jolasteko",
"Ported": "Portatua",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Eguneratu abiarazle hau zure pakete-kudeatzailearekin.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Itxi abiarazle hau, eraman {folder} karpetara eta ireki han eguneraketak gaitzeko.",
"Any MCP client": "Edozein MCP bezero",
"{name}'s cape is kept.": "{name}ren kapa gordetzen da.",
"Not reviewed by the Horizon registry": "Horizon erregistroak ez du berrikusi",
"Proxy": "Proxy",
"Checking": "Egiaztatzea",
"Updates": "Eguneraketak",
"Asking Microsoft…": "Microsoft-i galdetzen...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Minecraft {version}rako prestatua, soinurik gabe: jokoa isilduko da. Prestatu berriro zure Minecraft instalaziotik kopiatzeko.",
"Forget": "Ahaztu",
"Import a modpack…": "Inportatu modpack bat...",
"Search versions": "Bilatu bertsioak",
"failed": "huts egin zuen",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Ezkertuta: {line}.",
"Resource packs": "Baliabide paketeak",
"yesterday": "atzo",
"No cape": "Kaparik ez",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Saio bakoitzaren ondoren: fotograma-denboraren pertzentilak eta 14 ontziko histograma, tick-en denborak, memoria maximoa eta abiarazte-denborak, zure makinarekin (OS, CPU eta bere nukleoak eta erlojuak, memoria-tamaina, GPU, bere memoria eta kontrolatzailea, unitate mota, pantaila-tamaina eta freskatze-tasa, ordenagailu eramangarria edo mahaigaina, bateriarekin edo ez) eta errendimendua aldatzen duten ezarpenekin.",
"Make a token": "Egin token bat",
"Added {names}: the game turns it on when the world opens.": "{names} gehitua: mundua irekitzen denean jokoak pizten du.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Partekatua: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Wi-Fi berean dauden lagunak: Jokalari anitzeko, Gehitu zerbitzaria, eta itsatsi helbide hau.",
"None yet: drop a .hshader or a shader pack .zip here.": "Oraindik bat ere ez: jaregin .hshader edo .zip itzaltzaile pakete bat hemen.",
"Offline name · the game's own": "Lineaz kanpoko izena · jokoarena",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Natibozko modak ez daude sandboxed: zure ordenagailurako sarbide osoarekin exekutatzen dira, edozein programa bezala. Instalatu soilik haien egileak fidagarriak diren modak. Batekin jolasteko, eraiki ezazu jokoa Mods orrian; lehenengo eraikuntzak Rust deskargatzen du eta 20 eta 30 minutu behar ditu.",
"Your selected version only changes if you were playing the newest one.": "Hautatutako bertsioa berriena jotzen ari bazenu bakarrik aldatzen da.",
"Multiplayer": "Jokalari anitzekoa",
@@ -587,7 +567,6 @@
"the port": "portua",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "{source} iturria. Bere bertsioak {file} bidaltzen du, edukiaren mod bat: GitHub-eko horiek instalatzea ez da onartzen oraindik.",
"Build anyway": "Eraiki hala ere",
"A name, 3 to 16 letters": "Izen bat, 3 eta 16 letra artekoa",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "{mods} GitHub-etik ({source}) instalatu da. Eraiki ezazu Mods orrian.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Ezarpenak, Gakoak, Sortu sarbide-tokena. Ordenagailu honen giltzan gordetzen da eta Tailscale-ra soilik bidaltzen da.",
"{id} is up to date.": "{id} eguneratuta dago.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Irakurri dut eta fidatzen naiz: instalatu",
"Close export": "Itxi esportazioa",
"Playing needs a prepared Horizon version (Play page).": "Jolasak prestatutako Horizon bertsioa behar du (Play page).",
"Offline, the game's name": "Lineaz kanpo, jokoaren izena",
"From Horizon's registry": "Horizon-ren erregistrotik",
"Sounds": "Soinuak",
"Edit…": "Editatu…",
@@ -635,12 +613,10 @@
"up to date": "eguneratuta",
"← Newer": "← Berriagoa",
"Downloading from Mojang · {done} of {total} files": "Mojang-etik deskargatzen · {done} {total} fitxategietatik",
"{name}'s skin is kept.": "{name}ren azala mantentzen da.",
"Edit instance": "Editatu instantzia",
"Remove shortcut": "Kendu lasterbidea",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} ez dago hemen instalatuta (edo ez dago PATH-en): kopiatu konfigurazioa.",
"No worlds to put in.": "Ez dago mundurik jartzeko.",
"Default skin": "Azala lehenetsia",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Biltegi baterako esteka (bere azken bertsioa), bertsio batera, adar edo etiketa batera edo konpromezu batera. Abiarazleak kaleratze fitxategi edo konpromezu zehatz bat instalatzen du, inoiz ez mugitzen den adar bat.",
"Sign in with GitHub to rate": "Hasi saioa GitHub-ekin baloratzeko",
"Star on GitHub": "Eman izar bat GitHub-en",
@@ -1053,10 +1029,6 @@
"played by {names}": "{names}k jokatuta",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft kontua · lineako zerbitzariak ere",
"Offline · single player and LAN worlds": "Lineaz kanpo · jokalari bakarreko eta LAN munduak",
"Offline names": "Lineaz kanpoko izenak",
"Add a name": "Gehitu izen bat",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 eta 16 letra, zenbaki edo azpimarra. Aldatu izenak goiko barratik ere. Lineako zerbitzariek ez dituzte lineaz kanpoko izenak hartzen.",
"Play online with your Microsoft account": "Jokatu linean zure Microsoft kontuarekin",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Hasi saioa Minecraft: Java Edition jabea den kontuarekin. Zure izena eta azala lineako zerbitzarietara datoz, beste abiarazle batzuetan bezala.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsoft-en orria irekitzen da zure arakatzailean. Horizon ez du inoiz zure pasahitza ikusten.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "ساختن مرحله پس از ساخت {name}",
"In use": "در حال استفاده",
"Prepare": "آماده کنید",
"Developer options": "گزینه های توسعه دهنده",
"{online} of {max} players": "{online} از {max} بازیکن",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (نسخه جاوا). Play آن را برای اولین بار با جاوای مورد نیاز خود از Mojang برای حساب شما دانلود می کند.",
"Close": "بستن",
@@ -98,7 +97,6 @@
"From my install": "از نصب من",
"the update failed: {error}": "به روز رسانی انجام نشد: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesa DRI_PRIME=1 است، بنابراین Vulkan کارت دیگر را انتخاب می کند.",
"New name": "نام جدید",
"Dark": "تاریک",
"Not now": "الان نه",
"Use an access token…": "استفاده از رمز دسترسی…",
@@ -115,7 +113,6 @@
"Partly": "تا حدی",
"All": "همه",
"Instance": "نمونه",
"Classic arms": "بازوهای کلاسیک",
"Versions": "نسخه ها",
"Release build: slower to build, slightly faster game": "نسخه انتشار: ساخت بازی کندتر، بازی کمی سریعتر",
"Performance build": "ساخت عملکرد",
@@ -172,7 +169,6 @@
"about a minute left": "حدود یک دقیقه باقی مانده است",
"Cancel": "لغو کنید",
"Add to {client}": "افزودن به {client}",
"Skin…": "پوست…",
"Environment": "محیط زیست",
"They often still work together. If the build fails, install versions made for the same Nightly.": "آنها اغلب هنوز با هم کار می کنند. اگر ساخت با شکست مواجه شد، نسخه های ساخته شده برای همان Nightly را نصب کنید.",
"Import an instance folder…": "وارد کردن یک پوشه نمونه…",
@@ -184,7 +180,6 @@
"newest stable version": "جدیدترین نسخه پایدار",
"Choose image…": "انتخاب تصویر…",
"No worlds yet: they appear here once you play one.": "هنوز جهانی وجود ندارد: وقتی یکی را بازی کردید اینجا ظاهر می شوند.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "نام‌های آفلاین بدون حساب مایکروسافت که مالک بازی است، بازی می‌کنند. Minecraft هنوز از طریق نصب خودتان می آید.",
"crash reports beside it": "گزارش های خرابی در کنار آن",
"Install all": "همه را نصب کنید",
"No group": "بدون گروه",
@@ -202,7 +197,6 @@
"My instance": "نمونه من",
"Snapshot": "عکس فوری",
"Gallery": "گالری",
"Offline name": "نام آفلاین",
"Home": "صفحه اصلی",
"Stopping": "توقف",
"MSPT · tick time": "MSPT · زمان تیک",
@@ -305,8 +299,6 @@
"Patch notes": "پچ یادداشت ها",
"Your Minecraft server, {online}.": "سرور Minecraft شما، {online}.",
"Crash reports": "گزارش های خرابی",
"Offline name · the game's own · plays": "نام آفلاین · خود بازی · بازی می کند",
"Slim arms": "بازوهای باریک",
"Asking GitHub about {owner}/{repo}…": "سؤال از GitHub درباره {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "دانلود Minecraft {version} از موجنگ · {done} از {total} فایل",
"Could not save your choice: {error}": "انتخاب شما ذخیره نشد: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "منظرهٔ Horizon. یک عکس PNG، JPEG یا WebP از خودتان انتخاب کنید.",
"Not needed": "مورد نیاز نیست",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "این ساختنی از راه‌انداز هیچ ورود به سیستم مایکروسافت (HORIZON_MSA_CLIENT_ID) ندارد، بنابراین نمی‌تواند بازی را شروع کند.",
"Offline name · plays": "نام آفلاین · پخش می کند",
"Run the game through": "بازی را اجرا کنید",
"needed by another pack": "یک بسته دیگر مورد نیاز است",
"Older →": "قدیمی تر →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "اجرا نشد {program}: {error}",
"Restart": "راه اندازی مجدد",
"Copied to the clipboard.": "در کلیپ بورد کپی شد.",
"Your worlds, offline names and settings stay where they are.": "جهان‌ها، نام‌های آفلاین و تنظیمات شما در جایی که هستند باقی می‌مانند.",
"Send nothing": "چیزی ارسال نکنید",
"Move to Trash": "به سطل زباله بروید",
"Start from": "شروع از",
"Asking Mojang for its versions…": "درخواست از Mojang برای نسخه های آن…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "یک PNG پوسته 64×64 (یا 64×32) و یک PNG شنل 64×32 که توسط لانچر نگهداری می شود و در هنگام پخش این نام به بازی داده می شود. بازی در حال حاضر پوسته های پیش فرض را ترسیم می کند. زمانی که بتواند از اینها استفاده می کند. پوسته و شنل حساب مایکروسافت: به زودی.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "با نام دیگری به صورت آفلاین بازی کنید و از نوار بالا جابجا شوید. سرورهای آنلاین اسامی آفلاین نمی گیرند.",
"Report on Discord": "گزارش در مورد اختلاف",
"Export": "صادرات",
"Server": "سرور",
@@ -385,7 +373,6 @@
"No version installed yet.": "هنوز نسخه ای نصب نشده است.",
"Release": "رها کنید",
"Verified": "تایید شده است",
"Choose a skin…": "انتخاب پوست…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} هنوز مدهای اصلی خود را بازی نمی کند: بازی را با آنها بسازید.",
"Use jars from my instance…": "از شیشه های نمونه من استفاده کنید…",
"Applications menu": "منوی برنامه ها",
@@ -409,7 +396,6 @@
"Open backups": "نسخه های پشتیبان را باز کنید",
"The game is running: change packs in its own menus, or here once it is closed.": "بازی در حال اجرا است: بسته ها را در منوهای خودش تغییر دهید، یا بعد از بسته شدن در اینجا.",
"Check now": "اکنون بررسی کنید",
"Choose a cape…": "شنل انتخاب کنید…",
"Save": "ذخیره کنید",
"Folder": "پوشه",
"Searching…": "در حال جستجو…",
@@ -423,7 +409,6 @@
"MangoHud": "منگوهد",
"Sign out": "از سیستم خارج شوید",
"When it starts": "وقتی شروع می شود",
"{name}'s skin": "پوست {name}",
"Start": "شروع کنید",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "بدون نیاز به نصب Minecraft: Horizon آن را از Mojang برای حساب شما دانلود می کند.",
"Logs": "سیاههها",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "علامت کلمه، در حالی که لیست انتشار بارگیری می شود.",
"Playing offline": "در حال پخش آفلاین",
"Sign in to Tailscale": "وارد Tailscale شوید",
"Offline names without an account": "نام های آفلاین بدون حساب",
"Help make Horizon faster and steadier?": "به ساخت Horizon سریعتر و پایدارتر کمک می کنید؟",
"Sign in to play": "برای بازی وارد شوید",
"Ported": "منتقل شده است",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "این لانچر را با مدیر بسته خود به‌روزرسانی کنید.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "این لانچر را ببندید، آن را به {folder} منتقل کنید و برای فعال شدن به‌روزرسانی‌ها از همان‌جا بازش کنید.",
"Any MCP client": "هر مشتری MCP",
"{name}'s cape is kept.": "شنل {name} نگهداری می شود.",
"Not reviewed by the Horizon registry": "توسط رجیستری Horizon بررسی نشده است",
"Proxy": "پروکسی",
"Checking": "چک کردن",
"Updates": "به روز رسانی ها",
"Asking Microsoft…": "سوال از مایکروسافت…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "آماده برای Minecraft {version}، بدون صداهای آن: بازی بی صدا خواهد بود. دوباره آماده شوید تا آنها را از نصب Minecraft خود کپی کنید.",
"Forget": "فراموش کن",
"Import a modpack…": "وارد کردن modpack…",
"Search versions": "جستجو در نسخه ها",
"failed": "شکست خورد",
@@ -506,7 +488,6 @@
"Left off: {line}.": "متوقف شد: {line}.",
"Resource packs": "بسته های منابع",
"yesterday": "دیروز",
"No cape": "بدون شنل",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "بعد از هر جلسه: صدک‌های فریم زمان و یک هیستوگرام 14 سطلی، زمان‌های تیک، حافظه اوج و زمان راه‌اندازی، با دستگاه شما (سیستم‌عامل، CPU و هسته‌ها و ساعت‌های آن، اندازه حافظه، GPU، حافظه و درایور آن، نوع درایو، اندازه صفحه نمایش و نرخ تازه‌سازی، لپ‌تاپ یا دسکتاپ، روی باتری یا نه) و تنظیماتی که عملکرد را تغییر می‌دهند.",
"Make a token": "یک ژتون درست کنید",
"Added {names}: the game turns it on when the world opens.": "اضافه شده {names}: وقتی جهان باز می شود، بازی آن را روشن می کند.",
@@ -559,7 +540,6 @@
"Shared: {url}": "به اشتراک گذاشته شده: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "دوستانی که از یک Wi-Fi استفاده می کنند: چند نفره، افزودن سرور، سپس این آدرس را جایگذاری کنید.",
"None yet: drop a .hshader or a shader pack .zip here.": "هنوز هیچ کدام: یک .hshader یا یک بسته shader .zip را اینجا بگذارید.",
"Offline name · the game's own": "نام آفلاین · متعلق به بازی",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "حالت‌های بومی سندباکس نیستند: آنها مانند هر برنامه‌ای با دسترسی کامل به رایانه شما اجرا می‌شوند. فقط مدهایی را نصب کنید که به نویسندگان آنها اعتماد دارید. برای بازی با یکی، بازی را در صفحه Mods بسازید. اولین بیلد Rust را دانلود می کند و 20 تا 30 دقیقه طول می کشد.",
"Your selected version only changes if you were playing the newest one.": "نسخه انتخابی شما تنها در صورتی تغییر می‌کند که در حال بازی کردن جدیدترین نسخه باشید.",
"Multiplayer": "چند نفره",
@@ -589,7 +569,6 @@
"the port": "بندر",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "منبع {source}. انتشار آن {file}، یک مد محتوا است: نصب آن‌ها از GitHub هنوز پشتیبانی نمی‌شود.",
"Build anyway": "به هر حال بساز",
"A name, 3 to 16 letters": "یک نام، 3 تا 16 حرف",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "نصب {mods} از GitHub ({source}). آن را در صفحه Mods بسازید.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "تنظیمات، کلیدها، ایجاد نشانه دسترسی. در دسته کلید این رایانه نگهداری می شود و فقط به Tailscale ارسال می شود.",
"{id} is up to date.": "{id} به روز است.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "من آن را خواندم و به آن اعتماد کردم: نصب کنید",
"Close export": "بستن صادرات",
"Playing needs a prepared Horizon version (Play page).": "بازی به نسخه آماده شده Horizon (صفحه Play) نیاز دارد.",
"Offline, the game's name": "آفلاین، نام بازی",
"From Horizon's registry": "از رجیستری Horizon",
"Sounds": "صداها",
"Edit…": "ویرایش…",
@@ -637,12 +615,10 @@
"up to date": "به روز",
"← Newer": "← جدیدتر",
"Downloading from Mojang · {done} of {total} files": "دانلود از موجنگ · {done} از {total} فایل",
"{name}'s skin is kept.": "پوست {name} نگهداری می شود.",
"Edit instance": "ویرایش نمونه",
"Remove shortcut": "حذف میانبر",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} در اینجا نصب نشده است (یا در PATH نیست): به جای آن پیکربندی را کپی کنید.",
"No worlds to put in.": "دنیایی برای گذاشتن وجود ندارد.",
"Default skin": "پوسته پیش فرض",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "پیوندی به یک مخزن (آخرین نسخه آن)، یک نسخه، یک شاخه یا برچسب یا یک commit. راه‌انداز یک فایل انتشار دقیق یا commit را نصب می‌کند، نه شاخه‌ای که حرکت می‌کند.",
"Sign in with GitHub to rate": "برای امتیاز دهی با GitHub وارد شوید",
"Star on GitHub": "ستاره دادن در GitHub",
@@ -1055,10 +1031,6 @@
"played by {names}": "بازی توسط {names}",
"{day}, {time} UTC": "{day}، {time} UTC",
"Microsoft account · online servers too": "حساب Microsoft · سرورهای آنلاین هم",
"Offline · single player and LAN worlds": "آفلاین · تک‌نفره و جهان‌های LAN",
"Offline names": "نام‌های آفلاین",
"Add a name": "افزودن نام",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 تا 16 حرف، عدد یا زیرخط. از نوار بالا هم می‌توانید نام را عوض کنید. سرورهای آنلاین نام‌های آفلاین را نمی‌پذیرند.",
"Play online with your Microsoft account": "با حساب Microsoft خود آنلاین بازی کنید",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "با حسابی وارد شوید که مالک Minecraft: Java Edition است. نام و اسکین شما مثل لانچرهای دیگر به سرورهای آنلاین هم می‌آید.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "صفحهٔ خود Microsoft در مرورگرتان باز می‌شود. Horizon هرگز رمز عبور شما را نمی‌بیند.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Rakennuksen {name} rakennusvaiheen jälkeinen vaihe",
"In use": "Käytössä",
"Prepare": "Valmistaudu",
"Developer options": "Kehittäjävaihtoehdot",
"{online} of {max} players": "{online}/{max} pelaajaa",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java-versio). Play lataa sen Mojangista tilillesi ensimmäistä kertaa tarvitsemallaan Javalla.",
"Close": "Sulje",
@@ -98,7 +97,6 @@
"From my install": "Omasta asennuksestani",
"the update failed: {error}": "päivitys epäonnistui: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "Mesan DRI_PRIME=1, joten Vulkan valitsee toisen kortin.",
"New name": "Uusi nimi",
"Dark": "Tumma",
"Not now": "Ei nyt",
"Use an access token…": "Käytä käyttöoikeustunnusta…",
@@ -115,7 +113,6 @@
"Partly": "Osittain",
"All": "Kaikki",
"Instance": "Esimerkki",
"Classic arms": "Klassiset käsivarret",
"Versions": "Versiot",
"Release build: slower to build, slightly faster game": "Julkaisun rakenne: hitaampi rakentaa, hieman nopeampi peli",
"Performance build": "Suorituskyvyn rakentaminen",
@@ -172,7 +169,6 @@
"about a minute left": "noin minuutti jäljellä",
"Cancel": "Peruuta",
"Add to {client}": "Lisää {client}",
"Skin…": "Iho…",
"Environment": "Ympäristö",
"They often still work together. If the build fails, install versions made for the same Nightly.": "He työskentelevät usein edelleen yhdessä. Jos rakentaminen epäonnistuu, asenna samalle Nightlylle tehdyt versiot.",
"Import an instance folder…": "Tuo ilmentymäkansio…",
@@ -184,7 +180,6 @@
"newest stable version": "uusin vakaa versio",
"Choose image…": "Valitse kuva…",
"No worlds yet: they appear here once you play one.": "Ei vielä maailmoja: ne näkyvät täällä, kun pelaat yhden.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline-nimet toimivat ilman pelin omistavaa Microsoft-tiliä. Minecraft tulee edelleen omasta asennuksestasi.",
"crash reports beside it": "kolariraportit sen vieressä",
"Install all": "Asenna kaikki",
"No group": "Ei ryhmää",
@@ -202,7 +197,6 @@
"My instance": "Minun esimerkkini",
"Snapshot": "Tilannekuva",
"Gallery": "Galleria",
"Offline name": "Offline-nimi",
"Home": "Kotiin",
"Stopping": "Pysähtyminen",
"MSPT · tick time": "MSPT · rastiaika",
@@ -305,8 +299,6 @@
"Patch notes": "Patch muistiinpanoja",
"Your Minecraft server, {online}.": "Minecraft-palvelimesi, {online}.",
"Crash reports": "Törmäysraportit",
"Offline name · the game's own · plays": "Offline-nimi · pelin oma · pelaaminen",
"Slim arms": "Ohut kädet",
"Asking GitHub about {owner}/{repo}…": "Kysymys GitHubista {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Ladataan Minecraftia {version} Mojangista · {done} / {total} tiedostoa",
"Could not save your choice: {error}": "Valintaasi ei voitu tallentaa: {error}",
@@ -355,7 +347,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizonin maisema. Valitse oma PNG-, JPEG- tai WebP-kuva.",
"Not needed": "Ei tarvita",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Tässä käynnistysohjelman koontiversiossa ei ole Microsoftin kirjautumista (HORIZON_MSA_CLIENT_ID), joten se ei voi käynnistää peliä.",
"Offline name · plays": "Offline-nimi · toistetaan",
"Run the game through": "Aja peli läpi",
"needed by another pack": "tarvitaan toinen pakkaus",
"Older →": "Vanhempi →",
@@ -366,13 +357,10 @@
"Could not run {program}: {error}": "Ei voitu suorittaa {program}: {error}",
"Restart": "Käynnistä uudelleen",
"Copied to the clipboard.": "Kopioitu leikepöydälle.",
"Your worlds, offline names and settings stay where they are.": "Maailmasi, offline-nimesi ja asetuksesi pysyvät ennallaan.",
"Send nothing": "Älä lähetä mitään",
"Move to Trash": "Siirrä roskakoriin",
"Start from": "Aloita alkaen",
"Asking Mojang for its versions…": "Mojangin versioiden kysyminen…",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "64 × 64 (tai 64 × 32) skin PNG ja 64 × 32 cape PNG, jotka kantoraketti säilyttää ja annetaan pelille, kun tämä nimi on käytössä. Peli piirtää toistaiseksi oletusskinet; se käyttää näitä kun voi. Microsoft-tilin skin and cap: tulossa pian.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Pelaa offline-tilassa toisella nimellä ja vaihda yläpalkista. Online-palvelimet eivät ota offline-nimiä.",
"Report on Discord": "Raportti Discordista",
"Export": "Vie",
"Server": "Palvelin",
@@ -385,7 +373,6 @@
"No version installed yet.": "Versiota ei ole vielä asennettu.",
"Release": "Vapauta",
"Verified": "Vahvistettu",
"Choose a skin…": "Valitse iho…",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} ei vielä toista alkuperäisiä modejaan: rakenna peli niiden avulla.",
"Use jars from my instance…": "Käytä purkkejani...",
"Applications menu": "Sovellukset-valikko",
@@ -409,7 +396,6 @@
"Open backups": "Avaa varmuuskopiot",
"The game is running: change packs in its own menus, or here once it is closed.": "Peli on käynnissä: vaihda paketteja sen omissa valikoissa tai täällä, kun se on suljettu.",
"Check now": "Tarkista nyt",
"Choose a cape…": "Valitse viitta…",
"Save": "Tallenna",
"Folder": "Kansio",
"Searching…": "Haetaan…",
@@ -423,7 +409,6 @@
"MangoHud": "MangoHud",
"Sign out": "Kirjaudu ulos",
"When it starts": "Kun se alkaa",
"{name}'s skin": "{name} ihoa",
"Start": "Aloita",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Minecraft-asennusta ei tarvita: Horizon lataa sen Mojangista tilillesi.",
"Logs": "Lokit",
@@ -447,7 +432,6 @@
"The wordmark, while the release list loads.": "Sanamerkki, kun julkaisuluettelo latautuu.",
"Playing offline": "Pelaa offline-tilassa",
"Sign in to Tailscale": "Kirjaudu sisään Tailscale-palveluun",
"Offline names without an account": "Offline-nimet ilman tiliä",
"Help make Horizon faster and steadier?": "Auttaa tekemään Horizonista nopeamman ja vakaamman?",
"Sign in to play": "Kirjaudu sisään pelataksesi",
"Ported": "Siirretty",
@@ -490,14 +474,12 @@
"Update this launcher with your package manager.": "Päivitä tämä käynnistysohjelma paketinhallinnallasi.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Sulje tämä käynnistysohjelma, siirrä se kansioon {folder} ja avaa se siellä, jotta päivitykset toimivat.",
"Any MCP client": "Mikä tahansa MCP-asiakas",
"{name}'s cape is kept.": "{name}:n viitta säilytetään.",
"Not reviewed by the Horizon registry": "Ei tarkistettu Horizon-rekisterissä",
"Proxy": "Välityspalvelin",
"Checking": "Tarkistetaan",
"Updates": "Päivitykset",
"Asking Microsoft…": "Kysymys Microsoftilta…",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Valmisteltu Minecraftille {version}, ilman sen ääniä: peli on hiljainen. Valmistaudu uudelleen kopioimaan ne Minecraft-asennuksestasi.",
"Forget": "Unohda",
"Import a modpack…": "Tuo modpack…",
"Search versions": "Hae versioita",
"failed": "epäonnistunut",
@@ -506,7 +488,6 @@
"Left off: {line}.": "Jäi pois: {line}.",
"Resource packs": "Resurssipaketit",
"yesterday": "eilen",
"No cape": "Ei viitta",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Jokaisen istunnon jälkeen: kehysajan prosenttipisteet ja 14 kauhan histogrammi, rastiajat, huippumuisti- ja käynnistysajat, koneesi kanssa (käyttöjärjestelmä, prosessori ja sen ytimet ja kellot, muistin koko, GPU, sen muisti ja ohjain, asematyyppi, näytön koko ja virkistystaajuus, kannettava tietokone tai pöytätietokone, akulla tai ei) ja suorituskykyä muuttavat asetukset.",
"Make a token": "Tee merkki",
"Added {names}: the game turns it on when the world opens.": "Lisätty {names}: peli käynnistää sen, kun maailma avautuu.",
@@ -559,7 +540,6 @@
"Shared: {url}": "Jaettu: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Ystävät samassa Wi-Fi-yhteydessä: Moninpeli, Lisää palvelin ja liitä tämä osoite.",
"None yet: drop a .hshader or a shader pack .zip here.": "Ei vielä mitään: pudota .hshader tai shader-paketti .zip tähän.",
"Offline name · the game's own": "Offline-nimi · pelin oma",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Natiivimodit eivät ole hiekkalaatikossa: ne toimivat täydellä pääsyllä tietokoneeseesi, kuten kaikki ohjelmat. Asenna vain modit, joiden kirjoittajiin luotat. Voit pelata yhdellä rakentamalla pelin Modit-sivulle; ensimmäinen versio lataa Rustin ja kestää 20–30 minuuttia.",
"Your selected version only changes if you were playing the newest one.": "Valitsemasi versio muuttuu vain, jos pelasit uusinta.",
"Multiplayer": "Moninpeli",
@@ -589,7 +569,6 @@
"the port": "satamaan",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Lähde {source}. Sen julkaisu toimitetaan {file}, sisältömodi: niiden asentamista GitHubista ei tueta vielä.",
"Build anyway": "Rakenna joka tapauksessa",
"A name, 3 to 16 letters": "Nimi, 3-16 kirjainta",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Asennettu {mods} GitHubista ({source}). Rakenna se Modit-sivulla.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Asetukset, Avaimet, Luo käyttöoikeustunnus. Sitä säilytetään tämän tietokoneen avainnipussa ja lähetetään vain Tailscalelle.",
"{id} is up to date.": "{id} on ajan tasalla.",
@@ -604,7 +583,6 @@
"I read it and trust it: install": "Luin sen ja luotan siihen: asenna",
"Close export": "Sulje vienti",
"Playing needs a prepared Horizon version (Play page).": "Pelaamiseen tarvitaan valmis Horizon-versio (Play-sivu).",
"Offline, the game's name": "Offline, pelin nimi",
"From Horizon's registry": "Horizonin rekisteristä",
"Sounds": "Äänet",
"Edit…": "Muokkaa…",
@@ -637,12 +615,10 @@
"up to date": "ajan tasalla",
"← Newer": "← Uudempi",
"Downloading from Mojang · {done} of {total} files": "Ladataan Mojangista · {done} / {total} tiedostoa",
"{name}'s skin is kept.": "{name}:n iho säilytetään.",
"Edit instance": "Muokkaa esiintymää",
"Remove shortcut": "Poista pikakuvake",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} ei ole asennettu tähän (tai ei polkuun): kopioi sen sijaan asetus.",
"No worlds to put in.": "Ei maailmoja, joihin laittaa.",
"Default skin": "Oletusskin",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Linkki arkistoon (sen uusimpaan julkaisuun), julkaisuun, haaraan tai tagiin tai sitoumukseen. Käynnistysohjelma asentaa yhden tarkan julkaisutiedoston tai commit, ei koskaan liikkuvaa haaraa.",
"Sign in with GitHub to rate": "Kirjaudu sisään GitHubilla arvioidaksesi",
"Star on GitHub": "Anna tähti GitHubissa",
@@ -1055,10 +1031,6 @@
"played by {names}": "pelasi {names}",
"{day}, {time} UTC": "{day} klo {time} UTC",
"Microsoft account · online servers too": "Microsoft-tili · myös verkkopalvelimet",
"Offline · single player and LAN worlds": "Offline · yksinpeli ja LAN-maailmat",
"Offline names": "Offline-nimet",
"Add a name": "Lisää nimi",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3–16 kirjainta, numeroa tai alaviivaa. Nimeä voi vaihtaa myös yläpalkista. Verkkopalvelimet eivät hyväksy offline-nimiä.",
"Play online with your Microsoft account": "Pelaa verkossa Microsoft-tililläsi",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Kirjaudu sisään tilillä, joka omistaa Minecraft: Java Editionin. Nimesi ja skinisi kulkevat mukanasi verkkopalvelimille, kuten muissakin käynnistysohjelmissa.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Microsoftin oma sivu avautuu selaimessasi. Horizon ei koskaan näe salasanaasi.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Pagbuo ng post-build na hakbang ni {name}",
"In use": "Ginagamit",
"Prepare": "Maghanda",
"Developer options": "Mga pagpipilian sa developer",
"{online} of {max} players": "{online} sa {max} manlalaro",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Edition). I-play ang pag-download nito mula sa Mojang para sa iyong account sa unang pagkakataon, kasama ang Java na kailangan nito.",
"Close": "Isara",
@@ -98,7 +97,6 @@
"From my install": "Mula sa aking pag-install",
"the update failed: {error}": "nabigo ang pag-update: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 ni Mesa, kaya pinili ni Vulkan ang isa pang card.",
"New name": "Bagong pangalan",
"Dark": "Madilim",
"Not now": "Hindi ngayon",
"Use an access token…": "Gumamit ng access token...",
@@ -115,7 +113,6 @@
"Partly": "Bahagyang",
"All": "Lahat",
"Instance": "Instance",
"Classic arms": "Mga klasikong armas",
"Versions": "Mga bersyon",
"Release build: slower to build, slightly faster game": "I-release ang build: mas mabagal na buuin, medyo mas mabilis na laro",
"Performance build": "Pagbuo ng pagganap",
@@ -172,7 +169,6 @@
"about a minute left": "humigit-kumulang isang minuto ang natitira",
"Cancel": "Kanselahin",
"Add to {client}": "Idagdag sa {client}",
"Skin…": "Balat…",
"Environment": "Kapaligiran",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Madalas pa rin silang magkatrabaho. Kung nabigo ang build, i-install ang mga bersyon na ginawa para sa parehong Nightly.",
"Import an instance folder…": "Mag-import ng instance folder...",
@@ -184,7 +180,6 @@
"newest stable version": "pinakabagong stable na bersyon",
"Choose image…": "Pumili ng larawan…",
"No worlds yet: they appear here once you play one.": "Wala pang mundo: lilitaw ang mga ito dito kapag naglaro ka ng isa.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Naglalaro ang mga offline na pangalan nang walang Microsoft account na nagmamay-ari ng laro. Ang Minecraft ay nagmula pa rin sa iyong sariling pag-install.",
"crash reports beside it": "mga ulat ng pag-crash sa tabi nito",
"Install all": "I-install lahat",
"No group": "Walang grupo",
@@ -202,7 +197,6 @@
"My instance": "Ang aking halimbawa",
"Snapshot": "Snapshot",
"Gallery": "Galeri",
"Offline name": "Offline na pangalan",
"Home": "Bahay",
"Stopping": "Humihinto",
"MSPT · tick time": "MSPT · oras ng tick",
@@ -304,8 +298,6 @@
"Patch notes": "Mga tala ng patch",
"Your Minecraft server, {online}.": "Ang iyong Minecraft server, {online}.",
"Crash reports": "Mga ulat ng pag-crash",
"Offline name · the game's own · plays": "Offline na pangalan · sariling laro · gumaganap",
"Slim arms": "Payat na bisig",
"Asking GitHub about {owner}/{repo}…": "Nagtatanong sa GitHub tungkol sa {owner}/{repo}…",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Dina-download ang Minecraft {version} mula sa Mojang · {done} ng {total} file",
"Could not save your choice: {error}": "Hindi ma-save ang iyong pinili: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "landscape ni Horizon. Pumili ng PNG, JPEG o WebP na larawan ng iyong sarili.",
"Not needed": "Hindi kailangan",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Ang build na ito ng launcher ay walang Microsoft sign-in (HORIZON_MSA_CLIENT_ID), kaya hindi nito masisimulan ang laro.",
"Offline name · plays": "Offline na pangalan · gumaganap",
"Run the game through": "Patakbuhin ang laro",
"needed by another pack": "kailangan ng isa pang pakete",
"Older →": "Mas matanda →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Hindi makatakbo {program}: {error}",
"Restart": "I-restart",
"Copied to the clipboard.": "Kinopya sa clipboard.",
"Your worlds, offline names and settings stay where they are.": "Ang iyong mga mundo, offline na pangalan at setting ay nananatili kung nasaan sila.",
"Send nothing": "Walang ipadala",
"Move to Trash": "Ilipat sa Basura",
"Start from": "Magsimula sa",
"Asking Mojang for its versions…": "Hinihiling kay Mojang ang mga bersyon nito...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Isang 64×64 (o 64×32) skin PNG at isang 64×32 cape PNG, na iniingatan ng launcher at ibinibigay sa laro kapag naglalaro ang pangalang ito. Ang laro ay kumukuha ng mga default na skin sa ngayon; ginagamit nito ang mga ito kapag kaya na nito. Ang balat at kapa ng isang Microsoft account: paparating na.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Maglaro offline sa ilalim ng ibang pangalan, at lumipat mula sa itaas na bar. Ang mga online na server ay hindi kumukuha ng mga offline na pangalan.",
"Report on Discord": "Ulat sa Discord",
"Export": "I-export",
"Server": "server",
@@ -384,7 +372,6 @@
"No version installed yet.": "Wala pang naka-install na bersyon.",
"Release": "Release",
"Verified": "Na-verify",
"Choose a skin…": "Pumili ng balat...",
"{instance} doesn't play its native mods yet: build the game with them.": "Hindi pa nilalaro ni {instance} ang mga katutubong mod nito: buuin ang laro sa kanila.",
"Use jars from my instance…": "Gumamit ng mga garapon mula sa aking halimbawa...",
"Applications menu": "Menu ng mga application",
@@ -408,7 +395,6 @@
"Open backups": "Buksan ang mga backup",
"The game is running: change packs in its own menus, or here once it is closed.": "Ang laro ay tumatakbo: baguhin ang mga pack sa sarili nitong mga menu, o dito kapag ito ay sarado.",
"Check now": "Suriin ngayon",
"Choose a cape…": "Pumili ng kapa...",
"Save": "I-save",
"Folder": "Folder",
"Searching…": "Naghahanap…",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Mag-sign out",
"When it starts": "Kapag nagsimula na",
"{name}'s skin": "Ang balat ni {name}",
"Start": "Magsimula",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Walang kinakailangang pag-install ng Minecraft: Horizon dina-download ito mula sa Mojang para sa iyong account.",
"Logs": "Mga log",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Ang wordmark, habang naglo-load ang listahan ng release.",
"Playing offline": "Nagpe-play offline",
"Sign in to Tailscale": "Mag-sign in sa Tailscale",
"Offline names without an account": "Mga offline na pangalan na walang account",
"Help make Horizon faster and steadier?": "Tumulong na gawing mas mabilis at matatag ang Horizon?",
"Sign in to play": "Mag-sign in para maglaro",
"Ported": "Na-port",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "I-update ang launcher na ito gamit ang iyong package manager.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Isara ang launcher na ito, ilipat ito sa {folder}, at buksan doon para i-enable ang mga update.",
"Any MCP client": "Anumang MCP client",
"{name}'s cape is kept.": "Ang kapa ni {name} ay itinatago.",
"Not reviewed by the Horizon registry": "Hindi nasuri ng Horizon registry",
"Proxy": "Proxy",
"Checking": "Sinusuri",
"Updates": "Mga update",
"Asking Microsoft…": "Nagtatanong sa Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Inihanda para sa Minecraft {version}, nang walang mga tunog nito: tatahimik ang laro. Maghanda muli upang kopyahin ang mga ito mula sa iyong pag-install sa Minecraft.",
"Forget": "Kalimutan",
"Import a modpack…": "Mag-import ng modpack...",
"Search versions": "Maghanap ng mga bersyon",
"failed": "nabigo",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Naiwan: {line}.",
"Resource packs": "Mga resource pack",
"yesterday": "kahapon",
"No cape": "Walang kapa",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Pagkatapos ng bawat session: frame-time percentiles at isang 14-bucket histogram, tick times, peak memory at startup times, kasama ang iyong machine (OS, CPU at mga core at orasan nito, laki ng memory, GPU, memory at driver nito, uri ng drive, laki ng screen at refresh rate, laptop o desktop, sa baterya o wala) at ang mga setting na nagbabago sa performance.",
"Make a token": "Gumawa ng token",
"Added {names}: the game turns it on when the world opens.": "Idinagdag {names}: ino-on ito ng laro kapag bumukas ang mundo.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Ibinahagi: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Mga kaibigan sa parehong Wi-Fi: Multiplayer, Magdagdag ng Server, pagkatapos ay i-paste ang address na ito.",
"None yet: drop a .hshader or a shader pack .zip here.": "Wala pa: mag-drop ng .hshader o isang shader pack .zip dito.",
"Offline name · the game's own": "Offline na pangalan · ang laro ng sarili",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Ang mga katutubong mod ay hindi naka-sandbox: tumatakbo ang mga ito nang may ganap na access sa iyong computer, tulad ng anumang program. Mag-install lamang ng mga mod na pinagkakatiwalaan mo ang mga may-akda. Upang maglaro ng isa, buuin ang laro sa pahina ng Mods; ang unang build ay nagda-download ng Rust at tumatagal ng 20 hanggang 30 minuto.",
"Your selected version only changes if you were playing the newest one.": "Nagbabago lang ang iyong napiling bersyon kung pinapatugtog mo ang pinakabago.",
"Multiplayer": "Multiplayer",
@@ -587,7 +567,6 @@
"the port": "ang daungan",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Ang pinagmulan ng {source}. Ang paglabas nito ay {file}, isang content mod: hindi pa sinusuportahan ang pag-install ng mga iyon mula sa GitHub.",
"Build anyway": "Bumuo pa rin",
"A name, 3 to 16 letters": "Isang pangalan, 3 hanggang 16 na letra",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Na-install ang {mods} mula sa GitHub ({source}). Buuin ito sa pahina ng Mods.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Mga Setting, Mga Susi, Bumuo ng token ng pag-access. Nakatago ito sa keychain ng computer na ito at ipinapadala lang sa Tailscale.",
"{id} is up to date.": "{id} ay napapanahon.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Binasa ko ito at pinagkakatiwalaan ko ito: i-install",
"Close export": "Isara ang pag-export",
"Playing needs a prepared Horizon version (Play page).": "Ang paglalaro ay nangangailangan ng inihandang Horizon na bersyon (I-play ang pahina).",
"Offline, the game's name": "Offline, ang pangalan ng laro",
"From Horizon's registry": "Mula sa rehistro ni Horizon",
"Sounds": "Mga tunog",
"Edit…": "I-edit…",
@@ -635,12 +613,10 @@
"up to date": "napapanahon",
"← Newer": "← Mas bago",
"Downloading from Mojang · {done} of {total} files": "Nagda-download mula sa Mojang · {done} ng {total} file",
"{name}'s skin is kept.": "Ang balat ni {name} ay pinananatili.",
"Edit instance": "I-edit ang instance",
"Remove shortcut": "Alisin ang shortcut",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} ay hindi naka-install dito (o wala sa PATH): kopyahin ang config sa halip.",
"No worlds to put in.": "Walang mga mundong malalagay.",
"Default skin": "Default na balat",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Isang link sa isang repository (pinakabago nitong release), isang release, isang branch o tag, o isang commit. Ang launcher ay nag-i-install ng isang eksaktong release file o commit, hindi isang sangay na gumagalaw.",
"Sign in with GitHub to rate": "Mag-sign in gamit ang GitHub para mag-rate",
"Star on GitHub": "I-star sa GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "nilalaro ni {names}",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft account · mga online server din",
"Offline · single player and LAN worlds": "Offline · single player at LAN mundo",
"Offline names": "Mga offline na pangalan",
"Add a name": "Magdagdag ng pangalan",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 hanggang 16 na titik, numero o underscore. Magpalit din ng mga pangalan mula sa itaas na bar. Ang mga online na server ay hindi kumukuha ng mga offline na pangalan.",
"Play online with your Microsoft account": "Maglaro online gamit ang iyong Microsoft account",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Mag-sign in gamit ang account na nagmamay-ari ng Minecraft: Java Edition. Ang iyong pangalan at balat ay kasama sa mga online na server, tulad ng sa iba pang mga launcher.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Ang sariling pahina ng Microsoft ay bubukas sa iyong browser. Hindi kailanman nakikita ni Horizon ang iyong password.",
-28
View File
@@ -37,7 +37,6 @@
"Building {name}'s post-build step": "Bygging {name}'s eftirbyggingarstigið",
"In use": "Í nýtslu",
"Prepare": "Fyrireika",
"Developer options": "Forritararmøguleikar",
"{online} of {max} players": "{online} av {max} spælarum",
"Minecraft {version} (Java Edition). Play downloads it from Mojang for your account the first time, with the Java it needs.": "Minecraft {version} (Java Útgáva). Play heinta tað frá Mojang til tína kontu fyrstu ferð, við tí Java tað hevur brúk fyri.",
"Close": "Lat aftur",
@@ -98,7 +97,6 @@
"From my install": "Frá mínari uppseting",
"the update failed: {error}": "dagføringin miseydnaðist: {error}",
"Mesa's DRI_PRIME=1, so Vulkan picks the other card.": "DRI_PRIME=1 hjá Mesa, so velur Vulkan hitt kortið.",
"New name": "Nýtt navn",
"Dark": "Myrkt",
"Not now": "Ikki nú",
"Use an access token…": "Brúka eitt atgongdarmerki...",
@@ -115,7 +113,6 @@
"Partly": "Partvís",
"All": "Øll",
"Instance": "Uppseting",
"Classic arms": "Klassiskir armar",
"Versions": "Útgávur",
"Release build: slower to build, slightly faster game": "Útgáva bygging: hægri at byggja, eitt sindur skjótari spæl",
"Performance build": "Avrikið byggi",
@@ -172,7 +169,6 @@
"about a minute left": "umleið ein minuttur eftir",
"Cancel": "Avlýs",
"Add to {client}": "Legg til {client}",
"Skin…": "Húð...",
"Environment": "Umhvørvi",
"They often still work together. If the build fails, install versions made for the same Nightly.": "Tey arbeiða ofta enn saman. Um byggingin miseydnast, skalt tú seta útgávur upp, sum eru gjørdar til sama Nightly.",
"Import an instance folder…": "Innflyt eina instansmappu...",
@@ -184,7 +180,6 @@
"newest stable version": "nýggjasta støðuga útgávan",
"Choose image…": "Vel mynd...",
"No worlds yet: they appear here once you play one.": "Ongin heimur enn: teir koma fram her tá tú einaferð hevur spælt ein.",
"Offline names play without a Microsoft account that owns the game. Minecraft still comes from your own install.": "Offline nøvn spæla uttan eina Microsoft kontu, sum eigur spælið. Minecraft kemur enn frá egnari uppseting.",
"crash reports beside it": "feilfrágreiðingar við síðuna av henni",
"Install all": "Set øll upp",
"No group": "Eingin bólkur",
@@ -202,7 +197,6 @@
"My instance": "Mítt dømi",
"Snapshot": "Snapshot",
"Gallery": "Myndasavn",
"Offline name": "Navn uttan net",
"Home": "Heim",
"Stopping": "Steðgar",
"MSPT · tick time": "MSPT · tikktíð",
@@ -304,8 +298,6 @@
"Patch notes": "Plástur viðmerkingar",
"Your Minecraft server, {online}.": "Tín Minecraft ambætari, {online}.",
"Crash reports": "Feilfrágreiðingar",
"Offline name · the game's own · plays": "Offline navn · spælið egna · spælir",
"Slim arms": "Slankir armar",
"Asking GitHub about {owner}/{repo}…": "Spyrja GitHub um {owner}/{repo}...",
"Downloading Minecraft {version} from Mojang · {done} of {total} files": "Heinta Minecraft {version} frá Mojang · {done} av {total} fílum",
"Could not save your choice: {error}": "Kundi ikki goyma títt val: {error}",
@@ -354,7 +346,6 @@
"Horizon's landscape. Pick a PNG, JPEG or WebP picture of your own.": "Horizon's landslag. Vel eina PNG, JPEG ella WebP mynd av tíni egnu.",
"Not needed": "Ikki neyðugt",
"This build of the launcher has no Microsoft sign-in (HORIZON_MSA_CLIENT_ID), so it can't start the game.": "Hendan byggingin av sjósetaranum hevur onga Microsoft innritan (HORIZON_MSA_KUNDA_ID), so hon kann ikki byrja spælið.",
"Offline name · plays": "Navn uttan net · spælir",
"Run the game through": "Koyr spælið ígjøgnum",
"needed by another pack": "brúk fyri einum øðrum pakka",
"Older →": "Eldri →",
@@ -365,13 +356,10 @@
"Could not run {program}: {error}": "Kundi ikki koyra {program}: {error}",
"Restart": "Endurbyrja",
"Copied to the clipboard.": "Avritað á klippiborðið.",
"Your worlds, offline names and settings stay where they are.": "Tínir heimar, offline nøvn og innstillingar halda seg har tey eru.",
"Send nothing": "Send einki",
"Move to Trash": "Flyt til rusk",
"Start from": "Byrja frá kl.12.00.",
"Asking Mojang for its versions…": "Spyrja Mojang um útgávurnar...",
"A 64×64 (or 64×32) skin PNG and a 64×32 cape PNG, kept by the launcher and given to the game when this name plays. The game draws the default skins for now; it uses these once it can. A Microsoft account's skin and cape: coming soon.": "Ein 64×64 (ella 64×32) húð PNG og ein 64×32 kápa PNG, sum sjósetingin heldur og gevur spælinum, tá hetta navnið spælir. Spælið dregur forsettu skinnini fyribils; tað brúkar hesar, tá tað einaferð kann. Húð og kápa hjá einum Microsoft konto: kemur skjótt.",
"Play offline under another name, and switch from the top bar. Online servers don't take offline names.": "Spæl offline undir øðrum navni, og skift frá ovastu strikuni. Net-ambætarar taka ikki offline nøvn.",
"Report on Discord": "Frágreiðing um Discord .",
"Export": "Útflutningur",
"Server": "Ambætari",
@@ -384,7 +372,6 @@
"No version installed yet.": "Eingin útgáva er sett upp enn.",
"Release": "Útgáva",
"Verified": "Staðfest",
"Choose a skin…": "Vel eina húð...",
"{instance} doesn't play its native mods yet: build the game with them.": "{instance} spælir ikki sínar upprunaligu mods enn: bygg spælið við teimum.",
"Use jars from my instance…": "Brúka krukkur frá mínum dømi...",
"Applications menu": "Forritavalmynd",
@@ -408,7 +395,6 @@
"Open backups": "Opna backups",
"The game is running: change packs in its own menus, or here once it is closed.": "Spælið er í gongd: skifta pakkar í egnum valmyndum, ella her tá tað er stongt.",
"Check now": "Kanna nú",
"Choose a cape…": "Vel eina kápu...",
"Save": "Goym",
"Folder": "Mappa",
"Searching…": "Leita...",
@@ -422,7 +408,6 @@
"MangoHud": "MangoHud",
"Sign out": "Rita út",
"When it starts": "Tá tað byrjar",
"{name}'s skin": "Húðina hjá {name}",
"Start": "Byrja",
"No Minecraft install needed: Horizon downloads it from Mojang for your account.": "Eingin Minecraft uppseting er neyðug: Horizon heinta tað frá Mojang til tína kontu.",
"Logs": "Loggar",
@@ -446,7 +431,6 @@
"The wordmark, while the release list loads.": "Orðmerkið, meðan útgávulistin heintast.",
"Playing offline": "Spæla uttannet",
"Sign in to Tailscale": "Rita inn á Tailscale Tailscale .",
"Offline names without an account": "Offline nøvn uttan kontu",
"Help make Horizon faster and steadier?": "Hjálp til at gera Horizon skjótari og støðugari?",
"Sign in to play": "Rita inn fyri at spæla",
"Ported": "Flutt",
@@ -488,14 +472,12 @@
"Update this launcher with your package manager.": "Dagfør henda sjósetaran við pakkastjóranum tínum.",
"Close this launcher, move it to {folder}, and open it there to enable updates.": "Lat henda sjósetaran aftur, flyt hann til {folder}, og opna hann har fyri at gera dagføringar virknar.",
"Any MCP client": "Ein og hvør MCP kundi",
"{name}'s cape is kept.": "{name}'s kápa er hildin.",
"Not reviewed by the Horizon registry": "Ikki ummælt av Horizon skrásetingini",
"Proxy": "Umboð",
"Checking": "Kanna",
"Updates": "Dagføringar",
"Asking Microsoft…": "Spyrja Microsoft...",
"Prepared for Minecraft {version}, without its sounds: the game will be silent. Prepare again to copy them from your Minecraft install.": "Fyrireikað til Minecraft {version}, uttan síni ljóð: spælið verður tøgn. Fyrireika teg aftur til at kopiera tey frá tínari Minecraft uppseting.",
"Forget": "Gloym",
"Import a modpack…": "Innflyt ein modpakka...",
"Search versions": "Leita eftir útgávum",
"failed": "miseydnaðist",
@@ -504,7 +486,6 @@
"Left off: {line}.": "Eftir: {line}.",
"Resource packs": "Tilfeingispakkar",
"yesterday": "í gjár",
"No cape": "Eingin kápa",
"After each session: frame-time percentiles and a 14-bucket histogram, tick times, peak memory and startup times, with your machine (OS, CPU and its cores and clocks, memory size, GPU, its memory and driver, drive type, screen size and refresh rate, laptop or desktop, on battery or not) and the settings that change performance.": "Eftir hvørja setu: rammu-tíðarprosent og eitt 14-spann histogramm, tikk tíðir, toppminni og uppstartstíðir, við tínari maskinu (OS, CPU og tess kjarnur og klokkur, minnistødd, GPU, tess minni og bilførari, drivslag, skermstødd og uppfrískingartíðina, battarí ella skriviborð, setting avrikið á farteldu ella skriviborði, sum ikki broytir avrikið.",
"Make a token": "Ger eitt merki",
"Added {names}: the game turns it on when the world opens.": "Lagt afturat {names}: spælið tendrar tað, tá heimurin letur upp.",
@@ -557,7 +538,6 @@
"Shared: {url}": "Deilt: {url}",
"Friends on the same Wi-Fi: Multiplayer, Add Server, then paste this address.": "Vinir á sama Wi-Fi: Fleirspælari, Legg ambætara til, og líma síðani hesa adressuna inn.",
"None yet: drop a .hshader or a shader pack .zip here.": "Eingin enn: slepp einum .hshader ella einum skuggapakka .zip her.",
"Offline name · the game's own": "Offline navn · spælið egna",
"Native mods aren't sandboxed: they run with full access to your computer, like any program. Install only mods whose authors you trust. To play with one, build the game on the Mods page; the first build downloads Rust and takes 20 to 30 minutes.": "Native mods eru ikki sandkassaðir: teir koyra við fullari atgongd til tína teldu, eins og øll onnur forrit. Set bert mods upp, hvørs høvundar tú hevur álit á. Fyri at spæla við einum, bygg spælið á Mods síðuni; fyrsta build heinta Rust og tekur 20 til 30 minuttir.",
"Your selected version only changes if you were playing the newest one.": "Tín valda útgáva broytist bert, um tú spældi ta nýggjastu.",
"Multiplayer": "Fleirspælari",
@@ -587,7 +567,6 @@
"the port": "Havnin",
"The source of {source}. Its release ships {file}, a content mod: installing those from GitHub is not supported yet.": "Keldan til {source}. Útgávan hjá henni sendir {file}, ein innihaldsmod: at seta tey upp frá GitHub er ikki stuðlað enn.",
"Build anyway": "Bygg allíkavæl",
"A name, 3 to 16 letters": "Eitt navn, 3 til 16 bókstavir",
"Installed {mods} from GitHub ({source}). Build it on the Mods page.": "Sett upp {mods} frá GitHub ({source}). Bygg tað á Mods síðuni.",
"Settings, Keys, Generate access token. It's kept in this computer's keychain and only sent to Tailscale.": "Innstillingar, Lyklar, Generera atgongdarmerki. Tað er goymt í lyklaringinum á hesi telduni og bert sent til Tailscale.",
"{id} is up to date.": "{id} er dagført.",
@@ -602,7 +581,6 @@
"I read it and trust it: install": "Eg lesi tað og havi álit á tí: seta upp",
"Close export": "Stongja útflutningin",
"Playing needs a prepared Horizon version (Play page).": "At spæla skal hava eina fyrireikaða Horizon útgávu (Spæli síða).",
"Offline, the game's name": "Offline, navnið á spælinum",
"From Horizon's registry": "Frá skrásetingini hjá Horizon",
"Sounds": "Ljóðar",
"Edit…": "Rætta...",
@@ -635,12 +613,10 @@
"up to date": "dagført",
"← Newer": "← Nýggjari",
"Downloading from Mojang · {done} of {total} files": "Heinta frá Mojang · {done} av {total} fílum",
"{name}'s skin is kept.": "Húðin hjá {name} er hildin.",
"Edit instance": "Rætta dømi",
"Remove shortcut": "Strika snarvegin",
"{program} is not installed here (or not on the PATH): copy the config instead.": "{program} er ikki installerað her (ella ikki á PATH): kopiera config ístaðin.",
"No worlds to put in.": "Ongar heimar at leggja í.",
"Default skin": "Forsett húð",
"A link to a repository (its latest release), a release, a branch or tag, or a commit. The launcher installs one exact release file or commit, never a branch that moves.": "Ein leinkja til eitt goymslustað (nýggjastu útgávuna), eina útgávu, eina grein ella merki, ella eina commit. Launcherin setur upp eina nágreiniliga útgávufílu ella commit, ongantíð eina grein sum flytur seg.",
"Sign in with GitHub to rate": "Rita inn við GitHub fyri at meta um",
"Star on GitHub": "Gev eina stjørnu á GitHub",
@@ -1053,10 +1029,6 @@
"played by {names}": "spælt av {names} .",
"{day}, {time} UTC": "{day}, {time} UTC",
"Microsoft account · online servers too": "Microsoft konta · net-ambætarar eisini",
"Offline · single player and LAN worlds": "Offline · einspælari og LAN heimar",
"Offline names": "Nøvn uttanfyri netið",
"Add a name": "Legg navn til",
"3 to 16 letters, numbers or underscores. Switch names from the top bar too. Online servers don't take offline names.": "3 til 16 bókstavir, tøl ella undirstrikur. Skift nøvn frá ovastu strikuni eisini. Net-ambætarar taka ikki offline nøvn.",
"Play online with your Microsoft account": "Spæl á netinum við tínari Microsoft konto",
"Sign in with the account that owns Minecraft: Java Edition. Your name and skin come along to online servers, like in other launchers.": "Rita inn við kontuni, sum eigur Minecraft: Java Útgáva. Títt navn og húð koma við á online ambætarar, eins og í øðrum launcher.",
"Microsoft's own page opens in your browser. Horizon never sees your password.": "Egna síðan hjá Microsoft letur upp í tínum kaga. Horizon sær ongantíð títt loyniorð.",
Loaded 100 of 199 files, more files were not shown because too many files have changed in this diff. Show more