Compare commits

..
Author SHA1 Message Date
Horizon agentandClaude Opus 5.5 92dab6cafc Pages v2: text fields, and a page in the title screen's Friends icon slot
horizon_hooks::pages gains Row::Field (Row::field(label, text).max(n)),
vanilla's EditBox on a page drawn as its own screen, with Act::Edit (each
change, before any other act or redraw reaches the page) and Act::Submit
(Enter); Place::Title, the title screen's Friends icon slot, unchanged in
place and look; Page::back, the label of the button that leaves such a
page; and pages::connect, for a Title page to join a server.

The icon opens the first Title page as multiplayer::Screen::Page, a form
laid out as Join a Friend (multiplayer/page.rs); its fields go through the
title screen's caret like every field of its own (focus, typing, caret
keys, selection, copy, paste, the max length), Tab walks fields then
buttons. Without a Title page the icon opens Join a Friend while a
resolver is registered, else it stays inactive. The options shell skips
fields. title.rs loses lines.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 23:11:27 +01:00
Horizon agentandClaude Opus 5.5 e11233f2dc The title screen's Friends icon is inactive without an invite-code resolver (spec #14167 step 4)
Join a Friend opens from vanilla's Friends icon slot, unchanged in place
and size at every GUI scale; it is now drawn inactive, and takes no click,
key or controller press, when no Hooks::tunnel resolver is registered
(net::joins_friends), as the pause menu's icon is without a sharing page.
horizon-official registers horizon-friends' resolver, so players of the
official game see no change; the plain executable, which refuses every
friend: address, no longer opens a screen that cannot join.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 22:45:31 +01:00
Ludovic Marie c89cd3f9e1 Merge pull request #14374 from horizon-rust/docs/governance
Add GOVERNANCE.md: the council, theme groups and how roles are earned
2026-11-09 22:35:02 +01:00
Ludovic Marie 75a016b1b0 Merge pull request #14211 from oloion/fix/frog-walk-animation
🤖 Agent: the client now runs Frog.updateWalkAnimation (min(d*25,1), 0 while jumping); FROG_WALK keeps FrogModel's 1.5 factor (agent fix 341a929).
2026-11-09 22:32:39 +01:00
Ludovic Marie 691a39cab6 Merge pull request #14204 from horizon-rust/layers/studio-extras-gate
🤖 Agent: studio::EDITOR is a compile-time constant (true by default, so the default build runs no check); without horizon-extras recording/playback stay and the editor input, drawing and commands are off.
2026-11-09 22:25:53 +01:00
Ludovic Marie 3c06105a0e Merge pull request #14199 from horizon-rust/layers/replay-move
🤖 Agent: pure move checked by line multiset; the editor is reached through five calls (save path, replay opened/advanced/closing/closed) at the places its code was.
2026-11-09 22:20:16 +01:00
Ludovic Marie 726726a1fc Merge pull request #14186 from horizon-rust/layers/replay-state
🤖 Agent: playback state (driver, camera type to restore, standalone, playback clock) moves to game/replay.rs Replay; Studio keeps the editor; callers ask replay.playing(); game.rs does not grow.
2026-11-09 22:14:22 +01:00
Ludovic Marie 82da4379bd Merge pull request #14161 from horizon-rust/layers/studio-calls
🤖 Agent: pure move: game.rs's inline Studio blocks and the replay key shortcuts become game/studio.rs methods with the same bodies and early returns; the engine asks replaying()/flying()/active().
2026-11-09 22:09:29 +01:00
Ludovic Marie 7627e37dba Merge pull request #14351 from horizon-rust/split/pages-plain-rows
🤖 Agent: Row::Button/Text are #[non_exhaustive] variants built through constructors, so later options do not break crates; the options shell pairs two half buttons into one row and a press on an inactive one reaches nothing (tested).
2026-11-09 22:09:25 +01:00
Ludovic Marie cd8eb96cef Merge pull request #14214 from horizon-rust/split/cosmetics-draw
🤖 Agent: step 2a-i of spec #14091 adds PlayerDraw to horizon-hooks (plain types only) so crates can draw on player models in the world pass; creatures.rs is main's, with the swap moved to creatures/mob_geometry.rs.
2026-11-09 22:04:26 +01:00
Ludovic Marie 829aec1dba Merge pull request #14080 from rdbtCVS/screenshot-off-render-thread
🤖 Agent: F2 and world-icon PNGs are written on a thread after map_async; a second F2 in the same second now skips the name still being written (agent fix 1ffa9ed), and agent screenshots keep the synchronous path.
2026-11-09 22:04:22 +01:00
Ludovic Marie 82a6e896d1 Merge pull request #13627 from vnsmoreira/fix/armor-stand-player-break-loot
🤖 Agent: the player break now pops the named stand item and then goes through brokenByAnything, which plays the break sound before the loot as ArmorStand.brokenByAnything orders it; stand_break_loot, stand_command_hurt and armor_stand_equip_events pass with it, and command_exec on a union with main shows no armor stand mismatch.
2026-11-09 22:04:18 +01:00
Ludovic Marie 0300ba0a76 Merge pull request #14339 from horizon-rust/team/drop-itarqos5
🤖 Agent: removes itarqos5 from .github/trusted-reviewers.txt, the Team and reviewer lists in docs/release-flow.md and the pinned login in tests/test_nightly_set.py; the nightly, claim and triage test modules (102 tests) passed per the PR.
2026-11-09 21:59:04 +01:00
Ludovic Marie 3a3c182aed Merge pull request #14208 from horizon-rust/split/cosmetics-names
🤖 Agent: step 3b makes names.rs, scoreboard.rs and perspective.rs call the engine's dispatch (Game::hooks_name_marks builds one PlayerModel per tag drawn) instead of the cosmetics directly.
2026-11-09 21:56:53 +01:00
Ludovic Marie e76394c2cf Merge pull request #14107 from horizon-rust/split/official-servers-crate
🤖 Agent: the official server now reaches the list only through horizon-official's started hook, so horizon-client's own executable (plain builds, harnesses) has neither the official server nor the withdrawn partner's address; verify and launcher green on this head.
2026-11-09 21:53:06 +01:00
Ludovic Marie d9cfca426c Merge pull request #14207 from horizon-rust/split/cosmetics-sprites
🤖 Agent: the API half of cosmetics step 3: Hooks::name_decoration returns a Copy NameDecoration (fixed &'static mark rectangles, optional badge, tag lift) so no heap data or engine type crosses the hook.
2026-11-09 21:53:02 +01:00
Ludovic Marie 763d4868d7 Merge pull request #14181 from horizon-rust/split/cosmetics-hooks
🤖 Agent: cosmetics step 1 of spec #14091: the emote feed and presence go through plain-type frame and tick hooks in horizon-hooks, so no engine or renderer type crosses the seam.
2026-11-09 21:44:17 +01:00
Ludovic Marie 110a92a1aa Merge pull request #14096 from horizon-rust/layers/seat
🤖 Agent: seat() is a thread-local the engine sets at Split::turn and around a guest's join/profile load (the profile used to load before the guest's turn, into P1's seat); a new profile saves on P1's seat and reads its stores back into the guest's. Without splitscreen it is always 0. Main merged in (horizon_platform::hooks exports both seat and main's tunnel).
2026-11-09 21:35:51 +01:00
Ludovic Marie 3a8d647c8c Merge pull request #14154 from Skr1zzzz/falling-removals
🤖 Agent: one pass over the big lists per RemoveEntities packet, per-id cleanup order kept (dragon before its crystal); moved to remote_removal.rs so remote.rs shrinks (agent fix 8cf1e6b).
2026-11-09 21:30:12 +01:00
Ludovic Marie 3c346ba1a4 Merge pull request #13810 from NikitaMGrimm/hdr-lighting-one-meaning
🤖 Agent: re-checked the new head: only main merged in, and the PR's own diff is unchanged. shader_pack_kind().is_none() is still exactly the old native/pack_post test, so HDR Lighting greys only where the running pack lights the world.
2026-11-09 21:25:43 +01:00
Ludovic Marie b41db51bf9 Merge pull request #13808 from vnsmoreira/packs/polytone-fluid-fog
🤖 Agent: re-checked the new head: the only change is that FluidFog/FluidFogs moved to the render crate's pack_palette after #13959, converted from horizon_polytone's type once when the pack loads. The fog still runs last and is vanilla's without a modifier.
2026-11-09 21:25:38 +01:00
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 1ecc5a9bdc Merge pull request #13811 from Mik00000/perf/natural-spawning-cache
🤖 Agent: Util.shuffle runs every pass again, so the level random keeps vanilla's draws, and nothing is cached across ticks any more. What stays saves allocations: Counted streamed instead of collected, the SpawnPlayer buffer reused, and a single-player collect without the neighbour scan. Fake players stay out of the anchors and in the level, as on main. Merged with main on a branch together with #13795 and #13800: clippy and 3827 tests pass; natural_spawn runs in CI parity.
2026-11-09 21:21:02 +01:00
Ludovic Marie d05675d755 Merge pull request #13800 from Mik00000/perf/block-entities-opt
🤖 Agent: every hopper again records tickedGameTime each tick, so the 8/7 transfer cooldown matches vanilla, and is_full keeps #13763's insertion_item for pots. The gains stay: slot iterators instead of a Vec per transfer, empty hoppers with nothing above them or within reach skip the whole pass, one block lookup per tick. Merged with main on a branch together with #13795 and #13811: clippy and 3827 tests pass; the hopper harnesses run in CI parity.
2026-11-09 21:20:57 +01:00
Ludovic Marie 2568835cc6 Merge pull request #13795 from TheMrZZ/fix/command-spawnpoint-respawn-config
🤖 Agent: with the offline capture tools removed, the pitch now goes through RespawnConfig, the personal respawn save (old records load pitch +0.0) and only the free-point branch of find_respawn_and_use; bed and anchor keep pitch 0, as RespawnData's block cases do. Merged with main on a branch together with #13800 and #13811: clippy and 3827 Rust tests pass on the desktop.
2026-11-09 21:20:53 +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
Horizon agent f4e5fbdfd0 Merge the drag hook fixture fix into layers/studio-extras-gate 2026-11-09 20:56:43 +01:00
Horizon agent 6d5b520591 Merge the drag hook fixture fix into layers/replay-move 2026-11-09 20:56:41 +01:00
Horizon agent dff332b257 Merge the drag hook fixture fix into layers/replay-state 2026-11-09 20:56:40 +01:00
Horizon agentandClaude Opus 5.5 c1dc47e41f Tests: the drag hook fixture cuts Studio's drag at studio_mouse_dragged
game.rs's CursorMoved arm now asks self.studio_mouse_dragged(b.width)
instead of the inline timeline drag; the fixture leaves that call out of
its slice as it left the inline block.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 20:56:39 +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
Horizon agentandClaude Opus 5.5 a8bf4c1474 Team: itarqos5 leaves the Horizon Team
Drops the trusted-reviewers line, the Team lists in docs/release-flow.md and the pinned login in
test_nightly_set. GitHub team memberships (horizon-team, contributors) are already removed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 20:46:41 +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
Vinícius MoreiraandClaude Opus 5.5 29ac1e17b9 Polytone: fluid modifiers' fog
A fluid modifier's fog_colormap (a flat colour), fog_radius and fog_fade apply to the
water's or lava's fog after everything else: the colour replaces it, the radius scales the
fog, and a fade of 0 makes it a hard wall. Measured on the real mod (red fog at 0.3 of the
radius, within the scene's variance of the vanilla baseline). Colormap ids and expressions
aren't read yet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:41:22 -03:00
Horizon agent 115f5235b9 Merge remote-tracking branch 'origin/main' into split/official-servers-crate
# Conflicts:
#	crates/horizon-client-lib/Cargo.toml
#	crates/horizon-official/Cargo.toml
#	crates/horizon-official/src/lib.rs
#	crates/horizon-platform/src/lib.rs
2026-11-09 20:24:48 +01:00
Horizon agent e2afd13715 Merge branch 'split/cosmetics-names' into split/cosmetics-draw
# Conflicts:
#	crates/horizon-client/src/game/creatures.rs
#	crates/horizon-hooks/src/lib.rs
2026-11-09 20:19:51 +01:00
Horizon agent 00aba43d81 Merge branch 'split/cosmetics-sprites' into split/cosmetics-names 2026-11-09 20:19:06 +01:00
Horizon agentandClaude Opus 5.5 e893fd3eac Hooks doc: the frame rule is the player methods', not tunnel's
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 20:18:59 +01:00
Horizon agent ee986c3e62 Merge branch 'split/cosmetics-hooks' into split/cosmetics-sprites
# Conflicts:
#	crates/horizon-hooks/src/lib.rs
2026-11-09 20:18:48 +01:00
Horizon agent 19aabc08c2 Merge remote-tracking branch 'origin/layers/seat' into split/cosmetics-hooks
# Conflicts:
#	crates/horizon-hooks/src/lib.rs
#	crates/horizon-platform/src/lib.rs
2026-11-09 20:18:27 +01:00
Horizon agent ca3649534d Merge remote-tracking branch 'origin/main' into layers/seat
# Conflicts:
#	crates/horizon-platform/src/lib.rs
2026-11-09 20:15:33 +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 agent 8df100e589 Merge the studio fixture fix into layers/studio-extras-gate 2026-11-09 19:57:58 +01:00
Horizon agent a416f1dfcd Merge the studio fixture fix into layers/replay-move 2026-11-09 19:57:55 +01:00
Horizon agentandClaude Opus 5.5 4c52129f7d Tests: capture fixture follows the Replay split
Replay playback moved out of Studio into game/replay.rs's Replay; the
pointer-capture fixture carries game.replay.driver and Game::studio_up.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:57:53 +01:00
Horizon agent 243d765452 Merge the studio fixture fix into layers/replay-state 2026-11-09 19:56:58 +01:00
Horizon agentandClaude Opus 5.5 ff52e244ae Tests: fixture Studio gets flying/replaying/active
fov.rs and the pointer-capture methods now ask self.studio.flying() and
replaying(); the fixtures mirror those three methods of game/studio.rs.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:56:54 +01:00
Horizon agent bb712cca1a Merge the studio fixture fix into layers/studio-calls 2026-11-09 19:56:20 +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 8cf1e6b4d6 Move a packet's entity removal out of remote.rs
remote.rs is over 3000 lines and may not grow (verify's "Big files don't
grow" failed): remove_entity, remove_entities and their test move to
game/remote_removal.rs, a child module of remote, unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:55:05 +01:00
Horizon agentandClaude Opus 5.5 341a92902c Frog walk: keep FrogModel's 1.5 walk speed factor
FrogModel.setupAnim applies FROG_WALK with applyWalk(pos, speed, 1.5F, 2.5F)
on land (1.0F is the swim animation's).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:54:21 +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
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 0c77cd5898 Merge branch 'split/cosmetics-names' into split/cosmetics-draw 2026-11-09 19:22:00 +01:00
Horizon agent 4848a9eff5 Merge branch 'split/cosmetics-sprites' into split/cosmetics-names 2026-11-09 19:21:59 +01:00
Horizon agentandClaude Opus 5.5 95b0cb05e7 horizon-hooks test: call SpriteStore::has by its trait
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:21:58 +01:00
Horizon-agent 723c4e7c2b Merge remote-tracking branch 'origin/main' into pr-13811 2026-11-09 19:18:44 +01:00
Horizon-agent c32f43b4b0 Merge remote-tracking branch 'origin/main' into pr-13800 2026-11-09 19:18:37 +01:00
Horizon agentandClaude Opus 5.5 641a5859a2 horizon-platform re-exports the PlayerDraw types
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:18:34 +01:00
Horizon-agent b26a050b2b Merge remote-tracking branch 'origin/main' into pr-13795 2026-11-09 19:18:26 +01:00
Horizon agentandClaude Opus 5.5 7d17f516e5 Hooks: PlayerDraw, crates draw on player models in the world pass (spec #14091 step 2a-i)
horizon-hooks gains Hooks::player_layers with a plain PlayerDraw (bone
matrices, the frame's ticks, the body pose, sprites, draw of an Arc<Mesh>
with its parts posed) and the Mesh/Quad/Bone/Pass types. The engine
implements it on the GPU skin path (each mesh made a Part once, cached by
its address while a crate holds it) with the vertex path as fallback, and
dispatches it from creatures.rs's world pass one call for one call; the
cosmetics still draw there until 2a-ii.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:15:18 +01:00
Horizon agent 0f0ca381d4 Merge remote-tracking branch 'origin/main' into split/official-servers-crate
# Conflicts:
#	crates/horizon-platform/src/lib.rs
2026-11-09 19:14:23 +01:00
Oloion e3d24ab1a5 mobs: fix frog walking keyframe animation in singleplayer
Remote entity client update now calls frog::walk_target for Species::Frog so limb_speed advances at the vanilla 25x distance rate instead of 4x. Also restore FrogAnimation.FROG_WALK speed factor to vanilla 1.0F in body_anim and guard keyframe looping against zero length.
2026-11-09 21:11:32 +03:00
Horizon agentandClaude Opus 5.5 8902d94a19 Cosmetics: name tags, the tab mark and the camera pull through the hooks (spec #14091 step 3b)
names.rs, scoreboard.rs and perspective.rs call the engine dispatch
(name_decoration, player_mark, camera) instead of the cosmetics; the
cosmetics answer from their per-seat state: badges become sprites by id
put in the atlas from the frame hook, covered slots read PlayerModel's
gear, the camera pull comes from the emote that pulled it.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:07:06 +01:00
Horizon agentandClaude Opus 5.5 ca6140d05e Hooks: name decoration, player-list mark, camera and sprites by id (spec #14091 step 3a)
horizon-hooks gains Hooks::name_decoration (a Copy NameDecoration: mark
rectangles, a badge cut from the crate's sprite, the lift over the body),
player_mark for the player list, camera (a share of the third-person
distance), and sprites by id: Sprites read while drawing, SpriteStore
filled in Hooks::frame (skin slots, hooks/<hex>). PlayerModel carries
gear and invisibility; Frame says whether the world is the window's own.
horizon-platform re-exports them. The engine fills the store; no crate
answers the new hooks yet (step 3b).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:05:10 +01:00
Horizon agentandClaude Opus 5.5 ac0f7d6030 Studio's editor runs only with horizon-extras (layer plan M6)
studio::EDITOR = cfg!(feature = "horizon-extras"): without it the bars,
camera path, editor mouse and keys and the freecam/keyframe/path and
studio screen commands are off; recording and playback stay (platform).
The default build is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:03:04 +01:00
MSedgeMC 2e9f807458 Merge remote-tracking branch 'upstream/main' into fix/stonecutter-result-components 2026-11-09 18:01:23 +00:00
Horizon agentandClaude Opus 5.5 a7f07a08de rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 19:00:49 +01:00
Horizon agentandClaude Opus 5.5 42026ce09f Replay recording and playback move to game/replay.rs (layer plan M6)
Pure move: open/close/seek/advance, record start/stop/status, the world
snapshot and the record/replay words of /studio and horizon-ctl studio
leave game/studio.rs, which keeps the editor (free camera, path,
timeline, top bar, its own command words). Where playback touched the
editor it calls it: save_studio_camera_track, studio_replay_opened,
studio_replay_advanced, studio_replay_closing, studio_replay_closed.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:58:26 +01:00
Horizon agentandClaude Opus 5.5 0e528f7287 Cosmetics: name the per-seat state Seat (the tests' Service is a transport)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:58:25 +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 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
Horizon agentandClaude Opus 5.5 ac0a2f1275 rustfmt
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:52:51 +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 963782a17b Replay playback's state leaves Studio: game/replay.rs's Replay (layer plan M6)
Recording and playback are platform, Studio's editor is Horizon
(docs/layers.md, Replays): the driver, the camera type to restore,
standalone and the playback clock move to Replay; Studio keeps the free
camera, timeline and top bar. Callers ask self.replay.playing(); the own
player's tick fraction is Game::own_player_alpha(). No behaviour change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:52:07 +01:00
Horizon agent 7ca4fd68bd Merge remote-tracking branch 'origin/layers/seat' into split/cosmetics-hooks 2026-11-09 18:48:40 +01: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 1ffa9ed25f Screenshots: a second F2 in the same second takes the next name
The PNG is now written on its own thread, so the first press's file may not
exist yet when a second press picks its name: both took the same path and
two writers raced on one file. screenshot_name also skips the paths of the
screenshots still being written (UiState::screenshot_messages).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:44:35 +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 547b1d4959 Merge branch 'layers/hud-layers' into layers/seat 2026-11-09 18:40:43 +01:00
Horizon agentandClaude Opus 5.5 e2918de5aa Seat: a splitscreen guest's profile loads into its own seat
Split::enter loaded a guest's profile before its turn began, so the
crates' settings stores read the guest's lines into P1's seat. The load
now runs on the guest's seat; a new profile is saved on P1's seat (the
stores write P1's values, as the rest of the profile copies P1's) and
its stores are read back into the guest's (Settings::load_stores).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:40:35 +01:00
Horizon agentandClaude Opus 5.5 e6b0a03270 Cosmetics: emote feed and presence behind frame/tick hooks (spec #14091 step 1)
horizon-hooks gains Hooks::frame and Hooks::tick with a plain player-model
view (PlayerModels, BodyPose moves here), re-exported by horizon-platform.
The cosmetics' client, emote feed, owner check and presence live in a
per-seat static behind those hooks; only a window's game calls them, so
the server thread no longer runs tick_emotes. net::Session gets a serial
that names the connection.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:40:24 +01:00
Horizon agentandClaude Opus 5.5 38865e907e Studio: game.rs asks it through a few calls (layer plan M6)
game.rs's inline Studio blocks (bars, camera path, timeline drag, mouse
buttons, free-camera flight) and play_keys.rs's replay shortcuts move into
game/studio.rs methods; the engine reads Studio through replaying(),
flying() and active(). Pure move, no behaviour change.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:37:38 +01:00
Nikita Maximilian Grimm b7615761ee Merge remote-tracking branch 'origin/main' into hdr-lighting-one-meaning
# Conflicts:
#	crates/horizon-client-render/src/gfx/output.rs
2026-11-09 18:34:44 +01:00
Ludovic Marie 8f198d9cbd Merge origin/main into split/cosmetics-hooks 2026-11-09 18:30:32 +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
Skr1zzzzandClaude Opus 5.5 396353c6b1 Client: one pass over the big entity lists per RemoveEntities packet
Part of #13007. Each removed id ran its own retain over the mobs, orbs, dropped
items, falling blocks and primed TNT, and a scan of the passenger map, so a
packet of n ids made n passes over lists that hold thousands of falling blocks
while sand drops. RemoveEntities now removes its ids together: the per-id side
effects keep their order (the dragon's nearest crystal still follows the
crystals one id at a time), and those five lists and the passenger map are
filtered once against the packet's ids.

8,000 falling blocks, packets of 256 ids (debug test build): 26.1 ms -> 1.3 ms
per packet.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 20:26:14 +03:00
Horizon agent 4c28a9b5b9 Merge remote-tracking branch 'origin/main' into pr-13795 2026-11-09 18:26:09 +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
Horizon agentandClaude Opus 5.5 466201a864 Cargo.lock: horizon-official-servers after the merge
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 18:06:31 +01:00
Horizon agent ddb4f9df58 Merge branch 'split/official-servers-module' into split/official-servers-crate
# Conflicts:
#	Cargo.lock
#	docs/forking.md
2026-11-09 18:02:48 +01:00
Horizon agent bd90908a72 Merge branch 'layers/hud-layers' into layers/seat 2026-11-09 17:44:40 +01:00
rdbtCVSandClaude Sonnet 5.5 1b4f056692 Merge main into hdr-lighting-one-meaning
Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-11-09 16:44:13 +00:00
rdbtCVSandClaude Opus 5.5 15d2dd04c4 Screenshots: write F2's and the world icon's PNG off the render thread
The render thread waited for the GPU to finish the screenshot's frame
(poll wait_indefinitely), then converted the pixels and encoded the PNG
inline: at 4K or a Screenshot Quality above 1x, a second or more of frozen
game. F2's and the world icon's readbacks are now mapped asynchronously and
written on a thread of their own; the result reaches the chat a frame or a
few later. Agent screenshots and screenshot-sequence keep the synchronous
path, which hands them the result with the frame.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 16:43:50 +00: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 agentandClaude Opus 5.5 a8d445f56c Hooks: seat(), the splitscreen player whose turn it is
Splitscreen players share one process and thread, so a crate's statics
are shared by them. The engine now says whose turn it is
(horizon_hooks::seat(), re-exported in horizon_platform::hooks; 0 for
P1), set where split.rs switches turns and while a joining player's game
starts, so settings stores, pages and HUD layers can keep per-player
state.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:33:09 +01:00
Horizon agent d82a6941d1 Merge remote-tracking branch 'origin/main' into pr-13800
# Conflicts:
#	crates/horizon-client/src/game/machines.rs
2026-11-09 17:19:40 +01:00
Horizon agentandClaude Opus 5.5 f7772b587f Natural spawning: the level keeps every player, the spawn state the anchoring ones
After main filtered fake players out of the spawn anchors, building the
level from that list would drop them from natural_level too; main builds
the level from every player and SpawnPlayer from the filtered list.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:17:42 +01:00
Horizon-agent d1098c9a91 Merge remote-tracking branch 'origin/main' into pr-13811 2026-11-09 17:17:21 +01:00
Horizon-agentandClaude Opus 5.5 d50d56d837 Natural spawning: shuffle every pass, no candidate cache keyed on chunk count
Util.shuffle in ServerChunkCache.tickChunks draws from the level's random
whether or not a category may spawn, so skipping it moved every later draw
of that random off vanilla's. The candidate cache keyed on player x/z and
the chunk count went stale when a chunk's ticket level or entity loading
changed under a player standing still (an AFK farm). Both go; the allocation
savings (streamed Counted, reused SpawnPlayer buffer, the single-player
collect) stay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:17:21 +01:00
Horizon agentandClaude Opus 5.5 8e2780a8f0 Cargo.lock: horizon-official-servers
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:15:07 +01:00
Horizon agentandClaude Opus 5.5 1feb0c7b0b Keep every hopper's cooldown entry, as vanilla keeps tickedGameTime
With get_mut, an idle hopper never recorded the tick it ticked, so a
hopper that had already ticked this tick and then received an item from
another hopper took cooldown 8 instead of 7 (HopperBlockEntity.tryMoveInItem
skips one when its tickedGameTime >= the source's). Restore the per-tick
entry and the original prune; the other optimizations stay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:15:07 +01:00
Horizon agentandClaude Opus 5.5 8a5af429d7 Drop the offline capture reporting tools
They only re-project captures kept on the author's machine and start no
engine, so the test_*_parity.py name would register a harness CI cannot
run. The Rust fix and its unit and guest-death tests stay.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:08:50 +01:00
Horizon agentandClaude Opus 5.5 2cd4ec9888 horizon-official-servers: the official server leaves the engine for a Horizon crate
Layer plan M5: official_servers.rs moves (pure file move plus its hook) to
the new Horizon crate horizon-official-servers, which the official
executable registers through the platform's hooks: Hooks::started now gets
the game folder (Started::game_dir), and horizon-platform re-exports
servers.dat as horizon_platform::servers. Its addresses come from
horizon-addresses: the withdrawn partner's joins the list file, so its
allowed entry in tools/addresses.json goes. horizon-client's own executable
(plain builds, harnesses) no longer touches servers.dat at startup.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 17:05:24 +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 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
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
Mik00000 0f8225e608 perf(spawning): optimize natural mob spawning density scan and chunk cache 2026-11-09 12:59:02 +02:00
Nikita Maximilian GrimmandClaude Opus 5.5 b2ba0cb395 HDR settings: HDR Lighting greyed under a shader pack, one switch for it
HDR Lighting is one thing: all of Horizon's own lift above paper white, light
sources, the sun and the lit surfaces. HORIZON_HDR_LIGHTING=0 switched off only
the surfaces' part, a second switch with another scope; it is gone, and the
setting does the job. docs/graphics.md now describes the setting.

Under a shaders/ pack, and under a 0.2 pack on the float frame, Horizon lifts
nothing, so the row did nothing there. It is now greyed and says "The shader
pack lights the world itself." Under a 0.1 pack on the 8- or 16-bit frame the
last pass still lifts the light sources and the sun, so the row stays live
there, as it does for a pack that is refused, missing or whose mod is off. The
page reads this from the renderer's output, which now carries whether the
running pack lights the world. HDR's own reasons still come first.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 11:21:31 +01:00
Mik00000 72f748a785 perf(machines): optimize block entity ticking and hopper transfers 2026-11-09 12:11:26 +02:00
TheMrZZandCodex 9ad798b74b Preserve personal spawnpoint pitch for dedicated guests
Part of #13625. Keep owner physical pitch open and document recovered offline arrival evidence.

Co-Authored-By: Codex <[email protected]>
2026-11-09 10:33:51 +01:00
Vinícius MoreiraandClaude Opus 5.5 41fc640974 A player's break of an armor stand rolls its loot table
ArmorStand.hurtServer breaks a stand through brokenByPlayer on a second
player hit within five ticks, and at once for an always_kills_armor_stands
type: the stand item (with the stand's name) pops at its block, then
brokenByAnything plays the sound, rolls the loot table and pops the
equipment. Horizon's punch dropped the item and equipment without the
loot table, and /damage refused every can_break / always_kills type.

Part of #12514

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-09 04:35:28 -03:00
448 changed files with 9838 additions and 10600 deletions

No files matched your search

-1
View File
@@ -13,4 +13,3 @@
87152661 rdbtCVS # added by Ludovic, 2026-10-27
84875247 Online5277 # added by Ludovic, 2026-10-27 (his top three by merged pull requests)
86072227 levzzz5154 # added by Ludovic, 2026-10-28 (Horizon Team; author of horizon-mixins)
169198624 itarqos5 # added by Ludovic, 2026-11-08 (Discord Literal; Horizon Team)
+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).
Generated
+11
View File
@@ -1449,6 +1449,7 @@ dependencies = [
"horizon-core",
"horizon-cosmetics",
"horizon-dualsense",
"horizon-friends",
"horizon-hdr",
"horizon-hooks",
"horizon-items",
@@ -1795,11 +1796,21 @@ dependencies = [
"horizon-friends",
"horizon-game",
"horizon-heartbeat",
"horizon-official-servers",
"horizon-platform",
"log",
"winresource",
]
[[package]]
name = "horizon-official-servers"
version = "0.1.0"
dependencies = [
"horizon-addresses",
"horizon-platform",
"log",
]
[[package]]
name = "horizon-optifine"
version = "0.1.0"
+1
View File
@@ -34,6 +34,7 @@ members = [
"crates/horizon-game",
"crates/horizon-official",
"crates/horizon-heartbeat",
"crates/horizon-official-servers",
"crates/horizon-bench",
"crates/horizon-friends",
"crates/horizon-relay",
+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.
+4
View File
@@ -15,6 +15,10 @@ pub const OFFICIAL_SERVER: &str = "play.playhorizon.dev";
/// `official_server_previous` in `launcher/links.json`).
pub const OFFICIAL_SERVER_PREVIOUS: &[&str] = &["horizon.bunchy7s.dev"];
/// Afri-Network, a partner server the game added once below the official server (#9299) until
/// the partnership ended: kept so the game can take back out the entry it added.
pub const WITHDRAWN_PARTNER_SERVER: &str = "afri-network.co.za";
/// [`OFFICIAL_SERVER`] with the port its SRV record gives, for askers that don't look SRV up
/// (the telemetry server's status checks).
pub const OFFICIAL_SERVER_STATUS: &str = "play.playhorizon.dev:24454";
+37 -172
View File
@@ -74,70 +74,11 @@ pub trait ResourceSource {
vec!["minecraft".into()]
}
}
/// The bundled file a language reads, and whether it drops `ß`: a regional variant reads its
/// language's file (Swiss German writes "ss" for "ß", as vanilla's de_ch does).
fn bundled_code(code: &str) -> (&str, bool) {
match code {
"ko" => ("ko_kr", false),
"hr" => ("hr_hr", false),
"de_at" => ("de_de", false),
"de_ch" => ("de_de", true),
"fr_ca" | "fr_ch" => ("fr_fr", false),
"es_ar" | "es_cl" | "es_ec" | "es_mx" | "es_uy" | "es_ve" => ("es_es", false),
code => (code, false),
}
}
/// Lang files crates above the engine ship (`horizon_hooks::lang`), each a list of
/// (code, JSON) pairs. The game's entry installs them once, before any language loads.
static CRATE_FILES: std::sync::OnceLock<&'static [&'static [(&'static str, &'static str)]]> =
std::sync::OnceLock::new();
/// Installs the crates' lang files (`horizon_hooks::lang::engine::all()`). Only the first call
/// counts.
pub fn install_crate_files(files: &'static [&'static [(&'static str, &'static str)]]) {
let _ = CRATE_FILES.set(files);
}
/// The crates' entries for language `code` (through [`bundled_code`]'s variants) that the
/// engine's own `horizon` file for it doesn't have: on a key both have, the engine wins.
fn read_crate_files(files: &[&[(&str, &str)]], code: &str, map: &mut HashMap<String, String>) {
if files.is_empty() {
return;
}
let (file, swiss) = bundled_code(code);
let mut own = HashMap::new();
if let Some(bytes) = Bundled.read(&format!("assets/horizon/lang/{code}.json")) {
read_lang_file(&bytes, &mut own);
}
for (c, json) in files.iter().flat_map(|f| f.iter()) {
if *c != file {
continue;
}
let mut theirs = HashMap::new();
if swiss {
read_lang_file(json.replace('ß', "ss").as_bytes(), &mut theirs);
} else {
read_lang_file(json.as_bytes(), &mut theirs);
}
for (key, value) in theirs {
if !own.contains_key(&key) {
map.insert(key, value);
}
}
}
}
/// Horizon's own strings, compiled in so they need no prepared resources.
struct Bundled;
impl ResourceSource for Bundled {
fn read(&self, path: &str) -> Option<Vec<u8>> {
let code = path
.strip_prefix("assets/horizon/lang/")?
.strip_suffix(".json")?;
let (file, swiss) = bundled_code(code);
let path = format!("assets/horizon/lang/{file}.json");
let body = match path.as_str() {
let body = match path {
"assets/horizon/lang/en_us.json" => {
include_str!("../../horizon-client/assets/horizon/lang/en_us.json")
}
@@ -162,10 +103,10 @@ impl ResourceSource for Bundled {
"assets/horizon/lang/tr_tr.json" => {
include_str!("../../horizon-client/assets/horizon/lang/tr_tr.json")
}
"assets/horizon/lang/ko_kr.json" => {
"assets/horizon/lang/ko_kr.json" | "assets/horizon/lang/ko.json" => {
include_str!("../../horizon-client/assets/horizon/lang/ko_kr.json")
}
"assets/horizon/lang/hr_hr.json" => {
"assets/horizon/lang/hr_hr.json" | "assets/horizon/lang/hr.json" => {
include_str!("../../horizon-client/assets/horizon/lang/hr_hr.json")
}
"assets/horizon/lang/pt_pt.json" => {
@@ -390,20 +331,30 @@ impl ResourceSource for Bundled {
"assets/horizon/lang/vec_it.json" => {
include_str!("../../horizon-client/assets/horizon/lang/vec_it.json")
}
"assets/horizon/lang/de_de.json" => {
"assets/horizon/lang/de_de.json" | "assets/horizon/lang/de_at.json" => {
include_str!("../../horizon-client/assets/horizon/lang/de_de.json")
}
"assets/horizon/lang/fr_fr.json" => {
// Swiss German writes "ss" for "ß", as vanilla's de_ch does.
"assets/horizon/lang/de_ch.json" => {
let de = include_str!("../../horizon-client/assets/horizon/lang/de_de.json");
return Some(de.replace('ß', "ss").into_bytes());
}
"assets/horizon/lang/fr_fr.json"
| "assets/horizon/lang/fr_ca.json"
| "assets/horizon/lang/fr_ch.json" => {
include_str!("../../horizon-client/assets/horizon/lang/fr_fr.json")
}
"assets/horizon/lang/es_es.json" => {
"assets/horizon/lang/es_es.json"
| "assets/horizon/lang/es_ar.json"
| "assets/horizon/lang/es_cl.json"
| "assets/horizon/lang/es_ec.json"
| "assets/horizon/lang/es_mx.json"
| "assets/horizon/lang/es_uy.json"
| "assets/horizon/lang/es_ve.json" => {
include_str!("../../horizon-client/assets/horizon/lang/es_es.json")
}
_ => return None,
};
if swiss {
return Some(body.replace('ß', "ss").into_bytes());
}
Some(body.as_bytes().to_vec())
}
fn namespaces(&self) -> Vec<String> {
@@ -487,16 +438,6 @@ impl Language {
/// from every namespace and every source in priority order (later sources
/// override).
pub fn load(sources: &[&dyn ResourceSource], code: &str) -> Self {
let crate_files = CRATE_FILES.get().copied().unwrap_or_default();
Self::load_with(sources, code, crate_files)
}
/// [`Language::load`] with these crates' lang files.
fn load_with(
sources: &[&dyn ResourceSource],
code: &str,
crate_files: &[&[(&str, &str)]],
) -> Self {
let mut map = HashMap::new();
let mut codes = vec![DEFAULT];
if code != DEFAULT {
@@ -512,14 +453,12 @@ impl Language {
sources.iter().flat_map(|s| s.namespaces()).collect();
for c in codes {
for namespace in &namespaces {
for (i, source) in sources.iter().enumerate() {
if let Some(bytes) = source.read(&format!("assets/{namespace}/lang/{c}.json")) {
read_lang_file(&bytes, &mut map);
}
// The crates' text right after the engine's own (`Bundled`, the first source).
if i == 0 && namespace == "horizon" {
read_crate_files(crate_files, c, &mut map);
}
for source in sources {
let Some(bytes) = source.read(&format!("assets/{namespace}/lang/{c}.json"))
else {
continue;
};
read_lang_file(&bytes, &mut map);
}
}
}
@@ -749,43 +688,6 @@ mod tests {
);
}
#[test]
fn a_crates_text_loads_after_the_engines_and_before_packs() {
static CRATE: &[(&str, &str)] = &[
(
"en_us",
r#"{"test.crate.hello": "Hello", "horizon.osk.close": "Shut", "test.crate.packed": "Crate"}"#,
),
(
"de_de",
r#"{"test.crate.hello": "Grüß dich", "horizon.osk.close": "Zu"}"#,
),
("fr_fr", r#"{"test.crate.hello": "Bonjour"}"#),
];
let pack = Mem(HashMap::from([(
"assets/horizon/lang/en_us.json".to_owned(),
br#"{"test.crate.packed": "Pack"}"#.to_vec(),
)]));
let load = |code| Language::load_with(&[&pack], code, &[CRATE]);
let en = load("en_us");
assert_eq!(en.get("test.crate.hello"), Some("Hello"));
// The engine's own file wins on a key both have; a pack wins over both.
assert_eq!(en.get("horizon.osk.close"), Some("Close"));
assert_eq!(en.get("test.crate.packed"), Some("Pack"));
let de = load("de_de");
assert_eq!(de.get("test.crate.hello"), Some("Grüß dich"));
assert_eq!(de.get("horizon.osk.close"), Some("Schließen"));
// Regional variants read their language's file, as the engine's do.
assert_eq!(load("de_ch").get("test.crate.hello"), Some("Grüss dich"));
assert_eq!(load("fr_ca").get("test.crate.hello"), Some("Bonjour"));
// A language the crate lacks falls back to its English.
assert_eq!(load("pl_pl").get("test.crate.hello"), Some("Hello"));
// Without crate files, nothing changes.
let plain = Language::load_with(&[&pack], "de_de", &[]);
assert_eq!(plain.get("test.crate.hello"), None);
assert_eq!(plain.len() + 1, de.len());
}
#[test]
fn a_scoped_language_is_the_calling_threads_and_reports_what_it_lacks() {
let empty = Mem(HashMap::new());
@@ -837,20 +739,6 @@ mod tests {
std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../horizon-client/assets/horizon/lang")
}
/// The crates whose own lang files the game loads (`crates/<name>/assets/lang`,
/// registered through `horizon_hooks::lang`), with that folder.
fn crate_lang_dirs() -> Vec<(String, std::path::PathBuf)> {
let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut dirs: Vec<_> = std::fs::read_dir(&crates)
.unwrap()
.flatten()
.map(|e| (e.file_name().into_string().unwrap(), e.path()))
.map(|(name, path)| (name, path.join("assets/lang")))
.filter(|(_, dir)| dir.join("en_us.json").is_file())
.collect();
dirs.sort();
dirs
}
/// The keys of a flat bundled file in file order, duplicates included (a map
/// would keep only the last of two equal keys). One `"key": "value"` per line.
fn file_keys(body: &str) -> Vec<String> {
@@ -888,33 +776,11 @@ mod tests {
#[test]
fn bundled_files_are_served_and_have_no_stale_or_repeated_keys() {
let engine = check_lang_dir(&bundled_dir(), true);
assert!(
engine.1 >= 7,
"found {} bundled lang files in {}",
engine.1,
bundled_dir().display()
);
// A crate's files pass the same checks. Its keys are its own: on a key the engine's
// files also have, the engine's text would win and hide the crate's.
for (name, dir) in crate_lang_dirs() {
let (en, _) = check_lang_dir(&dir, false);
for key in en.keys() {
assert!(
!engine.0.contains_key(key),
"{name}: {key} is also the engine's"
);
}
}
}
/// The checks every lang folder passes: flat maps, no repeated key, no key en_us lacks, the
/// same placeholders as English, no empty text. Its en_us and how many files it has.
fn check_lang_dir(dir: &std::path::Path, bundled: bool) -> (HashMap<String, String>, usize) {
let dir = bundled_dir();
let en_body = std::fs::read_to_string(dir.join("en_us.json")).unwrap();
let en: HashMap<String, String> = serde_json::from_str(&en_body).unwrap();
let mut seen = 0;
for entry in std::fs::read_dir(dir).unwrap().flatten() {
for entry in std::fs::read_dir(&dir).unwrap().flatten() {
let name = entry.file_name().into_string().unwrap();
let Some(code) = name.strip_suffix(".json") else {
continue;
@@ -923,7 +789,7 @@ mod tests {
// A file that Bundled::read does not name is never loaded.
let path = format!("assets/horizon/lang/{name}");
assert!(
!bundled || Bundled.read(&path).is_some(),
Bundled.read(&path).is_some(),
"{name} is not served by Bundled"
);
let body = std::fs::read_to_string(entry.path()).unwrap();
@@ -949,7 +815,11 @@ mod tests {
assert!(!value.trim().is_empty(), "{code}: {key} is empty");
}
}
(en, seen)
assert!(
seen >= 7,
"found {seen} bundled lang files in {}",
dir.display()
);
}
#[test]
@@ -964,10 +834,10 @@ mod tests {
}
}
}
let english = |dir: &std::path::Path| -> HashMap<String, String> {
serde_json::from_str(&std::fs::read_to_string(dir.join("en_us.json")).unwrap()).unwrap()
};
let mut en = english(&bundled_dir());
let en: HashMap<String, String> = serde_json::from_str(
&std::fs::read_to_string(bundled_dir().join("en_us.json")).unwrap(),
)
.unwrap();
let crates = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("..");
let mut files = Vec::new();
for krate in [
@@ -977,11 +847,6 @@ mod tests {
] {
rust_files(&crates.join(krate).join("src"), &mut files);
}
// A crate that ships lang files names its keys in its own sources.
for (name, dir) in crate_lang_dirs() {
en.extend(english(&dir));
rust_files(&crates.join(name).join("src"), &mut files);
}
assert!(files.len() > 100, "found only {} sources", files.len());
let mut found = 0;
for file in files {
@@ -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;
+1 -2
View File
@@ -115,8 +115,7 @@ default = ["audio", "controllers", "horizon-extras"]
audio = ["horizon-client-render/audio"]
# Controllers: gilrs, and the DualSense's own output. Without it only `horizon-ctl pad`'s virtual pad.
controllers = ["dep:gilrs", "horizon-client-input/controllers"]
# Horizon's own parts (docs/forking.md, docs/layers.md): the features below, and the official
# server in the list (`official_servers`).
# Horizon's own parts still in this crate (docs/forking.md, docs/layers.md): the features below.
horizon-extras = ["discord"]
# "Playing Horizon" on the player's Discord profile (`discord_presence`).
discord = []
@@ -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
}
}
@@ -386,6 +386,7 @@ fn replay(window: Arc<Window>) -> Result<(), Box<dyn std::error::Error>> {
path: path.clone(),
size: None,
scaled: false,
background: false,
});
for _ in 0..32 {
draw(&mut renderer)?;
@@ -207,6 +207,7 @@ fn fixture(window: Arc<Window>) -> Result<(), Box<dyn std::error::Error>> {
path: out.join("cpu.png"),
size: None,
scaled: false,
background: false,
});
renderer.render(&frame)?;
let expected = read(&out.join("cpu.png"));
@@ -251,6 +252,7 @@ fn fixture(window: Arc<Window>) -> Result<(), Box<dyn std::error::Error>> {
path: out.join("gpu.png"),
size: None,
scaled: false,
background: false,
});
renderer.render(&frame)?;
assert_eq!(
@@ -167,6 +167,7 @@ fn fixture(window: Arc<Window>) -> Result<(), Box<dyn std::error::Error>> {
path: path.clone(),
size: None,
scaled: false,
background: false,
});
// twice: the first frame of a new warp builds it
renderer.render(&frame).unwrap();
@@ -336,6 +337,7 @@ fn bench(renderer: &mut Renderer, out: &Path) -> Result<(), Box<dyn std::error::
path: out.join("bench.png"),
size: None,
scaled: false,
background: false,
});
renderer.render(&frame).unwrap();
renderer.render(&frame).unwrap();
+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 {
+53
View File
@@ -233,6 +233,8 @@ pub struct FogInputs<'a> {
pub night_vision: f32,
/// The packs' `environment` fog settings (Polytone's).
pub environment: crate::pack_palette::Environment,
/// The packs' fluid modifiers' fog.
pub fluid_fog: crate::pack_palette::FluidFogs,
}
/// `FogRenderer.setupFog` + `computeFogColor`.
@@ -397,6 +399,24 @@ pub fn setup_fog(tables: &FogTables, state: &FogState, input: &FogInputs) -> Fog
}
}
}
// A pack's fluid modifier over its fluid's fog, after everything else (wiki "Custom Colors").
let fluid = match input.fog_type {
FogType::Lava => input.fluid_fog.lava,
FogType::Water if input.blindness.is_none() && input.darkness.is_none() => {
input.fluid_fog.water
}
_ => None,
};
if let Some(f) = fluid {
if let Some(rgb) = f.color {
let [r, g, b] = self::rgb(rgb);
fog.color = [r, g, b, 1.0];
}
let end = fog.environmental_end * f.radius;
let start = end - (end - fog.environmental_start * f.radius) * f.fade;
(fog.environmental_start, fog.environmental_end) = (start, end);
(fog.sky_end, fog.cloud_end) = (end, end);
}
let span = (rd / 10.0).clamp(4.0, 64.0);
fog.render_distance_start = rd - span;
fog.render_distance_end = rd;
@@ -495,6 +515,7 @@ mod tests {
full_water_vision: false,
night_vision: 0.0,
environment: Default::default(),
fluid_fog: Default::default(),
}
}
#[test]
@@ -611,6 +632,38 @@ mod tests {
let kept = setup_fog(&tables, &state, &input).color;
assert_eq!(&kept[..3], &[0.1, 0.2, 0.4]);
}
#[test]
fn a_fluid_modifier_scales_and_colours_its_fog_last() {
let sky = Sky {
fog_start: 10.0,
fog_end: 96.0,
..Sky::default()
};
let tables = FogTables {
water_fog_end: vec![1.0],
};
let mut input = inputs(&sky);
input.fog_type = FogType::Lava;
input.fire_resistance = true;
let vanilla = setup_fog(&tables, &FogState::default(), &input);
assert_eq!(
(vanilla.environmental_start, vanilla.environmental_end),
(0.0, 5.0)
);
input.fluid_fog.lava = Some(crate::pack_palette::FluidFog {
color: Some(0x00FF00),
radius: 2.0,
fade: 0.5,
});
let fog = setup_fog(&tables, &FogState::default(), &input);
assert_eq!(fog.color, [0.0, 1.0, 0.0, 1.0]);
// The end doubles; half the fade from 0 to 10 starts it at 5.
assert_eq!(
(fog.environmental_start, fog.environmental_end),
(5.0, 10.0)
);
assert_eq!((fog.sky_end, fog.cloud_end), (10.0, 10.0));
}
fn inputs_with<'a>(
input: &FogInputs<'a>,
environment: crate::pack_palette::Environment,
+40 -107
View File
@@ -201,6 +201,7 @@ pub use hdr::{Calibration as HdrCalibration, Output as HdrOutput};
mod hold;
pub use hold::WorldHold;
pub use output::{DisplayReading, EffectiveOutput, FrameConfiguration, FrameRequest};
pub use screenshot_save::Saved as SavedScreenshot;
pub mod block_light;
mod custom_sky;
mod displace;
@@ -236,6 +237,7 @@ pub mod panorama;
mod readback;
mod resident;
mod reuse;
mod screenshot_save;
mod stars;
mod surface_setup;
use surface_setup::{AdapterChoice, AdapterFailure, open_adapter, pick_adapter, set_up_surface};
@@ -1084,6 +1086,9 @@ pub struct ScreenshotRequest {
/// F2's: drawn at the game's resolution (Resolution Scale above 100%) times
/// `Renderer::screenshot_quality`, not the window's.
pub scaled: bool,
/// Written on a thread of its own (F2's, the world icon's): its outcome comes back a
/// frame or a few later in `Renderer::saved_screenshots`, not `screenshot_result`.
pub background: bool,
}
/// A solid terrain pipeline without HDR output's lighting (terrain.wgsl's `HDR_LIGHTING`),
/// for the frames HDR is off, and with it where the display offers HDR output: the
@@ -1578,6 +1583,9 @@ pub struct Renderer {
pub screenshot_result: Option<std::result::Result<[u32; 2], String>>,
/// The HDR copy the last screenshot wrote beside it, if it wrote one.
pub screenshot_hdr: Option<std::path::PathBuf>,
/// `background` screenshots written since the caller last took them.
pub saved_screenshots: Vec<SavedScreenshot>,
screenshot_saves: screenshot_save::Saves,
/// Screenshot Quality (Horizon setting): a `scaled` screenshot's frame is this many
/// times the game's resolution (1, 2, 4 or 8).
pub screenshot_quality: u32,
@@ -5077,6 +5085,7 @@ impl Renderer {
));
}
let world_primitives = world_primitives::WorldPrimitives::new(&device, frame_format);
let screenshot_saves = screenshot_save::Saves::new(&device);
Ok(Self {
display: None,
reading: display,
@@ -5348,6 +5357,8 @@ impl Renderer {
screenshot: None,
screenshot_result: None,
screenshot_hdr: None,
saved_screenshots: Vec::new(),
screenshot_saves,
screenshot_quality: 1,
screenshot_halvings: 0,
gamma: 0.5,
@@ -7041,8 +7052,10 @@ impl Renderer {
}
}
/// This renderer's output as applied, with what its destination offers and reports.
pub fn output(&self) -> &output::EffectiveOutput {
&self.output
pub fn output(&self) -> output::EffectiveOutput {
let native = self.native.as_ref().map(|n| n.frame.api);
self.output
.with_pack(self.shader_pack_kind() == Some("iris"), native)
}
/// What this renderer's display last reported: a renderer made again for the window
/// starts from it (`Renderer::new`'s `display`).
@@ -7975,6 +7988,8 @@ impl Renderer {
if self.device_lost() {
return Err("the graphics device was lost".into());
}
let saved = self.screenshot_saves.finished();
self.saved_screenshots.extend(saved);
if let Some(request) = self.capture.take() {
let result = self.write_capture(&request, frame);
self.capture_result = Some(result.map_err(|e| e.to_string()));
@@ -8319,9 +8334,7 @@ impl Renderer {
let taa = !frame.title
&& self.pack_post.as_ref().is_none_or(|p| p.1.is_none())
&& self.native.as_ref().is_none_or(|n| n.post.is_none());
let hdr_lighting = self.native.is_none()
&& self.pack_post.as_ref().is_none_or(|p| p.1.is_none())
&& std::env::var_os("HORIZON_HDR_LIGHTING").is_none_or(|v| v != "0");
let hdr_lighting = self.shader_pack_kind().is_none();
if let Some(hdr) = &mut self.hdr {
hdr.lighting = hdr_lighting && hdr.look;
}
@@ -12044,24 +12057,18 @@ impl Renderer {
self.screenshot = Some(request);
} else {
self.screenshot_halvings = 0;
self.screenshot_hdr = None;
if let Some(hdr_buffer) = hdr_readback {
let hdr_path = hdr_screenshot_path(&request.path);
match self.write_hdr_screenshot(&hdr_path, &hdr_buffer) {
Ok(()) => {
log::info!("Saved HDR screenshot to {}", hdr_path.display());
self.screenshot_hdr = Some(hdr_path);
}
Err(e) => log::warn!(
"Horizon renderer: HDR screenshot {}: {e}",
hdr_path.display()
),
}
let size = [self.config.width, self.config.height];
let hdr = hdr_readback
.filter(|_| self.hdr.is_some())
.map(|b| (hdr_screenshot_path(&request.path), b));
let shot = screenshot_save::Shot::new(&request, size, self.config.format, hdr);
if request.background {
self.screenshot_saves.start(shot, buffer);
} else {
let saved = screenshot_save::save_now(&self.device, shot, &buffer);
self.screenshot_hdr = saved.hdr;
self.screenshot_result = Some(saved.result);
}
self.screenshot_result = Some(
self.write_screenshot(&request, &buffer)
.map_err(|e| e.to_string()),
);
}
}
// The frame's own waits for the submit thread (its queue writes and passes).
@@ -12664,96 +12671,22 @@ impl Renderer {
let texture = copy.as_ref().unwrap_or(texture);
Some((request, copy_frame(&self.device, encoder, texture, size)))
} else {
self.screenshot_result = Some(Err(format!(
let error = format!(
"screenshots need a 32-bit surface format, not {:?}",
self.config.format
)));
);
if request.background {
self.saved_screenshots.push(screenshot_save::Saved {
path: request.path,
result: Err(error),
hdr: None,
});
} else {
self.screenshot_result = Some(Err(error));
}
None
}
}
/// The pixels `copy_frame` read back into `buffer`, 4 bytes each, row after row.
fn read_frame(&self, buffer: &wgpu::Buffer) -> Result<Vec<[u8; 4]>> {
let (sender, receiver) = std::sync::mpsc::channel();
buffer.map_async(wgpu::MapMode::Read, .., move |r| {
let _ = sender.send(r);
});
self.device
.poll(wgpu::PollType::wait_indefinitely())
.map_err(|e| e.to_string())?;
receiver
.recv()
.map_err(|e| e.to_string())?
.map_err(|e| e.to_string())?;
let (width, height, row) = (
self.config.width as usize,
self.config.height as usize,
padded_row(self.config.width) as usize,
);
let mut pixels = Vec::with_capacity(width * height);
{
let data = buffer.get_mapped_range(..).map_err(|e| e.to_string())?;
for y in 0..height {
pixels.extend_from_slice(data[y * row..y * row + width * 4].as_chunks::<4>().0);
}
}
buffer.unmap();
Ok(pixels)
}
fn write_screenshot(
&self,
request: &ScreenshotRequest,
buffer: &wgpu::Buffer,
) -> Result<[u32; 2]> {
let bgra = matches!(
self.config.format.remove_srgb_suffix(),
wgpu::TextureFormat::Bgra8Unorm
);
let mut pixels = Vec::with_capacity((self.config.width * self.config.height * 4) as usize);
for px in self.read_frame(buffer)? {
let (r, b) = if bgra { (px[2], px[0]) } else { (px[0], px[2]) };
pixels.extend_from_slice(&[r, px[1], b, 255]);
}
// NativeImage.resizeSubRectTo on takeAutoScreenshot's grab: the icon
// is the frame's centre square averaged down to its size.
let (width, height, pixels) = match request.size {
Some(size) => (
size[0],
size[1],
square_downscale(&pixels, self.config.width, self.config.height, size),
),
None => (self.config.width, self.config.height, pixels),
};
let mut encoder = png::Encoder::new(
std::io::BufWriter::new(std::fs::File::create(&request.path)?),
width,
height,
);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
encoder.write_header()?.write_image_data(&pixels)?;
Ok([width, height])
}
/// The HDR10 copy (`Hdr::capture`) as a 16-bit PNG tagged BT.2020 with PQ (cICP, PNG's
/// third edition), with the content light levels its pixels hold (cLLI), and
/// an ICC profile for the programs that don't read cICP (`hdr_icc`).
fn write_hdr_screenshot(&self, path: &std::path::Path, buffer: &wgpu::Buffer) -> Result<()> {
if self.hdr.is_none() {
return Ok(());
}
let pixels = hdr10_to_rgb16(&self.read_frame(buffer)?);
let mut info = png::Info::with_size(self.config.width, self.config.height);
info.color_type = png::ColorType::Rgb;
info.bit_depth = png::BitDepth::Sixteen;
info.icc_profile = Some(hdr_icc::profile().into());
let encoder =
png::Encoder::with_info(std::io::BufWriter::new(std::fs::File::create(path)?), info)?;
let mut writer = encoder.write_header()?;
// BT.2020 primaries, PQ, RGB, full range.
writer.write_chunk(png::chunk::cICP, &[9, 16, 0, 1])?;
writer.write_chunk(png::chunk::cLLI, &hdr_icc::content_light_levels(&pixels))?;
writer.write_image_data(&pixels)?;
Ok(())
}
}
/// `screenshots/2026-10-28_12.00.00.png` -> `screenshots/2026-10-28_12.00.00-hdr.png`.
fn hdr_screenshot_path(path: &std::path::Path) -> PathBuf {
+1 -1
View File
@@ -191,7 +191,7 @@ pub struct Hdr {
pub masks: Masks,
/// HDR lighting, whether Horizon lifts this frame's world: off under a Horizon shader pack
/// that draws, while a `shaders/` pack's post or material stage runs (the pack's own),
/// with HDR Lighting (`look`) off, and with `HORIZON_HDR_LIGHTING=0`, to compare.
/// and with HDR Lighting (`look`) off.
pub lighting: bool,
/// The HDR Lighting setting: off, nothing in the world is lifted, light sources and the
/// sun included, so the picture is SDR's on the HDR canvas.
@@ -144,6 +144,9 @@ pub struct EffectiveOutput {
pub(crate) nits: [f32; 3],
/// The HUD and menus' brightness, as a share of paper white: their nits over its.
pub(crate) ui_brightness: f32,
/// The running shader pack lights the world itself: Horizon lifts none of it, so HDR
/// Lighting has nothing to switch (`with_pack`).
pub(crate) pack_lights: bool,
}
impl Default for EffectiveOutput {
fn default() -> Self {
@@ -166,7 +169,22 @@ impl EffectiveOutput {
},
nits: [203.0, 1000.0, 0.0],
ui_brightness: 1.0,
pack_lights: false,
};
/// This output under the running shader pack: a `shaders/` one (`shaders`), or one of
/// Horizon's own of API `native`. Under a 0.1 pack on the 8- or 16-bit frame the last pass
/// still lifts the light sources and the sun its marks hold (`lifts_world` in
/// `Renderer::render`); under the rest Horizon lifts nothing.
pub(crate) fn with_pack(self, shaders: bool, native: Option<horizon_shader_api::Api>) -> Self {
let pack_lights = shaders
|| native.is_some_and(|api| {
api != horizon_shader_api::Api::V0_1 || self.frame.format == super::LINEAR_FRAME
});
Self {
pack_lights,
..self
}
}
/// Whether the destination offers HDR output.
pub fn hdr_offered(&self) -> bool {
self.offered.is_some()
@@ -273,6 +291,7 @@ pub(crate) fn resolve_output(
],
ui_brightness: settings.ui_nits(reading.luminance) as f32
/ settings.paper_white_nits(reading.luminance) as f32,
pack_lights: false,
}
}
@@ -0,0 +1,321 @@
//! Writing a screenshot's PNG once its frame is read back: on the render thread for the
//! requests that want the result with the frame (an agent's, a `screenshot-sequence`'s),
//! on a thread of its own for F2's and the world icon's (`ScreenshotRequest::background`).
//! The render thread then neither waits for the GPU to finish the frame nor encodes the
//! PNG, which at 4K or a Screenshot Quality above 1x froze the game for a second or more.
use super::{ScreenshotRequest, hdr_icc, hdr10_to_rgb16, padded_row, square_downscale};
use std::path::PathBuf;
use std::sync::mpsc::{Receiver, Sender, channel};
use std::time::Duration;
/// What a frame's readback holds and where its PNG goes.
pub(super) struct Shot {
pub path: PathBuf,
/// `ScreenshotRequest::size`: the world icon's square.
pub size: Option<[u32; 2]>,
/// The frame's size, which the readback's rows hold (padded to `padded_row`).
pub frame: [u32; 2],
/// Blue first (`Bgra8Unorm`), swapped to PNG's red first.
pub bgra: bool,
/// The HDR10 copy's readback and its PNG's path, beside the SDR one.
pub hdr: Option<(PathBuf, wgpu::Buffer)>,
}
impl Shot {
pub fn new(
request: &ScreenshotRequest,
frame: [u32; 2],
format: wgpu::TextureFormat,
hdr: Option<(PathBuf, wgpu::Buffer)>,
) -> Self {
Self {
path: request.path.clone(),
size: request.size,
frame,
bgra: format.remove_srgb_suffix() == wgpu::TextureFormat::Bgra8Unorm,
hdr,
}
}
}
/// A written screenshot: its path, its size or the error, and the HDR copy written beside it.
pub struct Saved {
pub path: PathBuf,
pub result: Result<[u32; 2], String>,
pub hdr: Option<PathBuf>,
}
/// Waits for `buffer`'s mapping on the render thread and writes the PNG there.
pub(super) fn save_now(device: &wgpu::Device, shot: Shot, buffer: &wgpu::Buffer) -> Saved {
let (sender, receiver) = channel();
map(buffer, &sender);
if let Some((_, hdr)) = &shot.hdr {
map(hdr, &sender);
}
let waited = device
.poll(wgpu::PollType::wait_indefinitely())
.map_err(|e| e.to_string());
let count = 1 + usize::from(shot.hdr.is_some());
let mapped = waited.and_then(|_| wait_mapped(&receiver, count));
write(shot, buffer, mapped)
}
/// Screenshots being written on their thread.
pub(super) struct Saves {
device: wgpu::Device,
sender: Sender<Saved>,
receiver: Receiver<Saved>,
in_flight: usize,
}
impl Saves {
pub fn new(device: &wgpu::Device) -> Self {
let (sender, receiver) = channel();
Self {
device: device.clone(),
sender,
receiver,
in_flight: 0,
}
}
/// Maps `buffer` (and the HDR copy's), whose copy was just submitted, and writes the
/// PNG on a thread of its own once the GPU has finished the frame.
pub fn start(&mut self, shot: Shot, buffer: wgpu::Buffer) {
let (mapped, on_mapped) = channel();
map(&buffer, &mapped);
if let Some((_, hdr)) = &shot.hdr {
map(hdr, &mapped);
}
let done = self.sender.clone();
let path = shot.path.clone();
let spawned = std::thread::Builder::new()
.name("Screenshot writer".into())
.spawn(move || {
let count = 1 + usize::from(shot.hdr.is_some());
let ready = wait_mapped(&on_mapped, count);
let _ = done.send(write(shot, &buffer, ready));
});
match spawned {
Ok(_) => {}
Err(e) => {
let _ = self.sender.send(Saved {
path,
result: Err(format!("no thread to write it: {e}")),
hdr: None,
});
}
}
self.in_flight += 1;
}
/// The screenshots written since the last call. Polls the device so a finished frame's
/// mapping reaches its writer: the render thread never waits for it.
pub fn finished(&mut self) -> Vec<Saved> {
if self.in_flight == 0 {
return Vec::new();
}
let _ = self.device.poll(wgpu::PollType::Poll);
let saved: Vec<Saved> = self.receiver.try_iter().collect();
self.in_flight -= saved.len();
saved
}
}
impl Drop for Saves {
/// A screenshot taken right before quitting is still written whole.
fn drop(&mut self) {
let deadline = std::time::Instant::now() + Duration::from_secs(10);
while self.in_flight > 0 && std::time::Instant::now() < deadline {
let _ = self.device.poll(wgpu::PollType::Poll);
if let Ok(saved) = self.receiver.recv_timeout(Duration::from_millis(20)) {
log_saved(&saved);
self.in_flight -= 1;
}
}
}
}
fn log_saved(saved: &Saved) {
match &saved.result {
Ok(_) => log::info!("Saved screenshot to {}", saved.path.display()),
Err(e) => log::warn!("Horizon renderer: screenshot {}: {e}", saved.path.display()),
}
}
fn map(buffer: &wgpu::Buffer, mapped: &Sender<Result<(), String>>) {
let mapped = mapped.clone();
buffer.map_async(wgpu::MapMode::Read, .., move |r| {
let _ = mapped.send(r.map_err(|e| e.to_string()));
});
}
/// `count` mappings done, or the first one that failed. A frame the GPU never finishes
/// (a lost device) gives up after a while instead of keeping its thread.
fn wait_mapped(mapped: &Receiver<Result<(), String>>, count: usize) -> Result<(), String> {
for _ in 0..count {
mapped
.recv_timeout(Duration::from_secs(30))
.map_err(|_| "the frame never came back from the GPU".to_string())??;
}
Ok(())
}
/// The PNG (and the HDR copy's beside it) from the mapped readbacks.
fn write(shot: Shot, buffer: &wgpu::Buffer, mapped: Result<(), String>) -> Saved {
let mut hdr_written = None;
let result = mapped.and_then(|()| {
if let Some((hdr_path, hdr_buffer)) = &shot.hdr {
let pixels = read_rows(hdr_buffer, shot.frame);
match pixels.and_then(|p| write_hdr_png(hdr_path, shot.frame, &p)) {
Ok(()) => {
log::info!("Saved HDR screenshot to {}", hdr_path.display());
hdr_written = Some(hdr_path.clone());
}
Err(e) => log::warn!(
"Horizon renderer: HDR screenshot {}: {e}",
hdr_path.display()
),
}
}
let pixels = read_rows(buffer, shot.frame)?;
write_png(&shot, &pixels)
});
Saved {
path: shot.path,
result,
hdr: hdr_written,
}
}
/// The pixels `copy_frame` read back into the mapped `buffer`, 4 bytes each, row after
/// row; unmaps it.
fn read_rows(buffer: &wgpu::Buffer, [width, height]: [u32; 2]) -> Result<Vec<[u8; 4]>, String> {
let (width, height, row) = (width as usize, height as usize, padded_row(width) as usize);
let mut pixels = Vec::with_capacity(width * height);
{
let data = buffer.get_mapped_range(..).map_err(|e| e.to_string())?;
for y in 0..height {
pixels.extend_from_slice(data[y * row..y * row + width * 4].as_chunks::<4>().0);
}
}
buffer.unmap();
Ok(pixels)
}
fn write_png(shot: &Shot, frame: &[[u8; 4]]) -> Result<[u32; 2], String> {
let [frame_w, frame_h] = shot.frame;
let mut pixels = Vec::with_capacity(frame.len() * 4);
for px in frame {
let (r, b) = if shot.bgra {
(px[2], px[0])
} else {
(px[0], px[2])
};
pixels.extend_from_slice(&[r, px[1], b, 255]);
}
// NativeImage.resizeSubRectTo on takeAutoScreenshot's grab: the icon
// is the frame's centre square averaged down to its size.
let (width, height, pixels) = match shot.size {
Some(size) => (
size[0],
size[1],
square_downscale(&pixels, frame_w, frame_h, size),
),
None => (frame_w, frame_h, pixels),
};
let file = std::fs::File::create(&shot.path).map_err(|e| e.to_string())?;
let mut encoder = png::Encoder::new(std::io::BufWriter::new(file), width, height);
encoder.set_color(png::ColorType::Rgba);
encoder.set_depth(png::BitDepth::Eight);
encoder
.write_header()
.and_then(|mut w| w.write_image_data(&pixels))
.map_err(|e| e.to_string())?;
Ok([width, height])
}
/// The HDR10 copy (`Hdr::capture`) as a 16-bit PNG tagged BT.2020 with PQ (cICP, PNG's
/// third edition), with the content light levels its pixels hold (cLLI), and
/// an ICC profile for the programs that don't read cICP (`hdr_icc`).
fn write_hdr_png(
path: &std::path::Path,
[width, height]: [u32; 2],
frame: &[[u8; 4]],
) -> Result<(), String> {
let pixels = hdr10_to_rgb16(frame);
let mut info = png::Info::with_size(width, height);
info.color_type = png::ColorType::Rgb;
info.bit_depth = png::BitDepth::Sixteen;
info.icc_profile = Some(hdr_icc::profile().into());
let file = std::fs::File::create(path).map_err(|e| e.to_string())?;
let written = png::Encoder::with_info(std::io::BufWriter::new(file), info)
.and_then(|encoder| encoder.write_header())
.and_then(|mut writer| {
// BT.2020 primaries, PQ, RGB, full range.
writer.write_chunk(png::chunk::cICP, &[9, 16, 0, 1])?;
writer.write_chunk(png::chunk::cLLI, &hdr_icc::content_light_levels(&pixels))?;
writer.write_image_data(&pixels)
});
written.map_err(|e| e.to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_background_save_writes_the_png_off_the_render_thread() {
let instance = crate::gfx::test_gpu::instance();
let Ok(adapter) = pollster::block_on(instance.request_adapter(&Default::default())) else {
return;
};
let Ok((device, queue)) = pollster::block_on(adapter.request_device(&Default::default()))
else {
return;
};
let dir = std::env::temp_dir().join(format!("horizon-shot-{}", std::process::id()));
std::fs::create_dir_all(&dir).unwrap();
let path = dir.join("shot.png");
let [w, h] = [3u32, 2];
// A frame of blue-first pixels, each row padded as `copy_frame` reads them back.
let row = padded_row(w) as usize;
let mut bytes = vec![0u8; row * h as usize];
for y in 0..h as usize {
for x in 0..w as usize {
bytes[y * row + x * 4..][..4].copy_from_slice(&[10 * x as u8, 20, 200, 0]);
}
}
let source = wgpu::util::DeviceExt::create_buffer_init(
&device,
&wgpu::util::BufferInitDescriptor {
label: None,
contents: &bytes,
usage: wgpu::BufferUsages::COPY_SRC,
},
);
let buffer = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: bytes.len() as u64,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
let mut encoder = device.create_command_encoder(&Default::default());
encoder.copy_buffer_to_buffer(&source, 0, &buffer, 0, bytes.len() as u64);
queue.submit([encoder.finish()]);
let request = ScreenshotRequest {
path: path.clone(),
size: None,
scaled: false,
background: true,
};
let mut saves = Saves::new(&device);
saves.start(
Shot::new(&request, [w, h], wgpu::TextureFormat::Bgra8Unorm, None),
buffer,
);
let deadline = std::time::Instant::now() + Duration::from_secs(10);
let saved = loop {
if let Some(saved) = saves.finished().pop() {
break saved;
}
assert!(std::time::Instant::now() < deadline, "never written");
std::thread::sleep(Duration::from_millis(5));
};
assert_eq!(saved.path, path);
assert_eq!(saved.result, Ok([w, h]));
let decoder =
png::Decoder::new(std::io::BufReader::new(std::fs::File::open(&path).unwrap()));
let mut reader = decoder.read_info().unwrap();
let mut out = vec![0; reader.output_buffer_size().unwrap()];
reader.next_frame(&mut out).unwrap();
// Red first, opaque: the last pixel of the first row was [20, 20, 200] blue-first.
assert_eq!(&out[8..12], &[200, 20, 20, 255]);
std::fs::remove_dir_all(&dir).unwrap();
}
}
@@ -1110,7 +1110,8 @@ impl Item {
/// active; saved values wait for it. Translucent Batching switches where the device can batch
/// (`graphics::translucent_batching_offered`), its saved value waiting for one that can,
/// Smooth Gradients only where it can draw the 16-bit frame, the same way, and GPU Culling
/// only where it is offered (`graphics::gpu_culling_offer`), with the reason it isn't.
/// only where it is offered (`graphics::gpu_culling_offer`), with the reason it isn't. HDR
/// Lighting has nothing to switch where the running shader pack lights the world itself.
fn blocked(self, s: &Settings, out: &EffectiveOutput) -> Option<&'static str> {
if !self.available() {
return Some("This feature is not yet available in Horizon.");
@@ -1141,6 +1142,9 @@ impl Item {
} else {
"Turn HDR on to use it."
}),
Item::Horizon(H::HdrLighting) if out.pack_lights => {
Some("The shader pack lights the world itself.")
}
Item::Horizon(H::TranslucentBatching)
if !crate::graphics::translucent_batching_offered() =>
{
@@ -31,6 +31,49 @@ fn smooth_gradients_wait_for_a_device_that_draws_the_16_bit_frame() {
assert_eq!(item.blocked(&s, &out), Some("Turn HDR on to use it."));
}
#[test]
fn hdr_lighting_is_greyed_only_where_the_running_pack_lights_the_world() {
use horizon_shader_api::Api;
let mut s = Settings::default();
s.horizon.hdr = HdrMode::On;
let item = Item::Horizon(H::HdrLighting);
let lights = Some("The shader pack lights the world itself.");
let out = offering(true, None);
// No pack running, as with one picked but refused, missing or its mod off: live.
assert_eq!(item.blocked(&s, &out.with_pack(false, None)), None);
// A 0.1 pack on the 16-bit frame: the light sources and the sun still shine.
assert_eq!(
item.blocked(&s, &out.with_pack(false, Some(Api::V0_1))),
None
);
assert_eq!(
item.blocked(&s, &out.with_pack(false, Some(Api::V0_2))),
lights
);
assert_eq!(item.blocked(&s, &out.with_pack(true, None)), lights);
let float = EffectiveOutput {
frame: crate::gfx::FrameConfiguration {
format: wgpu::TextureFormat::Rgba16Float,
..out.frame
},
..out
};
assert_eq!(
item.blocked(&s, &float.with_pack(false, Some(Api::V0_1))),
lights
);
// HDR's own reasons come first.
assert_eq!(
item.blocked(&s, &NONE.with_pack(true, None)),
Some("Your display or system doesn't offer HDR output.")
);
s.horizon.hdr = HdrMode::Off;
assert_eq!(
item.blocked(&s, &out.with_pack(true, None)),
Some("Turn HDR on to use it.")
);
}
#[test]
fn hdr_auto_can_be_selected_before_querying_and_brightness_waits_for_output() {
let mut s = Settings::default();
@@ -7,6 +7,14 @@ use horizon_polytone::colors::PackColors;
use crate::block_entity_render::DYES;
use crate::pack_palette::{self, Environment};
fn fluid(fog: horizon_polytone::colors::FluidFog) -> pack_palette::FluidFog {
pack_palette::FluidFog {
color: fog.color,
radius: fog.radius,
fade: fog.fade,
}
}
/// 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);
@@ -29,6 +37,10 @@ pub fn read(root: &Path) -> pack_palette::PackColors {
water_fog_brightening_time: env.water_fog_brightening_time,
horizon_height: env.horizon_height,
},
fluid_fog: pack_palette::FluidFogs {
water: colors.fluid_fog.water.map(fluid),
lava: colors.fluid_fog.lava.map(fluid),
},
}
}
@@ -59,6 +59,24 @@ pub struct PackColors {
pub xp_bar: [Option<u32>; 2],
/// The effect fogs' settings: the fog reads them every frame.
pub env: Environment,
/// The fog the packs' fluid modifiers give water and lava.
pub fluid_fog: FluidFogs,
}
/// A fluid modifier's fog: a flat colour (RGB), and the fog's radius and fade multipliers (1 is
/// vanilla's).
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct FluidFog {
pub color: Option<u32>,
pub radius: f32,
pub fade: f32,
}
/// The fog the packs' fluid modifiers give water and lava.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct FluidFogs {
pub water: Option<FluidFog>,
pub lava: Option<FluidFog>,
}
impl Default for PackColors {
@@ -72,6 +90,7 @@ impl Default for PackColors {
entity_shadows: true,
xp_bar: [None; 2],
env: Environment::default(),
fluid_fog: FluidFogs::default(),
}
}
}
@@ -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> {
@@ -337,6 +337,13 @@ impl Settings {
.and_then(|mode| self.video_modes.iter().position(|m| *m == mode))
.map_or(-1, |i| i as i32)
}
/// Loads only the crates' settings stores (`horizon_hooks::settings`) from the files next to
/// `path`, into the seat whose turn it is (`horizon_hooks::seat`): a splitscreen player whose
/// settings were made from P1's rather than loaded.
pub fn load_stores(path: &Path) {
let dir = path.parent();
horizon_hooks::settings::engine::load(&mut |file| fs::read_to_string(dir?.join(file)).ok());
}
pub fn load(path: &Path) -> Self {
let mut horizon = path
.parent()
@@ -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,
+6 -1
View File
@@ -39,6 +39,8 @@ horizon-chat-filter = { path = "../horizon-chat-filter" }
horizon-shaders = { path = "../horizon-shaders" }
# Horizon's own shader packs: the format, the stages and the check (docs/shaders.md).
horizon-shader-api = { path = "../horizon-shader-api" }
# Play with Friends: invite codes and their tunnel; the `friends` feature.
horizon-friends = { path = "../horizon-friends", optional = true }
# The narrator (GameNarrator): text-to-speech of chat, system messages and screens.
horizon-narrator = { path = "../horizon-narrator" }
# Horizon mods: sandboxed WebAssembly components, off unless installed and turned on (docs/mods.md).
@@ -121,10 +123,13 @@ controllers = ["horizon-client-lib/controllers", "dep:gilrs", "dep:horizon-duals
# 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", "horizon-client-render/horizon-extras", "discord"]
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"]
# Play with Friends: sharing a world behind an invite code (game/friends.rs). Joining one is
# horizon-friends' `game` side, which horizon-official registers (`horizon_hooks::tunnel`).
friends = ["dep:horizon-friends"]
# Records the call sites of mob random draws (`mob_ai_probe` traces).
rng-trace = ["horizon-core/rng-trace", "horizon-client-lib/rng-trace"]
# Rust's allocations go to the system heap instead of mimalloc, where heap profilers that replace
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Herbegin die speletjie om %s toe te pas: hulle voeg blokke, items of wêreldgenerering by.",
"horizon.shader_options.profile": "Profiel",
"horizon.agent.copy_details": "Kopieer verbindingbesonderhede",
"horizon.multiplayer.join": "Sluit aan",
"horizon.multiplayer.cancel_reconnecting": "Kanselleer Herkoppel",
"horizon.multiplayer.join_friend": "Sluit aan by 'n Vriend",
"horizon.multiplayer.invite_code": "Uitnodigingskode",
"horizon.multiplayer.relay": "Aflos (opsioneel)",
"Preset": "Vooraf ingesteld",
"LOD Distance": "LOD Afstand",
"Far Detail": "Verre Detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Vanlyn profiele behoort aan hierdie geval",
"horizon.splitscreen.profiles.move": "Beweeg waar jy speel",
"horizon.splitscreen.profiles.move_place": "Beweeg waar jy speel: %s",
"horizon.friends.title": "Speel met vriende",
"horizon.friends.hint": "Vriende plak die kode na die titelskerm se Vriende-knoppie, in Direkte verbinding, of op die lanseerder se Speel-bladsy.",
"horizon.friends.copied": "Gekopieer",
"horizon.friends.copy_code": "Kopieer kode",
"horizon.friends.stop_sharing": "Hou op deel",
"horizon.friends.none_yet": "Nog geen vriende hier nie.",
"horizon.friends.here_now": "Hier nou: %s",
"horizon.friends.share_intro": "Deel hierdie wêreld agter 'n uitnodigingskode: dit maak oop na LAN, en vriende op die internet sluit aan met die kode. Geen bediener van ons is betrokke nie.",
"horizon.friends.start_sharing": "Begin deel",
"horizon.friends.troubleshooting": "Foutsporing …",
"horizon.friends.stopped": "Het opgehou om die uitnodigingkode te deel.",
"horizon.friends.short_code_changed": "Iemand het aanhou om 'n verkeerde kort kode te probeer, so dit het verander.",
"horizon.friends.wrong_code": "Iemand het 'n verkeerde kode probeer.",
"horizon.friends.relay_stopped": "Te veel verkeerde kort kodes, so die aflos is af totdat jy weer deel. Vriende kan steeds met die volle kode aansluit.",
"horizon.friends.code_ready": "Jou uitnodigingskode is gereed: Speletjie-kieslys, Speel met vriende. Kopieer dit en stuur dit aan jou vriende.",
"horizon.friends.share_failed": "Kon nie die wêreld deel nie: %s",
"horizon.friends.finding_route": "Vind tans hoe vriende jou kan bereik …",
"horizon.osk.shift": "Verskuiwing",
"horizon.osk.space": "Ruimte",
"horizon.osk.delete": "Vee uit",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "أعد تشغيل اللعبة لتطبيق %s: فهي تضيف كتلًا أو عناصر أو توليد عالم.",
"horizon.shader_options.profile": "الملف الشخصي",
"horizon.agent.copy_details": "نسخ تفاصيل الاتصال",
"horizon.multiplayer.join": "انضم",
"horizon.multiplayer.cancel_reconnecting": "إلغاء إعادة الاتصال",
"horizon.multiplayer.join_friend": "انضم إلى صديق",
"horizon.multiplayer.invite_code": "رمز الدعوة",
"horizon.multiplayer.relay": "التتابع (اختياري)",
"Preset": "محددة مسبقا",
"LOD Distance": "مسافة اللد",
"Far Detail": "تفاصيل بعيدة",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "تنتمي الملفات الشخصية غير المتصلة بالإنترنت إلى هذه الحالة",
"horizon.splitscreen.profiles.move": "تحرك حيث تلعب",
"horizon.splitscreen.profiles.move_place": "تحرك حيث تلعب: %s",
"horizon.friends.title": "العب مع الأصدقاء",
"horizon.friends.hint": "يقوم الأصدقاء بلصق الرمز بعد زر الأصدقاء على شاشة العنوان، أو في الاتصال المباشر، أو على صفحة التشغيل الخاصة بالمشغل.",
"horizon.friends.copied": "منقول",
"horizon.friends.copy_code": "نسخ الرمز",
"horizon.friends.stop_sharing": "توقف عن المشاركة",
"horizon.friends.none_yet": "لا يوجد أصدقاء هنا بعد.",
"horizon.friends.here_now": "هنا الآن: %s",
"horizon.friends.share_intro": "شارك هذا العالم خلف رمز الدعوة: فهو يفتح على شبكة LAN، وينضم الأصدقاء على الإنترنت باستخدام الرمز. لا يوجد خادم خاص بنا متورط.",
"horizon.friends.start_sharing": "ابدأ المشاركة",
"horizon.friends.troubleshooting": "استكشاف الأخطاء وإصلاحها...",
"horizon.friends.stopped": "تم إيقاف مشاركة رمز الدعوة.",
"horizon.friends.short_code_changed": "استمر شخص ما في تجربة رمز قصير خاطئ، لذلك تغير.",
"horizon.friends.wrong_code": "حاول شخص ما رمزا خاطئا.",
"horizon.friends.relay_stopped": "رموز قصيرة خاطئة كثيرة، لذا أُوقف التتابع حتى تشارك مجددًا. يمكن للأصدقاء الانضمام بالرمز الكامل.",
"horizon.friends.code_ready": "رمز الدعوة الخاص بك جاهز: قائمة الألعاب، العب مع الأصدقاء. انسخها وأرسلها إلى أصدقائك.",
"horizon.friends.share_failed": "لا يمكن مشاركة العالم: %s",
"horizon.friends.finding_route": "التعرف على كيفية وصول الأصدقاء إليك...",
"horizon.osk.shift": "التحول",
"horizon.osk.space": "الفضاء",
"horizon.osk.delete": "حذف",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s tətbiq etmək üçün oyunu yenidən başladın: onlar bloklar, əşyalar və ya dünya yaradılması əlavə edir.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Bağlantı təfərrüatlarını kopyalayın",
"horizon.multiplayer.join": "Qoşulun",
"horizon.multiplayer.cancel_reconnecting": "Yenidən qoşulmanı ləğv edin",
"horizon.multiplayer.join_friend": "Dosta Qoşulun",
"horizon.multiplayer.invite_code": "Dəvət Kodu",
"horizon.multiplayer.relay": "Rele (isteğe bağlı)",
"Preset": "Əvvəlcədən təyin",
"LOD Distance": "LOD məsafəsi",
"Far Detail": "Uzaq Detal",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Oflayn profillər bu instansiyaya aiddir",
"horizon.splitscreen.profiles.move": "Oynadığınız yerdə hərəkət edin",
"horizon.splitscreen.profiles.move_place": "Oynadığınız yerə köçürün: %s",
"horizon.friends.title": "Dostlarla oynayın",
"horizon.friends.hint": "Dostlar kodu başlıq ekranının Dostlar düyməsindən sonra, Birbaşa Bağlantıda və ya başlatma qurğusunun Play səhifəsində yerləşdirin.",
"horizon.friends.copied": "Kopyalandı",
"horizon.friends.copy_code": "Kodu kopyalayın",
"horizon.friends.stop_sharing": "Paylaşmağı dayandırın",
"horizon.friends.none_yet": "Burada hələ dost yoxdur.",
"horizon.friends.here_now": "İndi burada: %s",
"horizon.friends.share_intro": "Bu dünyanı dəvət kodunun arxasında paylaşın: o, LAN-a açılır və internetdəki dostlar kodla qoşulur. Heç bir serverimiz iştirak etmir.",
"horizon.friends.start_sharing": "Paylaşmağa başlayın",
"horizon.friends.troubleshooting": "Problem həll olunur...",
"horizon.friends.stopped": "Dəvət kodunu paylaşmağı dayandırdı.",
"horizon.friends.short_code_changed": "Kimsə səhv qısa kodu sınamağa davam etdi, ona görə də dəyişdi.",
"horizon.friends.wrong_code": "Kimsə səhv kodu sınadı.",
"horizon.friends.relay_stopped": "Çox sayda yanlış qısa kod daxil edildi, ona görə yenidən paylaşana qədər rele söndürülüb. Dostlar hələ də tam kodla qoşula bilər.",
"horizon.friends.code_ready": "Dəvət kodunuz hazırdır: Oyun Menyu, Dostlarla Oyna. Kopyalayın və dostlarınıza göndərin.",
"horizon.friends.share_failed": "Dünyanı paylaşmaq mümkün olmadı: %s",
"horizon.friends.finding_route": "Dostların sizinlə necə əlaqə saxlaya biləcəyi tapılır...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Kosmos",
"horizon.osk.delete": "Sil",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s ҡулланыу өсөн уйынды яңынан эшләтегеҙ: улар блоктар, әйберҙәр йәки донъя генерацияһын өҫтәй.",
"horizon.shader_options.profile": "Профиль",
"horizon.agent.copy_details": "Тоташыу тураһында мәғлүмәтте күсерергә",
"horizon.multiplayer.join": "Ҡушылыу",
"horizon.multiplayer.cancel_reconnecting": "Яңынан тоташтырыуҙы юҡҡа сығарыу",
"horizon.multiplayer.join_friend": "Дуҫҡа ҡушыл",
"horizon.multiplayer.invite_code": "Саҡырыу коды",
"horizon.multiplayer.relay": "Реле (теләк буйынса)",
"Preset": "Алдан ҡуйылған",
"LOD Distance": "LOD арауығы",
"Far Detail": "Алыҫ деталь",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профилдәр был данаға ҡарай",
"horizon.splitscreen.profiles.move": "Уйнаған ергә күсерегеҙ .",
"horizon.splitscreen.profiles.move_place": "Уйнаған урынға күсегеҙ: %s .",
"horizon.friends.title": "Дуҫтар менән уйнау .",
"horizon.friends.hint": "Дуҫтар кодты титул экранының «Дуҫтар» төймәһенән һуң, туранан-тура бәйләнештә йәки стартердың «Уйнау» битендә йәбештерә.",
"horizon.friends.copied": "Күсерелгән",
"horizon.friends.copy_code": "Код күсермәһе",
"horizon.friends.stop_sharing": "Бүлешеүҙе туҡтатығыҙ",
"horizon.friends.none_yet": "Бында әлегә дуҫтар юҡ.",
"horizon.friends.here_now": "Бында хәҙер: %s",
"horizon.friends.share_intro": "Был донъя менән бүлешергә артында саҡырыу коды: ул LAN асыла, һәм дуҫтар интернетта код менән ҡушыла. Беҙҙең бер сервер ҙа ҡатнашмай.",
"horizon.friends.start_sharing": "Бүлешергә башлағыҙ",
"horizon.friends.troubleshooting": "Неисправность...",
"horizon.friends.stopped": "Саҡырыу коды менән бүлешеүҙе туҡтатты.",
"horizon.friends.short_code_changed": "Кемдер дөрөҫ булмаған ҡыҫҡа кодты һынап ҡараны, шуға күрә ул үҙгәрҙе.",
"horizon.friends.wrong_code": "Кемдер дөрөҫ булмаған кодты ҡулланып ҡараған.",
"horizon.friends.relay_stopped": "Дөрөҫ булмаған ҡыҫҡа кодтар бик күп булды, шуға күрә ҡабат бүлешкәнгә тиклем реле һүндерелгән. Дуҫтар тулы код менән килеүен дауам итә ала.",
"horizon.friends.code_ready": "Һеҙҙең саҡырыу коды әҙер: Уйын Менюһы, Дуҫтар менән уйнау. Күсереп яҙып, дуҫтарығыҙға ебәрегеҙ.",
"horizon.friends.share_failed": "Донъяны бүлешә алманым: %s",
"horizon.friends.finding_route": "Һеҙгә дуҫтар нисек барып етә алыуын табыу...",
"horizon.osk.shift": "Смена",
"horizon.osk.space": "Йыһан",
"horizon.osk.delete": "Юйырға",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Перазапусціце гульню, каб ужыць %s: яны дадаюць блокі, прадметы або генерацыю свету.",
"horizon.shader_options.profile": "Профіль",
"horizon.agent.copy_details": "Скапіруйце звесткі аб падключэнні",
"horizon.multiplayer.join": "Далучайцеся",
"horizon.multiplayer.cancel_reconnecting": "Адмяніць паўторнае падключэнне",
"horizon.multiplayer.join_friend": "Далучайцеся да сяброў",
"horizon.multiplayer.invite_code": "Код запрашэння",
"horizon.multiplayer.relay": "Рэле (неабавязкова)",
"Preset": "Прадусталяваная",
"LOD Distance": "LOD Адлегласць",
"Far Detail": "Далёкая дэталь",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Афлайн-профілі належаць да гэтага асобніка",
"horizon.splitscreen.profiles.move": "Рухайцеся туды, дзе гуляеце",
"horizon.splitscreen.profiles.move_place": "Рухайцеся туды, дзе вы гуляеце: %s",
"horizon.friends.title": "Гуляць з сябрамі",
"horizon.friends.hint": "Сябры ўстаўце код пасля кнопкі \"Сябры\" на тытульным экране ў раздзеле \"Прамое злучэнне\" або на старонцы \"Прайграванне\" праграмы запуску.",
"horizon.friends.copied": "Скапіравана",
"horizon.friends.copy_code": "Скапіруйце код",
"horizon.friends.stop_sharing": "Спыніць абагульванне",
"horizon.friends.none_yet": "Тут пакуль няма сяброў.",
"horizon.friends.here_now": "Вось зараз: %s",
"horizon.friends.share_intro": "Падзяліцеся гэтым светам за кодам запрашэння: ён адкрываецца ў лакальнай сеткі, і сябры ў Інтэрнэце далучаюцца з кодам. Наш сервер не задзейнічаны.",
"horizon.friends.start_sharing": "Пачніце абагульваць",
"horizon.friends.troubleshooting": "Ліквідацыя непаладак...",
"horizon.friends.stopped": "Абагульванне кода запрашэння спынена.",
"horizon.friends.short_code_changed": "Хтосьці спрабаваў увесці няправільны кароткі код, таму ён змяніўся.",
"horizon.friends.wrong_code": "Хтосьці паспрабаваў увесці няправільны код.",
"horizon.friends.relay_stopped": "Занадта шмат няправільных кароткіх кодаў, таму рэле выключана, пакуль вы не падзеліцеся зноў. Сябры ўсё яшчэ могуць далучыцца з поўным кодам.",
"horizon.friends.code_ready": "Ваш код запрашэння гатовы: меню гульні, гульня з сябрамі. Скапіруйце яго і адпраўце сваім сябрам.",
"horizon.friends.share_failed": "Не атрымалася падзяліцца светам: %s",
"horizon.friends.finding_route": "Пошук, як сябры могуць звязацца з вамі...",
"horizon.osk.shift": "зрух",
"horizon.osk.space": "космас",
"horizon.osk.delete": "Выдаліць",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Рестартирайте играта, за да приложите %s: те добавят блокове, предмети или генериране на света.",
"horizon.shader_options.profile": "Профил",
"horizon.agent.copy_details": "Копиране на подробности за връзката",
"horizon.multiplayer.join": "Присъединете се",
"horizon.multiplayer.cancel_reconnecting": "Отказ Повторно свързване",
"horizon.multiplayer.join_friend": "Присъединете се към приятел",
"horizon.multiplayer.invite_code": "Код за покана",
"horizon.multiplayer.relay": "Реле (по избор)",
"Preset": "Предварителна настройка",
"LOD Distance": "LOD разстояние",
"Far Detail": "Далечен детайл",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профилите принадлежат към този екземпляр",
"horizon.splitscreen.profiles.move": "Движете се там, където играете",
"horizon.splitscreen.profiles.move_place": "Преместете се там, където играете: %s",
"horizon.friends.title": "Играйте с приятели",
"horizon.friends.hint": "Приятели поставете кода след бутона Приятели на заглавния екран, в Direct Connection или на страницата за възпроизвеждане на стартовия панел.",
"horizon.friends.copied": "Копирано",
"horizon.friends.copy_code": "Копиране на код",
"horizon.friends.stop_sharing": "Спиране на споделянето",
"horizon.friends.none_yet": "Тук все още няма приятели.",
"horizon.friends.here_now": "Тук сега: %s",
"horizon.friends.share_intro": "Споделете този свят зад код за покана: той се отваря към LAN и приятели в интернет се присъединяват с кода. Не е включен наш сървър.",
"horizon.friends.start_sharing": "Започнете споделяне",
"horizon.friends.troubleshooting": "Отстраняване на неизправности...",
"horizon.friends.stopped": "Спря споделянето на кода за покана.",
"horizon.friends.short_code_changed": "Някой продължаваше да опитва грешен кратък код, така че той се промени.",
"horizon.friends.wrong_code": "Някой е опитал грешен код.",
"horizon.friends.relay_stopped": "Твърде много грешни кратки кодове, затова релето е изключено, докато не споделите отново. Приятелите все още могат да се присъединят с пълния код.",
"horizon.friends.code_ready": "Вашият код за покана е готов: Меню за игри, Играйте с приятели. Копирайте го и го изпратете на приятелите си.",
"horizon.friends.share_failed": "Не можах да споделя света: %s",
"horizon.friends.finding_route": "Търся как приятелите могат да се свържат с вас...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "пространство",
"horizon.osk.delete": "Изтриване",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Adloc'hit ar c'hoari evit arloañ %s : ouzhpennañ a reont bloc'hoù, elfennoù pe krouidigezh bed.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Eilañ munudoù ar c'hennask",
"horizon.multiplayer.join": "Kemer perzh",
"horizon.multiplayer.cancel_reconnecting": "Nullañ an adkennaskañ",
"horizon.multiplayer.join_friend": "Kemer perzh en ur mignon",
"horizon.multiplayer.invite_code": "Kod pediñ",
"horizon.multiplayer.relay": "Treuzkas (dibar)",
"Preset": "Raktreset",
"LOD Distance": "Pellder LOD",
"Far Detail": "Munudoù pell",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Ar profiloù ezlinenn a ya d'ober an ensavadur-mañ",
"horizon.splitscreen.profiles.move": "Dilec'hiañ el lec'h ma c'hoarier",
"horizon.splitscreen.profiles.move_place": "Dilec'hiañ el lec'h ma c'hoarier : %s",
"horizon.friends.title": "C'hoari gant mignoned",
"horizon.friends.hint": "Pegañ a ra ar vignoned ar c'hod goude bouton Mignoned ar skramm titl, e Kevreadur war-eeun, pe war bajenn C'hoari al lañser.",
"horizon.friends.copied": "Eilet",
"horizon.friends.copy_code": "Eilañ ar c'hod",
"horizon.friends.stop_sharing": "Paouez da rannañ",
"horizon.friends.none_yet": "Mignon ebet amañ c'hoazh.",
"horizon.friends.here_now": "Setu bremañ : %s",
"horizon.friends.share_intro": "Rannañ ar bed-mañ a-dreñv ur c'hod pediñ : digeriñ a ra d'ar LAN, ha mignoned war internet a gemer perzh gant ar c'hod. N'eus servijer ebet ac'hanomp e-barzh.",
"horizon.friends.start_sharing": "Kregiñ da rannañ",
"horizon.friends.troubleshooting": "Diskoulmañ kudennoù...",
"horizon.friends.stopped": "Paouezet da rannañ ar c'hod pediñ.",
"horizon.friends.short_code_changed": "Unan bennak a gendalc'has da glask ur c'hod berr fazius, setu m'eo cheñchet.",
"horizon.friends.wrong_code": "Unan bennak en deus klasket ur c'hod fall.",
"horizon.friends.relay_stopped": "Re a godoù berr fazius, setu m'eo diweredekaet an treuzkas betek ma rannit en-dro. Ar vignoned a c'hall c'hoazh mont e-barzh gant ar c'hod klok.",
"horizon.friends.code_ready": "Prest eo ho kod pediñ : Menü ar c'hoari, C'hoari gant mignoned. Eilañ anezhañ ha kas anezhañ d'ho mignoned.",
"horizon.friends.share_failed": "N'hall ket rannañ ar bed : %s",
"horizon.friends.finding_route": "Kavout penaos e c'hall mignoned tizhout ac'hanoc'h...",
"horizon.osk.shift": "Dilec'hiañ",
"horizon.osk.space": "Egor",
"horizon.osk.delete": "Dilemel",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Restartujte igru da primijenite %s: dodaju blokove, predmete ili generisanje svijeta.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopiraj detalje veze",
"horizon.multiplayer.join": "Pridružite se",
"horizon.multiplayer.cancel_reconnecting": "Otkaži ponovno povezivanje",
"horizon.multiplayer.join_friend": "Pridružite se prijatelju",
"horizon.multiplayer.invite_code": "Pozivni kod",
"horizon.multiplayer.relay": "Relej (opciono)",
"Preset": "Predložak",
"LOD Distance": "LOD Udaljenost",
"Far Detail": "Daleki detalj",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profili pripadaju ovoj instanci",
"horizon.splitscreen.profiles.move": "Krećite se tamo gdje igrate",
"horizon.splitscreen.profiles.move_place": "Premjestite se gdje igrate: %s",
"horizon.friends.title": "Igrajte se s prijateljima",
"horizon.friends.hint": "Prijatelji zalijepe kod iza dugmeta Prijatelji na naslovnom ekranu, u Direktnu vezu ili na Play stranicu pokretača.",
"horizon.friends.copied": "Kopirano",
"horizon.friends.copy_code": "Kopiraj kod",
"horizon.friends.stop_sharing": "Prekini dijeljenje",
"horizon.friends.none_yet": "Ovdje još nema prijatelja.",
"horizon.friends.here_now": "Evo sada: %s",
"horizon.friends.share_intro": "Podijelite ovaj svijet iza pozivnog koda: otvara se na LAN, a prijatelji na internetu se pridružuju kodu. Nijedan naš server nije uključen.",
"horizon.friends.start_sharing": "Počnite dijeliti",
"horizon.friends.troubleshooting": "Rješavanje problema...",
"horizon.friends.stopped": "Zaustavljeno je dijeljenje pozivnog koda.",
"horizon.friends.short_code_changed": "Neko je nastavio pokušavati s pogrešnim kratkim kodom, pa se to promijenilo.",
"horizon.friends.wrong_code": "Neko je probao pogrešan kod.",
"horizon.friends.relay_stopped": "Previše pogrešnih kratkih kodova, pa je relej isključen dok ponovo ne podijelite. Prijatelji se još mogu pridružiti s punim kodom.",
"horizon.friends.code_ready": "Vaš pozivni kod je spreman: Meni igre, Igrajte se sa prijateljima. Kopirajte ga i pošaljite svojim prijateljima.",
"horizon.friends.share_failed": "Ne mogu dijeliti svijet: %s",
"horizon.friends.finding_route": "Pronalaženje načina na koji prijatelji mogu doći do vas…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Razmak",
"horizon.osk.delete": "Izbriši",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinicia el joc per aplicar-hi %s: afegeixen blocs, objectes o generació del món.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copia els detalls de la connexió",
"horizon.multiplayer.join": "Uneix-te",
"horizon.multiplayer.cancel_reconnecting": "Cancel·la la tornada a connectar",
"horizon.multiplayer.join_friend": "Uneix-te a un amic",
"horizon.multiplayer.invite_code": "Codi d'invitació",
"horizon.multiplayer.relay": "Relé (opcional)",
"Preset": "Preestablert",
"LOD Distance": "Distància LOD",
"Far Detail": "Detall llunyà",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Els perfils fora de línia pertanyen a aquesta instància",
"horizon.splitscreen.profiles.move": "Mou-te on jugues",
"horizon.splitscreen.profiles.move_place": "Mou on jugues: %s",
"horizon.friends.title": "Juga amb els amics",
"horizon.friends.hint": "Els amics enganxen el codi després del botó Amics de la pantalla del títol, a la connexió directa o a la pàgina de reproducció del llançador.",
"horizon.friends.copied": "Copiat",
"horizon.friends.copy_code": "Copia el codi",
"horizon.friends.stop_sharing": "Deixa de compartir",
"horizon.friends.none_yet": "Encara no hi ha amics.",
"horizon.friends.here_now": "Aquí ara: %s",
"horizon.friends.share_intro": "Comparteix aquest món darrere d'un codi d'invitació: s'obre a LAN i els amics d'Internet s'uneixen amb el codi. Cap servidor nostre està implicat.",
"horizon.friends.start_sharing": "Comenceu a compartir",
"horizon.friends.troubleshooting": "Resolució de problemes...",
"horizon.friends.stopped": "S'ha deixat de compartir el codi d'invitació.",
"horizon.friends.short_code_changed": "Algú va seguir provant un codi curt equivocat, així que va canviar.",
"horizon.friends.wrong_code": "Algú ha provat un codi incorrecte.",
"horizon.friends.relay_stopped": "Massa codis curts incorrectes, així que el relé està aturat fins que tornis a compartir. Els amics encara s'hi poden unir amb el codi complet.",
"horizon.friends.code_ready": "El teu codi d'invitació està preparat: Menú de joc, Juga amb els amics. Copia'l i envia'l als teus amics.",
"horizon.friends.share_failed": "No s'ha pogut compartir el món: %s",
"horizon.friends.finding_route": "Trobar com els amics et poden arribar...",
"horizon.osk.shift": "Canvi",
"horizon.osk.space": "Espai",
"horizon.osk.delete": "Suprimeix",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Restartujte hru, aby se %s projevilo: přidává bloky, předměty nebo generování světa.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopírovat podrobnosti o připojení",
"horizon.multiplayer.join": "Připojte se",
"horizon.multiplayer.cancel_reconnecting": "Zrušit opětovné připojení",
"horizon.multiplayer.join_friend": "Přidejte se k příteli",
"horizon.multiplayer.invite_code": "Kód pozvánky",
"horizon.multiplayer.relay": "relé (volitelné)",
"Preset": "Přednastaveno",
"LOD Distance": "LOD Vzdálenost",
"Far Detail": "Daleký detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profily patří k této instanci",
"horizon.splitscreen.profiles.move": "Pohybujte se tam, kde hrajete",
"horizon.splitscreen.profiles.move_place": "Přesuňte se, kde hrajete: %s",
"horizon.friends.title": "Hrajte s přáteli",
"horizon.friends.hint": "Přátelé vloží kód za tlačítko Přátelé na titulní obrazovce, do Přímého připojení nebo na stránku Play spouštěče.",
"horizon.friends.copied": "Zkopírováno",
"horizon.friends.copy_code": "Kopírovat kód",
"horizon.friends.stop_sharing": "Přestat sdílet",
"horizon.friends.none_yet": "Zatím tu nejsou žádní přátelé.",
"horizon.friends.here_now": "Tady teď: %s",
"horizon.friends.share_intro": "Sdílejte tento svět pomocí zvacího kódu: otevře se na LAN a přátelé na internetu se připojí pomocí kódu. Není zapojen žádný náš server.",
"horizon.friends.start_sharing": "Začněte sdílet",
"horizon.friends.troubleshooting": "Odstraňování problémů...",
"horizon.friends.stopped": "Sdílení kódu pozvánky bylo zastaveno.",
"horizon.friends.short_code_changed": "Někdo neustále zkoušel špatný krátký kód, takže se to změnilo.",
"horizon.friends.wrong_code": "Někdo zkusil špatný kód.",
"horizon.friends.relay_stopped": "Příliš mnoho špatných krátkých kódů, takže relé je vypnuté, dokud nebudete sdílet znovu. Přátelé se stále mohou připojit s plným kódem.",
"horizon.friends.code_ready": "Váš zvací kód je připraven: Herní menu, Hrajte s přáteli. Zkopírujte jej a pošlete svým přátelům.",
"horizon.friends.share_failed": "Nepodařilo se sdílet svět: %s",
"horizon.friends.finding_route": "Zjištění, jak vás mohou přátelé kontaktovat…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Prostor",
"horizon.osk.delete": "Smazat",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s ӗҫлеттерес тесен вӑйӑна ҫӗнӗрен пуҫлӑр: вӗсем блоксем, япаласем е тӗнче генерацийӗ хушса параҫҫӗ.",
"horizon.shader_options.profile": "Профиль",
"horizon.agent.copy_details": "Ҫыхӑну даннӑйӗсене копилесе илӗр",
"horizon.multiplayer.join": "Пӗрлешӗр",
"horizon.multiplayer.cancel_reconnecting": "Ҫӗнӗрен ҫыхӑнассине пӑрахӑҫла",
"horizon.multiplayer.join_friend": "Тус ҫумне хутшӑн",
"horizon.multiplayer.invite_code": "Йыхрав кодӗ",
"horizon.multiplayer.relay": "Реле (опционально)",
"Preset": "Малтанах лартнӑ",
"LOD Distance": "LOD дистанцийӗ",
"Far Detail": "Инҫетри вак-тӗвек",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профильсем ҫак экземпляра кӗреҫҫӗ",
"horizon.splitscreen.profiles.move": "Ӑҫта вылятӑн, ҫавӑнта куҫ",
"horizon.splitscreen.profiles.move_place": "Ӑҫта вылятӑн, ҫавӑнта куҫ: %s",
"horizon.friends.title": "Юлташсемпе выля",
"horizon.friends.hint": "Туссем ҫак кода титул экранӗнчи Туссем кнопки хыҫҫӑн, Тӳрӗ ҫыхӑнура е пуҫлаканӑн Play страницинче ҫыпӑҫтараҫҫӗ.",
"horizon.friends.copied": "Копиленӗ",
"horizon.friends.copy_code": "Код копийӗ",
"horizon.friends.stop_sharing": "Пайлама пӑрахӑр",
"horizon.friends.none_yet": "Кунта туссем ҫук-ха.",
"horizon.friends.here_now": "Акӑ халӗ: %s",
"horizon.friends.share_intro": "Ҫак тӗнчене йыхрав кодӗ хыҫӗнче пайла: вӑл LAN-а уҫӑлать, интернетри туссем вара ҫав кодпа хутшӑнаҫҫӗ. Пирӗн пӗр сервер та ҫак ӗҫе хутшӑнмасть.",
"horizon.friends.start_sharing": "Пайлама пуҫлӑр",
"horizon.friends.troubleshooting": "Ҫитменлӗхсене пӗтересси...",
"horizon.friends.stopped": "Чӗнӳ кодне пайлама пӑрахрӑм.",
"horizon.friends.short_code_changed": "Такам кӗске кода йӑнӑш ҫырса пӑхрӗ, ҫавӑнпа вӑл улшӑнчӗ.",
"horizon.friends.wrong_code": "Такам йӑнӑш кодпа усӑ курса пӑхнӑ.",
"horizon.friends.relay_stopped": "Ытла нумай тӗрӗс мар кӗске код, ҫавӑнпа реле эсир тепӗр хут пайласан ҫеҫ ӗҫлӗ. Тусем тулли кодпа кӗме пултараҫҫӗ.",
"horizon.friends.code_ready": "Сирӗн чӗнӳ кодӗ хатӗр: Вӑйӑ меню, Туссемпе выля. Ӑна копилесе юлташсене ярса парӑр.",
"horizon.friends.share_failed": "Тӗнчене пайлаймарӑм: %s",
"horizon.friends.finding_route": "Юлташсем сирӗн пата мӗнле ҫитме пултарнине тупасси...",
"horizon.osk.shift": "Смена",
"horizon.osk.space": "Космос",
"horizon.osk.delete": "Пӗтер",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Ailgychwynnwch y gêm i gymhwyso %s: maent yn ychwanegu blociau, eitemau neu gynhyrchu bydoedd.",
"horizon.shader_options.profile": "Proffil",
"horizon.agent.copy_details": "Copïo Manylion Cysylltiad",
"horizon.multiplayer.join": "Ymuno",
"horizon.multiplayer.cancel_reconnecting": "Canslo Ailgysylltu",
"horizon.multiplayer.join_friend": "Ymunwch â Ffrind",
"horizon.multiplayer.invite_code": "Cod Gwahodd",
"horizon.multiplayer.relay": "Cyfnewid (dewisol)",
"Preset": "Rhagosodedig",
"LOD Distance": "Pellter LOD",
"Far Detail": "Manylyn Pell",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Mae proffiliau all-lein yn perthyn i'r achos hwn",
"horizon.splitscreen.profiles.move": "Symudwch lle rydych chi'n chwarae",
"horizon.splitscreen.profiles.move_place": "Symudwch ble rydych chi'n chwarae: %s",
"horizon.friends.title": "Chwarae gyda Ffrindiau",
"horizon.friends.hint": "Mae ffrindiau'n gludo'r cod ar ôl botwm Friends y sgrin deitl, yn Direct Connection, neu ar dudalen Chwarae'r lansiwr.",
"horizon.friends.copied": "Wedi'i gopïo",
"horizon.friends.copy_code": "Copi Cod",
"horizon.friends.stop_sharing": "Stopio Rhannu",
"horizon.friends.none_yet": "Dim ffrindiau yma eto.",
"horizon.friends.here_now": "Yma nawr: %s",
"horizon.friends.share_intro": "Rhannwch y byd hwn y tu ôl i god gwahoddiad: mae'n agor i LAN, ac mae ffrindiau ar y rhyngrwyd yn ymuno â'r cod. Nid oes unrhyw weinydd ohonom yn cymryd rhan.",
"horizon.friends.start_sharing": "Dechrau Rhannu",
"horizon.friends.troubleshooting": "Datrys Problemau...",
"horizon.friends.stopped": "Wedi stopio rhannu'r cod gwahoddiad.",
"horizon.friends.short_code_changed": "Roedd rhywun yn ceisio cod byr anghywir o hyd, felly fe newidiodd.",
"horizon.friends.wrong_code": "Ceisiodd rhywun god anghywir.",
"horizon.friends.relay_stopped": "Gormod o godau byr anghywir, felly mae'r cyfnewidydd i ffwrdd nes i chi rannu eto. Gall ffrindiau ymuno o hyd â'r cod llawn.",
"horizon.friends.code_ready": "Mae eich cod gwahoddiad yn barod: Dewislen Gêm, Chwarae gyda Ffrindiau. Copïwch ef a'i anfon at eich ffrindiau.",
"horizon.friends.share_failed": "Methu rhannu'r byd: %s",
"horizon.friends.finding_route": "Darganfod sut y gall ffrindiau eich cyrraedd…",
"horizon.osk.shift": "Turn",
"horizon.osk.space": "Gofod",
"horizon.osk.delete": "Dileu",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Genstart spillet for at anvende %s: de tilføjer blokke, genstande eller verdensgenerering.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopier forbindelsesoplysninger",
"horizon.multiplayer.join": "Deltag",
"horizon.multiplayer.cancel_reconnecting": "Annuller Gentilslutning",
"horizon.multiplayer.join_friend": "Slut dig til en ven",
"horizon.multiplayer.invite_code": "Invitationskode",
"horizon.multiplayer.relay": "Relæ (valgfrit)",
"Preset": "Forudindstillet",
"LOD Distance": "LOD Afstand",
"Far Detail": "Fjern detalje",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offlineprofiler hører til denne instans",
"horizon.splitscreen.profiles.move": "Flyt hvor du spiller",
"horizon.splitscreen.profiles.move_place": "Flyt hvor du spiller: %s",
"horizon.friends.title": "Spil med venner",
"horizon.friends.hint": "Venner indsætter koden efter titelskærmens Venner-knap, i Direct Connection eller på launcherens Play-side.",
"horizon.friends.copied": "Kopieret",
"horizon.friends.copy_code": "Kopiér kode",
"horizon.friends.stop_sharing": "Stop deling",
"horizon.friends.none_yet": "Ingen venner her endnu.",
"horizon.friends.here_now": "Her nu: %s",
"horizon.friends.share_intro": "Del denne verden bag en invitationskode: den åbner til LAN, og venner på internettet deltager med koden. Ingen af vores servere er involveret.",
"horizon.friends.start_sharing": "Begynd at dele",
"horizon.friends.troubleshooting": "Fejlfinding...",
"horizon.friends.stopped": "Stoppet med at dele invitationskoden.",
"horizon.friends.short_code_changed": "Nogen blev ved med at prøve en forkert kort kode, så den ændrede sig.",
"horizon.friends.wrong_code": "Nogen prøvede en forkert kode.",
"horizon.friends.relay_stopped": "For mange forkerte kortkoder, så relæet er slået fra, indtil du deler igen. Venner kan stadig deltage med den fulde kode.",
"horizon.friends.code_ready": "Din invitationskode er klar: Spilmenu, Spil med venner. Kopier det og send det til dine venner.",
"horizon.friends.share_failed": "Kunne ikke dele verden: %s",
"horizon.friends.finding_route": "Finder, hvordan venner kan nå dig...",
"horizon.osk.shift": "Skift",
"horizon.osk.space": "Plads",
"horizon.osk.delete": "Slet",
@@ -209,7 +209,11 @@
"horizon.mods.switch.restart": "Starte das Spiel neu, um %s anzuwenden: Sie fügen Blöcke, Gegenstände oder Weltgenerierung hinzu.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Verbindungsdaten kopieren",
"horizon.multiplayer.join": "Beitreten",
"horizon.multiplayer.cancel_reconnecting": "Neuverbindung abbrechen",
"horizon.multiplayer.join_friend": "Freund beitreten",
"horizon.multiplayer.invite_code": "Einladungscode",
"horizon.multiplayer.relay": "Relay (optional)",
"Preset": "Preset",
"LOD Distance": "LOD-Weite",
"Far Detail": "Ferndetails",
@@ -319,6 +323,7 @@
"horizon.extras.wheel_cycles_settings": "Mausrad ändert Einstellungen",
"horizon.extras.pack_browser": "Ressourcenpaket-Browser",
"horizon.extras.music_page.tooltip": "Musik & Geräusche erhält eine Seite „Musik …“: Spiele jeden eingebauten Titel jetzt ab oder schalte einen aus, damit das Spiel ihn nicht mehr wählt. Nichts ändert sich, bis du einen Titel ausschaltest.",
"horizon.friends.relay_stopped": "Zu viele falsche Kurzcodes, deshalb ist das Relay aus, bis du erneut teilst. Freunde können weiterhin mit dem vollständigen Code beitreten.",
"horizon.extras.pack_browser.tooltip": "Ressourcenpakete auswählen erhält eine Schaltfläche „Hinzufügen“, die Modrinth durchsucht und ein Paket in deinen Paketordner installiert. Aus kontaktiert das Spiel Modrinth nie.",
"horizon.splitscreen.setup.monitor": "Monitor %s",
"horizon.splitscreen.setup.monitor_unknown": "ein Monitor",
@@ -538,6 +543,22 @@
"horizon.splitscreen.profiles.offline_note": "Offline-Profile gehören zu dieser Instanz",
"horizon.splitscreen.profiles.move": "Spielort wechseln",
"horizon.splitscreen.profiles.move_place": "Spielort wechseln: %s",
"horizon.friends.title": "Mit Freunden spielen",
"horizon.friends.hint": "Freunde fügen den Code nach dem Freunde-Knopf des Titelbildschirms ein, bei „Direktverbindung“ oder auf der Spielen-Seite des Launchers.",
"horizon.friends.copied": "Kopiert",
"horizon.friends.copy_code": "Code kopieren",
"horizon.friends.stop_sharing": "Teilen beenden",
"horizon.friends.none_yet": "Noch keine Freunde hier.",
"horizon.friends.here_now": "Gerade hier: %s",
"horizon.friends.share_intro": "Teile diese Welt mit einem Einladungscode: Sie wird im LAN geöffnet, und Freunde im Internet treten mit dem Code bei. Es ist kein Server von uns beteiligt.",
"horizon.friends.start_sharing": "Teilen starten",
"horizon.friends.troubleshooting": "Fehlerbehebung …",
"horizon.friends.stopped": "Das Teilen des Einladungscodes wurde beendet.",
"horizon.friends.short_code_changed": "Jemand hat immer wieder einen falschen Kurzcode versucht, deshalb wurde er geändert.",
"horizon.friends.wrong_code": "Jemand hat einen falschen Code versucht.",
"horizon.friends.code_ready": "Dein Einladungscode ist bereit: Spielmenü, Mit Freunden spielen. Kopiere ihn und schicke ihn an deine Freunde.",
"horizon.friends.share_failed": "Die Welt konnte nicht geteilt werden: %s",
"horizon.friends.finding_route": "Es wird ermittelt, wie Freunde dich erreichen können …",
"horizon.osk.shift": "Umschalt",
"horizon.osk.space": "Leertaste",
"horizon.osk.delete": "Löschen",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Επανεκκινήστε το παιχνίδι για να εφαρμόσετε το %s: προσθέτουν μπλοκ, αντικείμενα ή παραγωγή κόσμου.",
"horizon.shader_options.profile": "Προφίλ",
"horizon.agent.copy_details": "Αντιγραφή στοιχείων σύνδεσης",
"horizon.multiplayer.join": "Εγγραφείτε",
"horizon.multiplayer.cancel_reconnecting": "Ακύρωση επανασύνδεσης",
"horizon.multiplayer.join_friend": "Γίνετε μέλος ενός φίλου",
"horizon.multiplayer.invite_code": "Κωδικός πρόσκλησης",
"horizon.multiplayer.relay": "Ρελέ (προαιρετικό)",
"Preset": "Προκαθορισμένη",
"LOD Distance": "Απόσταση LOD",
"Far Detail": "Μακρινή λεπτομέρεια",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Τα προφίλ εκτός σύνδεσης ανήκουν σε αυτήν την περίπτωση",
"horizon.splitscreen.profiles.move": "Μετακινηθείτε όπου παίζετε",
"horizon.splitscreen.profiles.move_place": "Μετακινηθείτε όπου παίζετε: %s",
"horizon.friends.title": "Παίξτε με φίλους",
"horizon.friends.hint": "Οι φίλοι επικολλούν τον κώδικα μετά το κουμπί Φίλοι της οθόνης τίτλου, στην Άμεση σύνδεση ή στη σελίδα Αναπαραγωγή του προγράμματος εκκίνησης.",
"horizon.friends.copied": "Αντιγράφηκε",
"horizon.friends.copy_code": "Αντιγραφή Κωδικού",
"horizon.friends.stop_sharing": "Διακοπή κοινής χρήσης",
"horizon.friends.none_yet": "Δεν υπάρχουν φίλοι εδώ ακόμα.",
"horizon.friends.here_now": "Εδώ τώρα: %s",
"horizon.friends.share_intro": "Μοιραστείτε αυτόν τον κόσμο πίσω από έναν κωδικό πρόσκλησης: ανοίγει σε LAN και οι φίλοι στο Διαδίκτυο συμμετέχουν με τον κωδικό. Κανένας διακομιστής μας δεν εμπλέκεται.",
"horizon.friends.start_sharing": "Ξεκινήστε την κοινή χρήση",
"horizon.friends.troubleshooting": "Αντιμετώπιση προβλημάτων...",
"horizon.friends.stopped": "Σταμάτησε η κοινή χρήση του κωδικού πρόσκλησης.",
"horizon.friends.short_code_changed": "Κάποιος συνέχισε να δοκιμάζει έναν λάθος σύντομο κωδικό, οπότε άλλαξε.",
"horizon.friends.wrong_code": "Κάποιος δοκίμασε λάθος κωδικό.",
"horizon.friends.relay_stopped": "Πολλοί λάθος σύντομοι κωδικοί, οπότε το ρελέ είναι κλειστό μέχρι να μοιραστείτε ξανά. Οι φίλοι μπορούν ακόμη να συνδεθούν με τον πλήρη κωδικό.",
"horizon.friends.code_ready": "Ο κωδικός πρόσκλησής σας είναι έτοιμος: Μενού παιχνιδιού, Παίξτε με φίλους. Αντιγράψτε το και στείλτε το στους φίλους σας.",
"horizon.friends.share_failed": "Δεν μπορούσα να μοιραστώ τον κόσμο: %s",
"horizon.friends.finding_route": "Βρείτε πώς μπορούν να σας φτάσουν οι φίλοι…",
"horizon.osk.shift": "Μετατόπιση",
"horizon.osk.space": "Διάστημα",
"horizon.osk.delete": "Διαγραφή",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Restart the game to apply %s: they add blocks, items or world generation.",
"horizon.shader_options.profile": "Profile",
"horizon.agent.copy_details": "Copy Connection Details",
"horizon.multiplayer.join": "Join",
"horizon.multiplayer.cancel_reconnecting": "Cancel Reconnecting",
"horizon.multiplayer.join_friend": "Join a Friend",
"horizon.multiplayer.invite_code": "Invite Code",
"horizon.multiplayer.relay": "Relay (optional)",
"Preset": "Preset",
"LOD Distance": "LOD Distance",
"Far Detail": "Far Detail",
@@ -283,6 +287,7 @@
"This feature is not yet available in Horizon.": "This feature is not yet available in Horizon.",
"Your display or system doesn't offer HDR output.": "Your display or system doesn't offer HDR output.",
"Turn HDR on to use it.": "Turn HDR on to use it.",
"The shader pack lights the world itself.": "The shader pack lights the world itself.",
"Your GPU or graphics API doesn't support it.": "Your GPU or graphics API doesn't support it.",
"Not with software rendering, which runs it on the CPU.": "Not with software rendering, which runs it on the CPU.",
"Out of video memory: off until the next start.": "Out of video memory: off until the next start.",
@@ -461,6 +466,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profiles belong to this instance",
"horizon.splitscreen.profiles.move": "Move where you play",
"horizon.splitscreen.profiles.move_place": "Move where you play: %s",
"horizon.friends.title": "Play with Friends",
"horizon.friends.hint": "Friends paste the code after the title screen's Friends button, in Direct Connection, or on the launcher's Play page.",
"horizon.friends.copied": "Copied",
"horizon.friends.copy_code": "Copy Code",
"horizon.friends.stop_sharing": "Stop Sharing",
"horizon.friends.none_yet": "No friends here yet.",
"horizon.friends.here_now": "Here now: %s",
"horizon.friends.share_intro": "Share this world behind an invite code: it opens to LAN, and friends on the internet join with the code. No server of ours is involved.",
"horizon.friends.start_sharing": "Start Sharing",
"horizon.friends.troubleshooting": "Troubleshooting...",
"horizon.friends.stopped": "Stopped sharing the invite code.",
"horizon.friends.short_code_changed": "Someone kept trying a wrong short code, so it changed.",
"horizon.friends.wrong_code": "Someone tried a wrong code.",
"horizon.friends.relay_stopped": "Too many wrong short codes, so the relay is off until you share again. Friends can still join with the full code.",
"horizon.friends.code_ready": "Your invite code is ready: Game Menu, Play with Friends. Copy it and send it to your friends.",
"horizon.friends.share_failed": "Couldn't share the world: %s",
"horizon.friends.finding_route": "Finding how friends can reach you…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Space",
"horizon.osk.delete": "Delete",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Restartigu la ludon por apliki %s: ili aldonas blokojn, objektojn aŭ mondgeneradon.",
"horizon.shader_options.profile": "Profilo",
"horizon.agent.copy_details": "Kopiu Detalojn pri Konekto",
"horizon.multiplayer.join": "Aliĝu",
"horizon.multiplayer.cancel_reconnecting": "Nuligi Rekonekti",
"horizon.multiplayer.join_friend": "Aliĝu al Amiko",
"horizon.multiplayer.invite_code": "Inviti Kodon",
"horizon.multiplayer.relay": "Relajso (laŭvola)",
"Preset": "Antaŭdifinita",
"LOD Distance": "LOD Distanco",
"Far Detail": "Malproksima Detalo",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Senretaj profiloj apartenas al ĉi tiu kazo",
"horizon.splitscreen.profiles.move": "Movu kien vi ludas",
"horizon.splitscreen.profiles.move_place": "Movu kien vi ludas: %s",
"horizon.friends.title": "Ludu kun Amikoj",
"horizon.friends.hint": "Amikoj algluas la kodon post la butono Amikoj de la titolekrano, en Rekta Konekto aŭ sur la Luda paĝo de la lanĉilo.",
"horizon.friends.copied": "Kopiita",
"horizon.friends.copy_code": "Kopiu Kodon",
"horizon.friends.stop_sharing": "Ĉesu Kundividon",
"horizon.friends.none_yet": "Ankoraŭ neniuj amikoj ĉi tie.",
"horizon.friends.here_now": "Ĉi tie nun: %s",
"horizon.friends.share_intro": "Kunhavigu ĉi tiun mondon malantaŭ invitkodo: ĝi malfermiĝas al LAN, kaj amikoj en la interreto aliĝas kun la kodo. Neniu servilo nia estas implikita.",
"horizon.friends.start_sharing": "Komencu Kunhavigi",
"horizon.friends.troubleshooting": "Solvado de problemoj...",
"horizon.friends.stopped": "Ĉesis kunhavigi la invitkodon.",
"horizon.friends.short_code_changed": "Iu daŭre provis malĝustan mallongan kodon, do ĝi ŝanĝiĝis.",
"horizon.friends.wrong_code": "Iu provis malĝustan kodon.",
"horizon.friends.relay_stopped": "Tro da malĝustaj mallongaj kodoj, do la relajso estas malŝaltita ĝis vi denove kundividos. Amikoj ankoraŭ povas aliĝi per la plena kodo.",
"horizon.friends.code_ready": "Via invitkodo estas preta: Luda Menuo, Ludu kun Amikoj. Kopiu ĝin kaj sendu ĝin al viaj amikoj.",
"horizon.friends.share_failed": "Ne povis dividi la mondon: %s",
"horizon.friends.finding_route": "Trovi kiel amikoj povas atingi vin...",
"horizon.osk.shift": "Majusklo",
"horizon.osk.space": "Spaco",
"horizon.osk.delete": "Forigi",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinicia el juego para aplicar %s: añaden bloques, objetos o generación del mundo.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copiar datos de conexión",
"horizon.multiplayer.join": "Unirse",
"horizon.multiplayer.cancel_reconnecting": "Cancelar reconexión",
"horizon.multiplayer.join_friend": "Unirse a un amigo",
"horizon.multiplayer.invite_code": "Código de invitación",
"horizon.multiplayer.relay": "Relay (opcional)",
"Preset": "Preajuste",
"LOD Distance": "Distancia LOD",
"Far Detail": "Detalle lejano",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Los perfiles sin conexión pertenecen a esta instancia",
"horizon.splitscreen.profiles.move": "Mover dónde juegas",
"horizon.splitscreen.profiles.move_place": "Mover dónde juegas: %s",
"horizon.friends.title": "Jugar con amigos",
"horizon.friends.hint": "Tus amigos pegan el código tras el botón Amigos de la pantalla de título, en Conexión directa o en la página Jugar del launcher.",
"horizon.friends.copied": "Copiado",
"horizon.friends.copy_code": "Copiar código",
"horizon.friends.stop_sharing": "Dejar de compartir",
"horizon.friends.none_yet": "Aún no hay amigos aquí.",
"horizon.friends.here_now": "Aquí ahora: %s",
"horizon.friends.share_intro": "Comparte este mundo con un código de invitación: se abre a la LAN y tus amigos de internet se unen con el código. No interviene ningún servidor nuestro.",
"horizon.friends.start_sharing": "Empezar a compartir",
"horizon.friends.troubleshooting": "Solución de problemas...",
"horizon.friends.stopped": "Se ha dejado de compartir el código de invitación.",
"horizon.friends.short_code_changed": "Alguien intentó varias veces un código corto incorrecto, así que ha cambiado.",
"horizon.friends.wrong_code": "Alguien ha probado un código incorrecto.",
"horizon.friends.relay_stopped": "Demasiados códigos cortos incorrectos: el relé queda apagado hasta que vuelvas a compartir. Tus amigos aún pueden unirse con el código completo.",
"horizon.friends.code_ready": "Tu código de invitación está listo: Menú del juego, Jugar con amigos. Cópialo y envíaselo a tus amigos.",
"horizon.friends.share_failed": "No se pudo compartir el mundo: %s",
"horizon.friends.finding_route": "Buscando cómo pueden llegar tus amigos hasta ti…",
"horizon.osk.shift": "Mayús",
"horizon.osk.space": "Espacio",
"horizon.osk.delete": "Borrar",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Taaskäivita mäng, et rakendada %s: need lisavad plokke, esemeid või maailma genereerimist.",
"horizon.shader_options.profile": "Profiil",
"horizon.agent.copy_details": "Kopeerige ühenduse üksikasjad",
"horizon.multiplayer.join": "Liitu",
"horizon.multiplayer.cancel_reconnecting": "Tühista uuesti ühendamine",
"horizon.multiplayer.join_friend": "Liituge sõbraga",
"horizon.multiplayer.invite_code": "Kutsekood",
"horizon.multiplayer.relay": "Relee (valikuline)",
"Preset": "Eelseadistatud",
"LOD Distance": "LOD vahemaa",
"Far Detail": "Kauge detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Sellesse eksemplari kuuluvad võrguühenduseta profiilid",
"horizon.splitscreen.profiles.move": "Liikuge sinna, kus mängite",
"horizon.splitscreen.profiles.move_place": "Liikuge sinna, kus mängite: %s",
"horizon.friends.title": "Mängige sõpradega",
"horizon.friends.hint": "Sõbrad kleebivad koodi pealkirjaekraani nupu Sõbrad järele, otseühenduses või käivitusprogrammi Play lehel.",
"horizon.friends.copied": "Kopeeritud",
"horizon.friends.copy_code": "Kopeeri kood",
"horizon.friends.stop_sharing": "Lõpeta jagamine",
"horizon.friends.none_yet": "Siin pole veel sõpru.",
"horizon.friends.here_now": "Siin praegu: %s",
"horizon.friends.share_intro": "Jagage seda maailma kutsekoodi taga: see avaneb LAN-i ja Internetis olevad sõbrad liituvad koodiga. Ükski meie server ei ole sellega seotud.",
"horizon.friends.start_sharing": "Alusta jagamist",
"horizon.friends.troubleshooting": "Veaotsing...",
"horizon.friends.stopped": "Kutsekoodi jagamine lõpetati.",
"horizon.friends.short_code_changed": "Keegi proovis pidevalt valet lühikoodi, nii et see muutus.",
"horizon.friends.wrong_code": "Keegi proovis vale koodi.",
"horizon.friends.relay_stopped": "Liiga palju valesid lühikoode, seega relee on väljas, kuni uuesti jagad. Sõbrad saavad siiski täiskoodiga liituda.",
"horizon.friends.code_ready": "Teie kutsekood on valmis: Mängumenüü, Mängige sõpradega. Kopeerige see ja saatke see oma sõpradele.",
"horizon.friends.share_failed": "Ei saanud maailma jagada: %s",
"horizon.friends.finding_route": "Kuidas sõbrad teiega ühendust saavad…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Kosmos",
"horizon.osk.delete": "Kustuta",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Berrabiarazi jokoa %s aplikatzeko: blokeak, elementuak edo mundu-sorrera gehitzen dituzte.",
"horizon.shader_options.profile": "Profila",
"horizon.agent.copy_details": "Kopiatu konexioaren xehetasunak",
"horizon.multiplayer.join": "Sartu",
"horizon.multiplayer.cancel_reconnecting": "Utzi berriro konektatzea",
"horizon.multiplayer.join_friend": "Sartu Lagun batekin",
"horizon.multiplayer.invite_code": "Gonbidatu kodea",
"horizon.multiplayer.relay": "Erreleboa (aukerakoa)",
"Preset": "Aurrez ezarritakoa",
"LOD Distance": "LOD Distantzia",
"Far Detail": "Urruneko xehetasuna",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Lineaz kanpoko profilak instantzia honetakoak dira",
"horizon.splitscreen.profiles.move": "Mugitu jolasten duzun tokira",
"horizon.splitscreen.profiles.move_place": "Mugitu jolasten duzun tokira: %s",
"horizon.friends.title": "Jolastu Lagunekin",
"horizon.friends.hint": "Lagunek itsatsi dute kodea izenburu-pantailaren Lagunak botoian, Zuzeneko konexioan edo abiarazlearen Play orrian.",
"horizon.friends.copied": "Kopiatua",
"horizon.friends.copy_code": "Kopiatu kodea",
"horizon.friends.stop_sharing": "Utzi partekatzeari",
"horizon.friends.none_yet": "Hemen oraindik ez dago lagunik.",
"horizon.friends.here_now": "Hemen orain: %s",
"horizon.friends.share_intro": "Partekatu mundu hau gonbidapen-kode baten atzean: LANera irekitzen da eta Interneteko lagunak bat egiten dute kodearekin. Ez dago gure zerbitzaririk parte hartzen.",
"horizon.friends.start_sharing": "Hasi Partekatzen",
"horizon.friends.troubleshooting": "Arazoak konpontzen...",
"horizon.friends.stopped": "Gonbidapen kodea partekatzeari utzi dio.",
"horizon.friends.short_code_changed": "Norbaitek kode labur oker bat probatzen jarraitu zuen, beraz, aldatu egin zen.",
"horizon.friends.wrong_code": "Norbaitek kode oker batekin saiatu da.",
"horizon.friends.relay_stopped": "Kode labur oker gehiegi, beraz erreleboa itzalita dago berriro partekatu arte. Lagunek kode osoarekin sartzen jarrai dezakete.",
"horizon.friends.code_ready": "Zure gonbidapen-kodea prest dago: Jokoen menua, Jolastu lagunekin. Kopiatu eta bidali zure lagunei.",
"horizon.friends.share_failed": "Ezin izan da mundua partekatu: %s",
"horizon.friends.finding_route": "Lagunak zurekin nola irits daitezkeen aurkitzen...",
"horizon.osk.shift": "Txanda",
"horizon.osk.space": "Espazioa",
"horizon.osk.delete": "Ezabatu",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "برای اعمال %s بازی را دوباره راه‌اندازی کنید: آن‌ها بلوک، آیتم یا تولید دنیا می‌افزایند.",
"horizon.shader_options.profile": "نمایه",
"horizon.agent.copy_details": "کپی جزئیات اتصال",
"horizon.multiplayer.join": "بپیوندید",
"horizon.multiplayer.cancel_reconnecting": "لغو اتصال مجدد",
"horizon.multiplayer.join_friend": "به یک دوست بپیوندید",
"horizon.multiplayer.invite_code": "کد دعوت",
"horizon.multiplayer.relay": "رله (اختیاری)",
"Preset": "از پیش تعیین شده",
"LOD Distance": "فاصله LOD",
"Far Detail": "جزئیات دور",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "پروفایل های آفلاین متعلق به این نمونه است",
"horizon.splitscreen.profiles.move": "جایی که بازی می کنید حرکت کنید",
"horizon.splitscreen.profiles.move_place": "جایی را که بازی می کنید حرکت دهید: %s",
"horizon.friends.title": "با دوستان بازی کنید",
"horizon.friends.hint": "دوستان کد را بعد از دکمه Friends صفحه عنوان، در اتصال مستقیم یا در صفحه Play راه‌انداز قرار می‌دهند.",
"horizon.friends.copied": "کپی شده است",
"horizon.friends.copy_code": "کد را کپی کنید",
"horizon.friends.stop_sharing": "اشتراک گذاری را متوقف کنید",
"horizon.friends.none_yet": "هنوز دوستی اینجا نیست",
"horizon.friends.here_now": "اکنون اینجا: %s",
"horizon.friends.share_intro": "این دنیا را پشت یک کد دعوت به اشتراک بگذارید: به شبکه LAN باز می شود و دوستانی که در اینترنت هستند با این کد ملحق می شوند. هیچ سروری از ما درگیر نیست.",
"horizon.friends.start_sharing": "اشتراک گذاری را شروع کنید",
"horizon.friends.troubleshooting": "عیب یابی ...",
"horizon.friends.stopped": "اشتراک‌گذاری کد دعوت متوقف شد.",
"horizon.friends.short_code_changed": "کسی مدام یک کد کوتاه اشتباه را امتحان می‌کرد، بنابراین تغییر کرد.",
"horizon.friends.wrong_code": "شخصی کد اشتباهی را امتحان کرده است.",
"horizon.friends.relay_stopped": "کدهای کوتاه اشتباه بیش از حد بود، بنابراین رله تا اشتراک‌گذاری دوباره خاموش است. دوستان هنوز می‌توانند با کد کامل بپیوندند.",
"horizon.friends.code_ready": "کد دعوت شما آماده است: منوی بازی، بازی با دوستان. کپی کنید و برای دوستانتان ارسال کنید.",
"horizon.friends.share_failed": "نمی توان جهان را به اشتراک گذاشت: %s",
"horizon.friends.finding_route": "یافتن نحوه ارتباط دوستان با شما…",
"horizon.osk.shift": "شیفت",
"horizon.osk.space": "فضا",
"horizon.osk.delete": "حذف کنید",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Käynnistä peli uudelleen, jotta %s tulee voimaan: ne lisäävät lohkoja, esineitä tai maailmanluontia.",
"horizon.shader_options.profile": "Profiili",
"horizon.agent.copy_details": "Kopioi yhteystiedot",
"horizon.multiplayer.join": "Liity",
"horizon.multiplayer.cancel_reconnecting": "Peruuta yhteyden muodostaminen",
"horizon.multiplayer.join_friend": "Liity ystäväksi",
"horizon.multiplayer.invite_code": "Kutsukoodi",
"horizon.multiplayer.relay": "Rele (valinnainen)",
"Preset": "Esiasetus",
"LOD Distance": "LOD Etäisyys",
"Far Detail": "Kaukainen yksityiskohta",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline-profiilit kuuluvat tähän esiintymään",
"horizon.splitscreen.profiles.move": "Muuta missä pelaat",
"horizon.splitscreen.profiles.move_place": "Siirry paikkaan, jossa pelaat: %s",
"horizon.friends.title": "Pelaa ystävien kanssa",
"horizon.friends.hint": "Ystävät liittävät koodin otsikkonäytön Ystävät-painikkeen perään, Suoraan yhteyteen tai käynnistysohjelman Play-sivulle.",
"horizon.friends.copied": "Kopioitu",
"horizon.friends.copy_code": "Kopioi koodi",
"horizon.friends.stop_sharing": "Lopeta jakaminen",
"horizon.friends.none_yet": "Täällä ei ole vielä ystäviä.",
"horizon.friends.here_now": "Täällä nyt: %s",
"horizon.friends.share_intro": "Jaa tämä maailma kutsukoodin takana: se avautuu lähiverkkoon, ja ystävät Internetissä liittyvät koodin avulla. Yksikään palvelin ei ole mukana.",
"horizon.friends.start_sharing": "Aloita jakaminen",
"horizon.friends.troubleshooting": "Vianmääritys...",
"horizon.friends.stopped": "Kutsukoodin jakaminen lopetettiin.",
"horizon.friends.short_code_changed": "Joku yritti jatkuvasti käyttää väärää lyhytkoodia, joten se muuttui.",
"horizon.friends.wrong_code": "Joku yritti väärää koodia.",
"horizon.friends.relay_stopped": "Liian monta väärää lyhytkoodia, joten rele on pois päältä, kunnes jaat uudelleen. Ystävät voivat yhä liittyä täydellä koodilla.",
"horizon.friends.code_ready": "Kutsukoodisi on valmis: Pelivalikko, Pelaa ystävien kanssa. Kopioi se ja lähetä se ystävillesi.",
"horizon.friends.share_failed": "Ei voinut jakaa maailmaa: %s",
"horizon.friends.finding_route": "Selvitetään, kuinka ystävät voivat tavoittaa sinut…",
"horizon.osk.shift": "Vaihto",
"horizon.osk.space": "Avaruus",
"horizon.osk.delete": "Poista",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "I-restart ang laro para mailapat ang %s: nagdadagdag sila ng mga bloke, item o pagbuo ng mundo.",
"horizon.shader_options.profile": "Profile",
"horizon.agent.copy_details": "Kopyahin ang Mga Detalye ng Koneksyon",
"horizon.multiplayer.join": "Sumali",
"horizon.multiplayer.cancel_reconnecting": "Kanselahin ang Muling Pagkonekta",
"horizon.multiplayer.join_friend": "Sumali sa isang Kaibigan",
"horizon.multiplayer.invite_code": "Code ng Imbitasyon",
"horizon.multiplayer.relay": "Relay (opsyonal)",
"Preset": "Preset",
"LOD Distance": "LOD Distansya",
"Far Detail": "Malayong Detalye",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Ang mga offline na profile ay kabilang sa pagkakataong ito",
"horizon.splitscreen.profiles.move": "Lumipat kung saan ka naglalaro",
"horizon.splitscreen.profiles.move_place": "Ilipat kung saan ka naglalaro: %s",
"horizon.friends.title": "Makipaglaro sa Kaibigan",
"horizon.friends.hint": "I-paste ng mga kaibigan ang code pagkatapos ng button na Friends ng screen ng pamagat, sa Direktang Koneksyon, o sa Play page ng launcher.",
"horizon.friends.copied": "Kinopya",
"horizon.friends.copy_code": "Kopyahin ang Code",
"horizon.friends.stop_sharing": "Itigil ang Pagbabahagi",
"horizon.friends.none_yet": "Wala pang kaibigan dito.",
"horizon.friends.here_now": "Narito ngayon: %s",
"horizon.friends.share_intro": "Ibahagi ang mundong ito sa likod ng code ng imbitasyon: bumubukas ito sa LAN, at sumali ang mga kaibigan sa internet gamit ang code. Walang kasamang server namin.",
"horizon.friends.start_sharing": "Simulan ang Pagbabahagi",
"horizon.friends.troubleshooting": "Pag-troubleshoot...",
"horizon.friends.stopped": "Huminto sa pagbabahagi ng code ng imbitasyon.",
"horizon.friends.short_code_changed": "May sumubok ng maling maikling code, kaya nagbago ito.",
"horizon.friends.wrong_code": "May sumubok ng maling code.",
"horizon.friends.relay_stopped": "Napakaraming maling short code, kaya naka-off ang relay hanggang magbahagi ka muli. Nakakasali pa rin ang mga kaibigan gamit ang buong code.",
"horizon.friends.code_ready": "Handa na ang iyong code ng imbitasyon: Game Menu, Play with Friends. Kopyahin ito at ipadala sa iyong mga kaibigan.",
"horizon.friends.share_failed": "Hindi maibahagi ang mundo: %s",
"horizon.friends.finding_route": "Hinahanap kung paano ka maaabot ng mga kaibigan...",
"horizon.osk.shift": "Paglipat",
"horizon.osk.space": "kalawakan",
"horizon.osk.delete": "Tanggalin",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Endurbyrja spælið fyri at nýta %s: tey leggja afturat blokkar, lutir ella heimsframleiðslu.",
"horizon.shader_options.profile": "Vangamynd",
"horizon.agent.copy_details": "Avrita sambandsupplýsingar",
"horizon.multiplayer.join": "Ver við",
"horizon.multiplayer.cancel_reconnecting": "Avlýs aftursamband",
"horizon.multiplayer.join_friend": "Melda teg til ein vin",
"horizon.multiplayer.invite_code": "Boðkoda",
"horizon.multiplayer.relay": "Stafett (valfrítt)",
"Preset": "Forsett",
"LOD Distance": "LOD Fjarstøða",
"Far Detail": "Fjar Detalja",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profilar hoyra til hesa instans",
"horizon.splitscreen.profiles.move": "Flyt har tú spælir",
"horizon.splitscreen.profiles.move_place": "Flyt har tú spælir: %s .",
"horizon.friends.title": "Spæl við vinum",
"horizon.friends.hint": "Vinir líma kotuna eftir Vinir knøttin á tittulskjálvtanum, í Beinleiðis sambandi ella á Spæla síðuni á sjósetaranum.",
"horizon.friends.copied": "Avritað",
"horizon.friends.copy_code": "Avritskotu",
"horizon.friends.stop_sharing": "Steðga við at deila",
"horizon.friends.none_yet": "Eingir vinir her enn.",
"horizon.friends.here_now": "Her nú: %s",
"horizon.friends.share_intro": "Deil hendan heimin aftanfyri eina boðkotu: hon letur upp fyri LAN, og vinir á internetinum melda seg til við koduni. Eingin servari hjá okkum er við.",
"horizon.friends.start_sharing": "Byrja at deila",
"horizon.friends.troubleshooting": "Trupulleikaloysn...",
"horizon.friends.stopped": "Steðgaði við at deila boðkotuna.",
"horizon.friends.short_code_changed": "Onkur bleiv við at royna eina skeiva stutta kodu, so hon broyttist.",
"horizon.friends.wrong_code": "Onkur royndi eina skeiva kodu.",
"horizon.friends.relay_stopped": "Ov nógvar skeivar stuttkour, so stafettin er sløkt, til tú deilir aftur. Vinir kunnu framvegis melda seg til við fullu koduni.",
"horizon.friends.code_ready": "Tín boðkoda er klár: Spælvalmynd, Spæl við vinum. Kopiera tað og send tað til tínar vinir.",
"horizon.friends.share_failed": "Kundi ikki deila heimin: %s",
"horizon.friends.finding_route": "At finna útav, hvussu vinir kunnu røkka tær...",
"horizon.osk.shift": "Vakt",
"horizon.osk.space": "Rúm",
"horizon.osk.delete": "Strika",
@@ -208,7 +208,11 @@
"horizon.mods.switch.restart": "Redémarre le jeu pour appliquer %s : ils ajoutent des blocs, des objets ou de la génération de monde.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Copier les détails de connexion",
"horizon.multiplayer.join": "Rejoindre",
"horizon.multiplayer.cancel_reconnecting": "Annuler la reconnexion",
"horizon.multiplayer.join_friend": "Rejoindre un ami",
"horizon.multiplayer.invite_code": "Code d'invitation",
"horizon.multiplayer.relay": "Relais (facultatif)",
"Preset": "Préréglage",
"LOD Distance": "Distance LOD",
"Far Detail": "Détails lointains",
@@ -298,6 +302,7 @@
"horizon.extras.zoom_mod_install": "Zoom : à installer depuis Mods",
"horizon.extras.pack_browser": "Navigateur de packs de ressources",
"horizon.extras.music_page.tooltip": "Musique et sons gagne une page Musique... : lancez n'importe quelle piste intégrée maintenant, ou désactivez-en une pour que le jeu arrête de la choisir. Rien ne change tant que vous ne désactivez pas une piste.",
"horizon.friends.relay_stopped": "Trop de codes courts erronés : le relais est désactivé jusqu'à ce que vous partagiez à nouveau. Vos amis peuvent toujours rejoindre avec le code complet.",
"horizon.extras.pack_browser.tooltip": "La sélection des packs de ressources gagne un bouton Ajouter qui cherche sur Modrinth et installe un pack dans votre dossier de packs. Désactivé, le jeu ne contacte jamais Modrinth.",
"horizon.splitscreen.setup.layout.two.0": "Auto",
"Opaque Ice": "Glace opaque",
@@ -427,6 +432,22 @@
"horizon.splitscreen.profiles.offline_note": "Les profils hors ligne appartiennent à cette instance",
"horizon.splitscreen.profiles.move": "Changer d'emplacement de jeu",
"horizon.splitscreen.profiles.move_place": "Changer d'emplacement de jeu : %s",
"horizon.friends.title": "Jouer avec des amis",
"horizon.friends.hint": "Vos amis collent le code après le bouton Amis de l'écran titre, dans « Connexion rapide » ou sur la page Jouer du lanceur.",
"horizon.friends.copied": "Copié",
"horizon.friends.copy_code": "Copier le code",
"horizon.friends.stop_sharing": "Arrêter le partage",
"horizon.friends.none_yet": "Aucun ami pour l'instant.",
"horizon.friends.here_now": "Présents : %s",
"horizon.friends.share_intro": "Partagez ce monde avec un code d'invitation : il s'ouvre au LAN, et vos amis sur internet le rejoignent avec le code. Aucun serveur de notre part n'est impliqué.",
"horizon.friends.start_sharing": "Commencer le partage",
"horizon.friends.troubleshooting": "Dépannage...",
"horizon.friends.stopped": "Le partage du code d'invitation est arrêté.",
"horizon.friends.short_code_changed": "Quelqu'un a essayé plusieurs fois un mauvais code court, il a donc été changé.",
"horizon.friends.wrong_code": "Quelqu'un a essayé un mauvais code.",
"horizon.friends.code_ready": "Votre code d'invitation est prêt : Menu du jeu, Jouer avec des amis. Copiez-le et envoyez-le à vos amis.",
"horizon.friends.share_failed": "Impossible de partager le monde : %s",
"horizon.friends.finding_route": "Recherche de la manière dont vos amis peuvent vous joindre…",
"horizon.osk.shift": "Maj.",
"horizon.osk.space": "Espace",
"horizon.osk.delete": "Effacer",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Torne a inviâ il zûc par aplicâ %s: a zontin blocs, ogjets o generazion dal mont.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Copiâ i detais de conession",
"horizon.multiplayer.join": "Iscrivitvi",
"horizon.multiplayer.cancel_reconnecting": "Annulâ la riconession",
"horizon.multiplayer.join_friend": "Iscrivitvi a un amì",
"horizon.multiplayer.invite_code": "Codiç di invit",
"horizon.multiplayer.relay": "Relê (opzionâl)",
"Preset": "Preset",
"LOD Distance": "Distance LOD",
"Far Detail": "Detai lontan",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "I profîi fûr linie a apartegnin a cheste esemplificazion",
"horizon.splitscreen.profiles.move": "Spostâsi dulà che tu zuiis",
"horizon.splitscreen.profiles.move_place": "Spostâsi dulà che si zuie: %s",
"horizon.friends.title": "Zuegâ cui amîs",
"horizon.friends.hint": "I amîs a incolin il codiç dopo dal botôn Amîs de scherme dal titul, in Conession direte, o su la pagjine Play dal lançadôr.",
"horizon.friends.copied": "Copiât",
"horizon.friends.copy_code": "Codiç di copie",
"horizon.friends.stop_sharing": "Fermâ di condividi",
"horizon.friends.none_yet": "Ancjemò nissun amì culì.",
"horizon.friends.here_now": "Eco cumò: %s",
"horizon.friends.share_intro": "Condividi chest mont daûr di un codiç di invit: al si vierç ae LAN, e i amîs su internet a si unissin cul codiç. Nissun nestri servidôr al è coinvolt.",
"horizon.friends.start_sharing": "Scomencia a condividi",
"horizon.friends.troubleshooting": "Risoluzion dai problemis...",
"horizon.friends.stopped": "Fermât di condividi il codiç di invit.",
"horizon.friends.short_code_changed": "Cualchidun al continuave a provâ un codiç curt sbalît, cussì al cambià.",
"horizon.friends.wrong_code": "Cualchidun al à provât un codiç sbalît.",
"horizon.friends.relay_stopped": "Masse codiçs curts sbalâts, cussì il relê al è spent fin che no tu condividis di gnûf. I amîs a puedin ancjemò jentrâ cul codiç complet.",
"horizon.friends.code_ready": "Il to codiç di invit al è pront: Menu dal zûc, Zugâ cui amîs. Copielu e mandâlu ai tois amiis.",
"horizon.friends.share_failed": "No rivave a condividi il mont: %s",
"horizon.friends.finding_route": "Cjatâ cemût che i amîs a puedin rivâ a te...",
"horizon.osk.shift": "Cambi",
"horizon.osk.space": "Spazi",
"horizon.osk.delete": "Elimina",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Start it spul opnij om %s tapasse te litten: se foegje blokken, items of wrâldgeneraasje ta.",
"horizon.shader_options.profile": "Profyl",
"horizon.agent.copy_details": "Kopiearje Ferbiningsdetails",
"horizon.multiplayer.join": "Meidwaan",
"horizon.multiplayer.cancel_reconnecting": "Ofbrekke opnij ferbinen",
"horizon.multiplayer.join_friend": "Doch mei oan in freon",
"horizon.multiplayer.invite_code": "Koade útnoegje",
"horizon.multiplayer.relay": "Relais (opsjoneel)",
"Preset": "Foarynsteld",
"LOD Distance": "LOD Ofstân",
"Far Detail": "Fier Detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profilen hearre ta dit eksimplaar",
"horizon.splitscreen.profiles.move": "Ferpleats wêr't jo spylje",
"horizon.splitscreen.profiles.move_place": "Ferpleats wêr't jo spylje: %s",
"horizon.friends.title": "Boartsje mei freonen",
"horizon.friends.hint": "Freonen plakke de koade nei de knop Freonen fan it titelskerm, yn Direkte ferbining, of op 'e Play-side fan 'e launcher.",
"horizon.friends.copied": "Kopiearre",
"horizon.friends.copy_code": "Kopiearje Code",
"horizon.friends.stop_sharing": "Stopje mei dielen",
"horizon.friends.none_yet": "Gjin freonen hjir noch.",
"horizon.friends.here_now": "Hjir no: %s",
"horizon.friends.share_intro": "Diel dizze wrâld efter in útnoegingskoade: it iepenet nei LAN, en freonen op it ynternet dogge mei mei de koade. Gjin tsjinner fan ús is belutsen.",
"horizon.friends.start_sharing": "Begjin te dielen",
"horizon.friends.troubleshooting": "Problemen oplosse...",
"horizon.friends.stopped": "Stoppe mei it dielen fan de útnoegingskoade.",
"horizon.friends.short_code_changed": "Immen besocht hieltyd in ferkearde koarte koade, dus it feroare.",
"horizon.friends.wrong_code": "Immen besocht in ferkearde koade.",
"horizon.friends.relay_stopped": "Te folle ferkearde koadekoarten, dus de estafette stiet út oant jo wer diele. Freonen kinne noch altyd mei de folsleine koade meidwaan.",
"horizon.friends.code_ready": "Jo útnoegingskoade is klear: Game Menu, Boartsje mei freonen. Kopiearje it en stjoer it nei jo freonen.",
"horizon.friends.share_failed": "Koe de wrâld net diele: %s",
"horizon.friends.finding_route": "Fyn hoe't freonen jo kinne berikke ...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Romte",
"horizon.osk.delete": "Wiskje",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Atosaigh an cluiche chun %s a chur i bhfeidhm: cuireann siad bloic, míreanna nó giniúint domhain leis.",
"horizon.shader_options.profile": "Próifíl",
"horizon.agent.copy_details": "Cóipeáil Sonraí Ceangail",
"horizon.multiplayer.join": "Bígí",
"horizon.multiplayer.cancel_reconnecting": "Cealaigh Athnascadh",
"horizon.multiplayer.join_friend": "Bígí le Cara",
"horizon.multiplayer.invite_code": "Cód Cuireadh",
"horizon.multiplayer.relay": "Sealaíocht (roghnach)",
"Preset": "Réamhshocraithe",
"LOD Distance": "LOD Fad",
"Far Detail": "Far Sonraigh",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Baineann próifílí as líne leis an gcás seo",
"horizon.splitscreen.profiles.move": "Bog áit a imríonn tú",
"horizon.splitscreen.profiles.move_place": "Bog áit a imríonn tú: %s",
"horizon.friends.title": "Seinn le Cairde",
"horizon.friends.hint": "Greamaigh Cairde an cód tar éis cnaipe Cairde an scáileáin teidil, i Ceangal Díreach, nó ar leathanach Súgartha an Tosaitheora.",
"horizon.friends.copied": "Cóipeáladh",
"horizon.friends.copy_code": "Cóipeáil Cód",
"horizon.friends.stop_sharing": "Stop Roinnt",
"horizon.friends.none_yet": "Níl aon chairde anseo fós.",
"horizon.friends.here_now": "Anseo anois: %s",
"horizon.friends.share_intro": "Roinn an domhan seo taobh thiar de chód cuirí: osclaíonn sé go LAN, agus glacann cairde ar an idirlíon leis an gcód. Níl aon fhreastalaí dár gcuid i gceist.",
"horizon.friends.start_sharing": "Tosaigh ag Roinnt",
"horizon.friends.troubleshooting": "Fabhtcheartú...",
"horizon.friends.stopped": "Stopadh an cód cuirí a roinnt.",
"horizon.friends.short_code_changed": "Lean duine éigin ag iarraidh cód gearr mícheart, mar sin d'athraigh sé.",
"horizon.friends.wrong_code": "Bhain duine éigin triail as cód mícheart.",
"horizon.friends.relay_stopped": "An iomarca cóid ghearra míchearta, mar sin tá an sealaíocht as go dtí go roinnfidh tú arís. Is féidir le cairde teacht isteach fós leis an gcód iomlán.",
"horizon.friends.code_ready": "Tá do chód cuireadh réidh: Roghchlár Cluiche, Spraoi le Cairde. Cóipeáil é agus seol chuig do chairde é.",
"horizon.friends.share_failed": "Níorbh fhéidir an domhan a roinnt: %s",
"horizon.friends.finding_route": "Ag fáil amach conas is féidir le cairde dul i dteagmháil leat…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Spás",
"horizon.osk.delete": "Scrios",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Ath-thòisich an geama gus %s a chur an sàs: tha iad a' cur blocaichean, nithean no gineadh saoghail ris.",
"horizon.shader_options.profile": "Pròifil",
"horizon.agent.copy_details": "Dèan lethbhreac den fhiosrachadh ceangail",
"horizon.multiplayer.join": "Thig còmhla",
"horizon.multiplayer.cancel_reconnecting": "Sguir dhen ath-cheangal",
"horizon.multiplayer.join_friend": "Thig còmhla ri Caraid",
"horizon.multiplayer.invite_code": "Còd cuireadh",
"horizon.multiplayer.relay": "Ath-chraoladh (roghainneil)",
"Preset": "Ro-shuidhichte",
"LOD Distance": "Astar LOD",
"Far Detail": "Fada mionaideach",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Buinidh pròifilean far-loidhne don t-suidheachadh seo",
"horizon.splitscreen.profiles.move": "Gluais far a bheil thu a 'cluich",
"horizon.splitscreen.profiles.move_place": "Gluais far a bheil thu a’ cluich: %s",
"horizon.friends.title": "Cluich le caraidean",
"horizon.friends.hint": "Bidh caraidean a’ cuir a-steach an còd às deidh putan Caraidean an sgrion tiotal, ann an Direct Connection, no air duilleag Cluich an lannsair.",
"horizon.friends.copied": "Rinn lethbhreac",
"horizon.friends.copy_code": "Dèan lethbhreac den Chòd",
"horizon.friends.stop_sharing": "Stad air roinneadh",
"horizon.friends.none_yet": "Chan eil caraidean an seo fhathast.",
"horizon.friends.here_now": "Seo agaibh a-nis: %s",
"horizon.friends.share_intro": "Roinn an saoghal seo air cùl còd cuireadh: bidh e a’ fosgladh gu LAN, agus bidh caraidean air an eadar-lìn a’ tighinn còmhla ris a’ chòd. Chan eil seirbheisiche sam bith againn an sàs.",
"horizon.friends.start_sharing": "Tòisich a 'roinneadh",
"horizon.friends.troubleshooting": "Fuasgladh thrioblaidean...",
"horizon.friends.stopped": "Sguir a bhith a’ roinneadh a’ chòd cuireadh.",
"horizon.friends.short_code_changed": "Chùm cuideigin a’ feuchainn còd goirid ceàrr, agus mar sin dh’atharraich e.",
"horizon.friends.wrong_code": "Dh’fheuch cuideigin còd ceàrr.",
"horizon.friends.relay_stopped": "Cus de chòdan goirid ceàrr, agus mar sin tha an t-sealaidheachd dheth gus an roinn thu a-rithist. Faodaidh caraidean a dhol còmhla leis a' chòd slàn fhathast.",
"horizon.friends.code_ready": "Tha an còd cuireadh agad deiseil: Clàr Gèam, Cluich le Caraidean. Dèan lethbhreac dheth agus cuir gu do charaidean e.",
"horizon.friends.share_failed": "Cha b’ urrainn dhuinn an saoghal a cho-roinn: %s",
"horizon.friends.finding_route": "Faigh a-mach mar as urrainn do charaidean ruighinn ort…",
"horizon.osk.shift": "Gluasad",
"horizon.osk.space": "Àite",
"horizon.osk.delete": "Sguab às",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinicia o xogo para aplicar %s: engaden bloques, obxectos ou xeración do mundo.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copiar os detalles da conexión",
"horizon.multiplayer.join": "Únete",
"horizon.multiplayer.cancel_reconnecting": "Cancelar a conexión",
"horizon.multiplayer.join_friend": "Únete a un amigo",
"horizon.multiplayer.invite_code": "Código de invitación",
"horizon.multiplayer.relay": "Relé (opcional)",
"Preset": "Predefinido",
"LOD Distance": "Distancia LOD",
"Far Detail": "Detalle lonxano",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Os perfís sen conexión pertencen a esta instancia",
"horizon.splitscreen.profiles.move": "Móvete onde xogas",
"horizon.splitscreen.profiles.move_place": "Move onde xogas: %s",
"horizon.friends.title": "Xoga cos amigos",
"horizon.friends.hint": "Os amigos pegan o código despois do botón Amigos da pantalla de título, na Conexión directa ou na páxina Play do iniciador.",
"horizon.friends.copied": "Copiouse",
"horizon.friends.copy_code": "Copiar código",
"horizon.friends.stop_sharing": "Deixa de compartir",
"horizon.friends.none_yet": "Aínda non hai amigos aquí.",
"horizon.friends.here_now": "Aquí agora: %s",
"horizon.friends.share_intro": "Comparte este mundo detrás dun código de invitación: ábrese a LAN e os amigos de Internet únense co código. Ningún servidor noso está implicado.",
"horizon.friends.start_sharing": "Comeza a compartir",
"horizon.friends.troubleshooting": "Solución de problemas...",
"horizon.friends.stopped": "Deixou de compartir o código de invitación.",
"horizon.friends.short_code_changed": "Alguén seguiu probando un código curto incorrecto, polo que cambiou.",
"horizon.friends.wrong_code": "Alguén intentou un código incorrecto.",
"horizon.friends.relay_stopped": "Demasiados códigos curtos incorrectos, polo que o relé está desactivado ata que volvas compartir. Os amigos aínda poden unirse co código completo.",
"horizon.friends.code_ready": "O teu código de invitación está listo: Menú Xogo, Xoga cos amigos. Cópiao e envíao aos teus amigos.",
"horizon.friends.share_failed": "Non se puido compartir o mundo: %s",
"horizon.friends.finding_route": "Buscando como os amigos poden contactar contigo...",
"horizon.osk.shift": "Cambio",
"horizon.osk.space": "Espazo",
"horizon.osk.delete": "Eliminar",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "E hoʻomaka hou i ka pāʻani e hoʻohana iā %s: hoʻohui lākou i nā poloka, nā mea a i ʻole ka hana honua.",
"horizon.shader_options.profile": "Pilikino",
"horizon.agent.copy_details": "E kope i nā kikoʻī pili",
"horizon.multiplayer.join": "Hui",
"horizon.multiplayer.cancel_reconnecting": "Hoʻopau i ka hoʻohui hou ʻana",
"horizon.multiplayer.join_friend": "E hui me kahi Hoa",
"horizon.multiplayer.invite_code": "Code kono",
"horizon.multiplayer.relay": "Relay (koho)",
"Preset": "Hoʻonohonoho mua",
"LOD Distance": "LOD mamao",
"Far Detail": "ʻIke lōʻihi",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "No kēia laʻana nā ʻaoʻao pahemo",
"horizon.splitscreen.profiles.move": "E neʻe i kahi āu e pāʻani ai",
"horizon.splitscreen.profiles.move_place": "E neʻe i kahi āu e pāʻani ai: %s",
"horizon.friends.title": "E pāʻani me nā hoa",
"horizon.friends.hint": "Hoʻopili nā hoa i ke code ma hope o ke pihi Hoa o ka pale poʻo inoa, ma Direct Connection, a i ʻole ma ka ʻaoʻao Play o ka mea hoʻolaha.",
"horizon.friends.copied": "Kope ʻia",
"horizon.friends.copy_code": "Kāhea kope",
"horizon.friends.stop_sharing": "Hooki i ka Kaʻana like",
"horizon.friends.none_yet": "ʻAʻohe hoa ma ʻaneʻi.",
"horizon.friends.here_now": "Eia i kēia manawa: %s",
"horizon.friends.share_intro": "E kaʻana like i kēia ao ma hope o kahi code kono: wehe ia i LAN, a hui pū nā hoaaloha ma ka pūnaewele me ke code. ʻAʻohe kikowaena o kā mākou pili.",
"horizon.friends.start_sharing": "Hoʻomaka Kaʻana like",
"horizon.friends.troubleshooting": "Hoʻoponopono pilikia...",
"horizon.friends.stopped": "Ua ho'ōki i ka hāʻawi ʻana i ke code kono.",
"horizon.friends.short_code_changed": "Ke hoʻāʻo nei kekahi i kahi code pōkole hewa, no laila ua loli.",
"horizon.friends.wrong_code": "Ua hoʻāʻo kekahi i kahi code hewa.",
"horizon.friends.relay_stopped": "Nui loa nā code pōkole hewa, no laila ua paʻa ka relay a hiki i kou kaʻana hou ʻana. Hiki nō i nā hoaaloha ke hui me ka code piha.",
"horizon.friends.code_ready": "Ua mākaukau kāu code kono: Game Menu, Play with Friends. E kope a hoʻouna aku i kāu mau hoaaloha.",
"horizon.friends.share_failed": "ʻAʻole hiki ke kaʻana like i ka honua: %s",
"horizon.friends.finding_route": "Ke ʻimi nei pehea e hiki ai i nā hoaaloha ke loaʻa iā ʻoe…",
"horizon.osk.shift": "Hoʻololi",
"horizon.osk.space": "Pā Hakahaka",
"horizon.osk.delete": "Holoi",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "הפעל מחדש את המשחק כדי להחיל %s: הם מוסיפים בלוקים, פריטים או יצירת עולם.",
"horizon.shader_options.profile": "פרופיל",
"horizon.agent.copy_details": "העתק את פרטי החיבור",
"horizon.multiplayer.join": "הצטרף",
"horizon.multiplayer.cancel_reconnecting": "בטל חיבור מחדש",
"horizon.multiplayer.join_friend": "הצטרף לחבר",
"horizon.multiplayer.invite_code": "קוד הזמנה",
"horizon.multiplayer.relay": "ממסר (אופציונלי)",
"Preset": "מוגדר מראש",
"LOD Distance": "מרחק LOD",
"Far Detail": "פרט רחוק",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "פרופילים לא מקוונים שייכים למופע הזה",
"horizon.splitscreen.profiles.move": "זז לאן שאתה משחק",
"horizon.splitscreen.profiles.move_place": "זז לאן שאתה משחק: %s",
"horizon.friends.title": "שחקו עם חברים",
"horizon.friends.hint": "חברים מדביקים את הקוד אחרי כפתור החברים של מסך הכותרת, בחיבור ישיר או בדף ההפעלה של המשגר.",
"horizon.friends.copied": "הועתק",
"horizon.friends.copy_code": "העתק קוד",
"horizon.friends.stop_sharing": "תפסיק לשתף",
"horizon.friends.none_yet": "אין כאן חברים עדיין.",
"horizon.friends.here_now": "כאן עכשיו: %s",
"horizon.friends.share_intro": "שתף את העולם הזה מאחורי קוד הזמנה: הוא נפתח ל-LAN, וחברים באינטרנט מצטרפים עם הקוד. אף שרת שלנו לא מעורב.",
"horizon.friends.start_sharing": "התחל לשתף",
"horizon.friends.troubleshooting": "פתרון בעיות...",
"horizon.friends.stopped": "הפסיק לשתף את קוד ההזמנה.",
"horizon.friends.short_code_changed": "מישהו כל הזמן ניסה קוד קצר שגוי, אז זה השתנה.",
"horizon.friends.wrong_code": "מישהו ניסה קוד שגוי.",
"horizon.friends.relay_stopped": "יותר מדי קודים קצרים שגויים, ולכן הממסר כבוי עד שתשתף שוב. חברים עדיין יכולים להצטרף עם הקוד המלא.",
"horizon.friends.code_ready": "קוד ההזמנה שלך מוכן: תפריט משחק, שחק עם חברים. העתק אותו ושלח אותו לחברים שלך.",
"horizon.friends.share_failed": "לא יכולתי לשתף את העולם: %s",
"horizon.friends.finding_route": "מוצא כיצד חברים יכולים להגיע אליך...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "חלל",
"horizon.osk.delete": "מחק",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s लागू करने के लिए गेम रीस्टार्ट करें: वे ब्लॉक, आइटम या विश्व जनरेशन जोड़ते हैं।",
"horizon.shader_options.profile": "प्रोफ़ाइल",
"horizon.agent.copy_details": "कनेक्शन विवरण कॉपी करें",
"horizon.multiplayer.join": "शामिल हों",
"horizon.multiplayer.cancel_reconnecting": "पुनः कनेक्ट करना रद्द करें",
"horizon.multiplayer.join_friend": "मित्र से जुड़ें",
"horizon.multiplayer.invite_code": "आमंत्रण कोड",
"horizon.multiplayer.relay": "रिले (वैकल्पिक)",
"Preset": "प्रीसेट",
"LOD Distance": "LOD दूरी",
"Far Detail": "दूर के विवरण",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "ऑफ़लाइन प्रोफ़ाइल इस इंस्टेंस के हैं",
"horizon.splitscreen.profiles.move": "स्थानांतरित करें जहाँ आप खेलते हैं",
"horizon.splitscreen.profiles.move_place": "स्थानांतरित करें जहाँ आप खेलते हैं: %s",
"horizon.friends.title": "मित्रों के साथ खेलें",
"horizon.friends.hint": "मित्र शीर्षक स्क्रीन के फ्रेंड्स बटन के बाद, डायरेक्ट कनेक्शन में, या लॉन्चर के प्ले पेज पर कोड पेस्ट करते हैं।",
"horizon.friends.copied": "कॉपी किया गया",
"horizon.friends.copy_code": "कोड कॉपी करें",
"horizon.friends.stop_sharing": "साझा करना बंद करें",
"horizon.friends.none_yet": "यहाँ अभी कोई मित्र नहीं है।",
"horizon.friends.here_now": "अभी यहाँ हैं: %s",
"horizon.friends.share_intro": "इस दुनिया को आमंत्रण कोड के पीछे साझा करें: यह LAN के लिए खुलता है, और इंटरनेट पर मित्र कोड के साथ जुड़ते हैं। इसमें हमारा कोई सर्वर शामिल नहीं है।",
"horizon.friends.start_sharing": "साझा करना शुरू करें",
"horizon.friends.troubleshooting": "समस्या निवारण...",
"horizon.friends.stopped": "आमंत्रण कोड साझा करना बंद कर दिया।",
"horizon.friends.short_code_changed": "किसी ने बार-बार गलत शॉर्ट कोड आजमाया, इसलिए यह बदल गया।",
"horizon.friends.wrong_code": "किसी ने गलत कोड आजमाया।",
"horizon.friends.relay_stopped": "बहुत अधिक गलत शॉर्ट कोड, इसलिए दोबारा साझा करने तक रिले बंद है। मित्र अभी भी पूर्ण कोड से जुड़ सकते हैं।",
"horizon.friends.code_ready": "आपका आमंत्रण कोड तैयार है: गेम मेनू, प्ले विद फ्रेंड्स। इसे कॉपी करें और अपने मित्रों को भेजें।",
"horizon.friends.share_failed": "दुनिया साझा नहीं की जा सकी: %s",
"horizon.friends.finding_route": "ढूंढ रहे हैं कि मित्र आप तक कैसे पहुँच सकते हैं…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Space",
"horizon.osk.delete": "Delete",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Ponovno pokrenite igru da biste primijenili %s: dodaju blokove, predmete ili generiranje svijeta.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopiraj pojedinosti veze",
"horizon.multiplayer.join": "Pridruži se",
"horizon.multiplayer.cancel_reconnecting": "Otkaži ponovno povezivanje",
"horizon.multiplayer.join_friend": "Pridruži se prijatelju",
"horizon.multiplayer.invite_code": "Pozivni kod",
"horizon.multiplayer.relay": "Prijenos (neobavezno)",
"Preset": "Predložak",
"LOD Distance": "LOD udaljenost",
"Far Detail": "Udaljeni detalji",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Izvanmrežni profili pripadaju ovoj instanci",
"horizon.splitscreen.profiles.move": "Premjesti mjesto igranja",
"horizon.splitscreen.profiles.move_place": "Premjesti mjesto igranja: %s",
"horizon.friends.title": "Igraj s prijateljima",
"horizon.friends.hint": "Prijatelji lijepe kod nakon gumba Prijatelji na naslovnom zaslonu, u izravnom povezivanju ili na stranici za igranje pokretača.",
"horizon.friends.copied": "Kopirano",
"horizon.friends.copy_code": "Kopiraj kod",
"horizon.friends.stop_sharing": "Zaustavi dijeljenje",
"horizon.friends.none_yet": "Ovdje još nema prijatelja.",
"horizon.friends.here_now": "Ovdje sada: %s",
"horizon.friends.share_intro": "Podijelite ovaj svijet iza pozivnog koda: otvara se za LAN, a prijatelji na internetu pridružuju se s kodom. Nijedan naš poslužitelj nije uključen.",
"horizon.friends.start_sharing": "Započni dijeljenje",
"horizon.friends.troubleshooting": "Rješavanje problema...",
"horizon.friends.stopped": "Zaustavljeno dijeljenje pozivnog koda.",
"horizon.friends.short_code_changed": "Netko je stalno pokušavao unijeti pogrešan kratki kod, pa se on promijenio.",
"horizon.friends.wrong_code": "Netko je pokušao unijeti pogrešan kod.",
"horizon.friends.relay_stopped": "Previše pogrešnih kratkih kodova, pa je prijenos isključen dok ponovno ne podijelite. Prijatelji se još mogu pridružiti s punim kodom.",
"horizon.friends.code_ready": "Vaš pozivni kod je spreman: Izbornik igre, Igraj s prijateljima. Kopirajte ga i pošaljite svojim prijateljima.",
"horizon.friends.share_failed": "Nije moguće dijeliti svijet: %s",
"horizon.friends.finding_route": "Pronalaženje načina na koji vas prijatelji mogu dosegnuti…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Razmaknica",
"horizon.osk.delete": "Izbriši",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Indítsa újra a játékot a(z) %s érvényesítéséhez: blokkokat, tárgyakat vagy világgenerálást ad hozzá.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Másolja a kapcsolat részleteit",
"horizon.multiplayer.join": "Csatlakozz",
"horizon.multiplayer.cancel_reconnecting": "Az újracsatlakozás megszakítása",
"horizon.multiplayer.join_friend": "Csatlakozz egy baráthoz",
"horizon.multiplayer.invite_code": "Meghívó kód",
"horizon.multiplayer.relay": "Relé (opcionális)",
"Preset": "Előre beállított",
"LOD Distance": "LOD távolság",
"Far Detail": "Távoli részlet",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Az offline profilok ehhez a példányhoz tartoznak",
"horizon.splitscreen.profiles.move": "Menj oda, ahol játszol",
"horizon.splitscreen.profiles.move_place": "Menjen oda, ahol játszik: %s",
"horizon.friends.title": "Játssz a barátokkal",
"horizon.friends.hint": "Az ismerősök beillesztik a kódot a címképernyő Barátok gombja mögé, a Közvetlen kapcsolatba vagy az indító Play oldalára.",
"horizon.friends.copied": "Másolva",
"horizon.friends.copy_code": "Kód másolása",
"horizon.friends.stop_sharing": "Megosztás leállítása",
"horizon.friends.none_yet": "Még nincsenek itt barátok.",
"horizon.friends.here_now": "Itt most: %s",
"horizon.friends.share_intro": "Oszd meg ezt a világot egy meghívókód mögött: megnyílik a LAN-hoz, és az interneten lévő ismerősök is csatlakoznak a kódhoz. A mi szerverünk nem érintett.",
"horizon.friends.start_sharing": "Indítsa el a Megosztást",
"horizon.friends.troubleshooting": "Hibaelhárítás...",
"horizon.friends.stopped": "A meghívókód megosztása leállt.",
"horizon.friends.short_code_changed": "Valaki folyamatosan rossz rövid kóddal próbálkozott, ezért megváltozott.",
"horizon.friends.wrong_code": "Valaki rossz kóddal próbálkozott.",
"horizon.friends.relay_stopped": "Túl sok rossz rövid kód érkezett, ezért a relé ki van kapcsolva, amíg újra nem osztja meg. A barátok a teljes kóddal továbbra is csatlakozhatnak.",
"horizon.friends.code_ready": "A meghívókód készen áll: Játékmenü, Játssz a barátokkal. Másold ki és küldd el ismerőseidnek.",
"horizon.friends.share_failed": "Nem sikerült megosztani a világot: %s",
"horizon.friends.finding_route": "Megtudja, hogyan érhetnek el barátaid…",
"horizon.osk.shift": "Váltás",
"horizon.osk.space": "Tér",
"horizon.osk.delete": "Törölje",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Վերագործարկեք խաղը՝ %s-ը կիրառելու համար. դրանք ավելացնում են բլոկներ, իրեր կամ աշխարհի գեներացիա։",
"horizon.shader_options.profile": "Անձնագիր",
"horizon.agent.copy_details": "Պատճենել կապի մանրամասները",
"horizon.multiplayer.join": "Միանալ",
"horizon.multiplayer.cancel_reconnecting": "Չեղարկել վերամիացումը",
"horizon.multiplayer.join_friend": "Միացեք ընկերոջը",
"horizon.multiplayer.invite_code": "Հրավիրել կոդը",
"horizon.multiplayer.relay": "Ռելե (ըստ ցանկության)",
"Preset": "Նախադրված",
"LOD Distance": "LOD Հեռավորություն",
"Far Detail": "Հեռավոր մանրամասն",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Անցանց պրոֆիլները պատկանում են այս օրինակին",
"horizon.splitscreen.profiles.move": "Տեղափոխեք այնտեղ, որտեղ խաղում եք",
"horizon.splitscreen.profiles.move_place": "Տեղափոխեք այնտեղ, որտեղ խաղում եք՝ %s",
"horizon.friends.title": "Խաղացեք ընկերների հետ",
"horizon.friends.hint": "Ընկերները տեղադրում են կոդը վերնագրի էկրանի Ընկերներ կոճակից հետո, ուղիղ միացումում կամ գործարկողի Play էջում:",
"horizon.friends.copied": "Պատճենվել է",
"horizon.friends.copy_code": "Պատճենել կոդը",
"horizon.friends.stop_sharing": "Դադարեցնել համօգտագործումը",
"horizon.friends.none_yet": "Այստեղ դեռ ընկերներ չկան:",
"horizon.friends.here_now": "Ահա հիմա: %s",
"horizon.friends.share_intro": "Կիսվեք այս աշխարհով հրավերի կոդով. այն բացվում է LAN-ի համար, և ինտերնետում գտնվող ընկերները միանում են կոդով: Մեր ոչ մի սերվեր ներգրավված չէ:",
"horizon.friends.start_sharing": "Սկսեք համօգտագործել",
"horizon.friends.troubleshooting": "Անսարքությունների վերացում...",
"horizon.friends.stopped": "Դադարեցվել է հրապարակել հրավերի կոդը:",
"horizon.friends.short_code_changed": "Ինչ-որ մեկը շարունակում էր սխալ կարճ կոդ փորձել, ուստի այն փոխվեց:",
"horizon.friends.wrong_code": "Ինչ-որ մեկը սխալ կոդ է փորձել:",
"horizon.friends.relay_stopped": "Չափից շատ սխալ կարճ կոդեր, ուստի ռելեն անջատված է, մինչև նորից կիսվեք։ Ընկերները դեռ կարող են միանալ ամբողջական կոդով։",
"horizon.friends.code_ready": "Ձեր հրավերի կոդը պատրաստ է. Խաղի ընտրացանկ, Խաղացեք ընկերների հետ: Պատճենեք այն և ուղարկեք ձեր ընկերներին։",
"horizon.friends.share_failed": "Չեմ կարող կիսվել աշխարհով. %s",
"horizon.friends.finding_route": "Գտեք, թե ինչպես ընկերները կարող են կապվել ձեզ հետ…",
"horizon.osk.shift": "Հերթափոխ",
"horizon.osk.space": "Տիեզերք",
"horizon.osk.delete": "Ջնջել",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Mulai ulang game untuk menerapkan %s: mod ini menambahkan blok, item, atau pembuatan dunia.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Salin Detail Koneksi",
"horizon.multiplayer.join": "Gabung",
"horizon.multiplayer.cancel_reconnecting": "Batalkan Menyambungkan Ulang",
"horizon.multiplayer.join_friend": "Gabung dengan Teman",
"horizon.multiplayer.invite_code": "Kode Undangan",
"horizon.multiplayer.relay": "Relay (opsional)",
"Preset": "Prasetel",
"LOD Distance": "Jarak LOD",
"Far Detail": "Detail Jauh",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Profil offline milik instans ini",
"horizon.splitscreen.profiles.move": "Pindahkan posisi bermain",
"horizon.splitscreen.profiles.move_place": "Pindahkan posisi bermain: %s",
"horizon.friends.title": "Bermain dengan Teman",
"horizon.friends.hint": "Teman menempelkan kode setelah mengeklik tombol Teman di layar judul, melalui Koneksi Langsung (Direct Connection), atau di halaman Main peluncur.",
"horizon.friends.copied": "Disalin",
"horizon.friends.copy_code": "Salin Kode",
"horizon.friends.stop_sharing": "Berhenti Berbagi",
"horizon.friends.none_yet": "Belum ada teman di sini.",
"horizon.friends.here_now": "Di sini sekarang: %s",
"horizon.friends.share_intro": "Bagikan dunia ini di balik kode undangan: dunia akan terbuka untuk LAN, dan teman di internet dapat bergabung menggunakan kode tersebut. Tidak ada server kami yang dilibatkan.",
"horizon.friends.start_sharing": "Mulai Berbagi",
"horizon.friends.troubleshooting": "Pemecahan Masalah...",
"horizon.friends.stopped": "Berhenti berbagi kode undangan.",
"horizon.friends.short_code_changed": "Seseorang terus mencoba kode pendek yang salah, sehingga kode telah diubah.",
"horizon.friends.wrong_code": "Seseorang mencoba memasukkan kode yang salah.",
"horizon.friends.relay_stopped": "Terlalu banyak kode pendek yang salah, sehingga relay nonaktif hingga Anda berbagi lagi. Teman tetap dapat bergabung dengan kode lengkap.",
"horizon.friends.code_ready": "Kode undangan Anda sudah siap: Menu Game -> Bermain dengan Teman. Salin dan kirimkan ke teman-teman Anda.",
"horizon.friends.share_failed": "Tidak dapat membagikan dunia: %s",
"horizon.friends.finding_route": "Mencari cara agar teman dapat menjangkau Anda…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Spasi",
"horizon.osk.delete": "Hapus",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Malitegharịa egwuregwu ka itinye %s n'ọrụ: ha na-agbakwunye blọk, ihe ma ọ bụ imepụta ụwa.",
"horizon.shader_options.profile": "Profaịlụ",
"horizon.agent.copy_details": "Detuo nkọwa njikọ",
"horizon.multiplayer.join": "Soro",
"horizon.multiplayer.cancel_reconnecting": "Kagbuo njikọ ọzọ",
"horizon.multiplayer.join_friend": "Soro enyi",
"horizon.multiplayer.invite_code": "Koodu ịkpọ oku",
"horizon.multiplayer.relay": "Ntugharị (nhọrọ)",
"Preset": "Ntọala",
"LOD Distance": "Ogologo LOD",
"Far Detail": "Nkọwa zuru oke",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Profaịlụ ndị na-anọghị n'ịntanetị bụ nke ihe atụ a",
"horizon.splitscreen.profiles.move": "Bugharịa ebe ị na-egwu",
"horizon.splitscreen.profiles.move_place": "Bugharịa ebe ị na-egwu: %s",
"horizon.friends.title": "Soro ndị enyi gwuo egwu",
"horizon.friends.hint": "Ndị enyi na-amanye koodu ahụ ka bọtịnụ ndị enyi gachara aha ihuenyo ahụ, na njikọ Direct, ma ọ bụ na ibe Play nke onye mbido.",
"horizon.friends.copied": "Eṅomiri",
"horizon.friends.copy_code": "Detuo koodu",
"horizon.friends.stop_sharing": "Kwụsị ikekọrịta",
"horizon.friends.none_yet": "Onweghi enyi ebea.",
"horizon.friends.here_now": "Ebe a ugbu a: %s",
"horizon.friends.share_intro": "Kekọrịta ụwa a n'azụ koodu ịkpọ òkù: ọ ga-emepe na LAN, ndị enyi na ịntanetị sonye na koodu ahụ. Ọ nweghị ihe nkesa nke anyị metụtara.",
"horizon.friends.start_sharing": "Malite ikekọrịta",
"horizon.friends.troubleshooting": "Nchọpụta nsogbu...",
"horizon.friends.stopped": "Kwụsị ikesa koodu ịkpọ òkù.",
"horizon.friends.short_code_changed": "Mmadụ nọgidere na-agbalị koodu dị mkpirikpi na-ezighi ezi, ya mere ọ gbanwere.",
"horizon.friends.wrong_code": "Mmadụ nwara koodu na-ezighi ezi.",
"horizon.friends.relay_stopped": "Koodu mkpụmkpụ na-ezighi ezi karịrị oke, ya mere relay agbanyụrụ ruo mgbe i ga-ekerịta ọzọ. Ndị enyi ka nwere ike iso na koodu zuru oke.",
"horizon.friends.code_ready": "Koodu ịkpọ oku gị adịla njikere: NchNhr Egwuregwu, Soro ndị enyi gwuo egwu. Detuo ya ma ziga ya ndị enyi gị.",
"horizon.friends.share_failed": "Enweghị ike ịkekọrịta ụwa: %s",
"horizon.friends.finding_route": "Ịchọta ka ndị enyi ga-esi nweta gị…",
"horizon.osk.shift": "Mgbanwe",
"horizon.osk.space": "Oghere",
"horizon.osk.delete": "Hichapụ",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Endurræstu leikinn til að virkja %s: þau bæta við blokkum, hlutum eða heimsmyndun.",
"horizon.shader_options.profile": "Prófíll",
"horizon.agent.copy_details": "Afritaðu tengingarupplýsingar",
"horizon.multiplayer.join": "Vertu með",
"horizon.multiplayer.cancel_reconnecting": "Hætta við að tengjast aftur",
"horizon.multiplayer.join_friend": "Vertu með í vini",
"horizon.multiplayer.invite_code": "Boðskóði",
"horizon.multiplayer.relay": "Relay (valfrjálst)",
"Preset": "Forstillt",
"LOD Distance": "LOD Fjarlægð",
"Far Detail": "Langt smáatriði",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Prófílar án nettengingar tilheyra þessu tilviki",
"horizon.splitscreen.profiles.move": "Færðu þig þangað sem þú spilar",
"horizon.splitscreen.profiles.move_place": "Færðu þig þar sem þú spilar: %s",
"horizon.friends.title": "Spilaðu með vinum",
"horizon.friends.hint": "Vinir líma kóðann aftan við Vinahnapp titilskjásins, í beinni tengingu eða á Play síðu ræsiforritsins.",
"horizon.friends.copied": "Afritað",
"horizon.friends.copy_code": "Afritaðu kóða",
"horizon.friends.stop_sharing": "Hættu að deila",
"horizon.friends.none_yet": "Engir vinir hér ennþá.",
"horizon.friends.here_now": "Hér núna: %s",
"horizon.friends.share_intro": "Deildu þessum heimi á bak við boðskóða: hann opnast fyrir staðarnet og vinir á internetinu tengjast með kóðanum. Enginn þjónn okkar kemur við sögu.",
"horizon.friends.start_sharing": "Byrjaðu að deila",
"horizon.friends.troubleshooting": "Úrræðaleit...",
"horizon.friends.stopped": "Hætti að deila boðskóðanum.",
"horizon.friends.short_code_changed": "Einhver hélt áfram að reyna rangan stuttkóða, svo hann breyttist.",
"horizon.friends.wrong_code": "Einhver reyndi rangan kóða.",
"horizon.friends.relay_stopped": "Of margir rangir stuttkóðar, svo gengið er slökkt þar til þú deilir aftur. Vinir geta samt tengst með fullum kóða.",
"horizon.friends.code_ready": "Boðskóðinn þinn er tilbúinn: Leikjavalmynd, Spilaðu með vinum. Afritaðu það og sendu það til vina þinna.",
"horizon.friends.share_failed": "Gat ekki deilt heiminum: %s",
"horizon.friends.finding_route": "Að finna hvernig vinir geta náð í þig...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Rými",
"horizon.osk.delete": "Eyða",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Riavvia il gioco per applicare %s: aggiungono blocchi, oggetti o generazione del mondo.",
"horizon.shader_options.profile": "Profilo",
"horizon.agent.copy_details": "Copia i dettagli della connessione",
"horizon.multiplayer.join": "Partecipa",
"horizon.multiplayer.cancel_reconnecting": "Annulla riconnessione",
"horizon.multiplayer.join_friend": "Unisciti a un amico",
"horizon.multiplayer.invite_code": "Codice invito",
"horizon.multiplayer.relay": "Relè (opzionale)",
"Preset": "Preimpostato",
"LOD Distance": "Distanza LOD",
"Far Detail": "Dettaglio lontano",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "I profili offline appartengono a questa istanza",
"horizon.splitscreen.profiles.move": "Muoviti dove giochi",
"horizon.splitscreen.profiles.move_place": "Spostati dove giochi: %s",
"horizon.friends.title": "Gioca con gli amici",
"horizon.friends.hint": "Gli amici incollano il codice dopo il pulsante Amici della schermata del titolo, in Connessione diretta o nella pagina di riproduzione del launcher.",
"horizon.friends.copied": "Copiato",
"horizon.friends.copy_code": "Copia codice",
"horizon.friends.stop_sharing": "Interrompi la condivisione",
"horizon.friends.none_yet": "Nessun amico qui ancora.",
"horizon.friends.here_now": "Ecco adesso: %s",
"horizon.friends.share_intro": "Condividi questo mondo dietro un codice di invito: si apre alla LAN e gli amici su Internet si uniscono con il codice. Nessun nostro server è coinvolto.",
"horizon.friends.start_sharing": "Inizia a condividere",
"horizon.friends.troubleshooting": "Risoluzione dei problemi...",
"horizon.friends.stopped": "Interrotta la condivisione del codice di invito.",
"horizon.friends.short_code_changed": "Qualcuno continuava a provare un codice funzione sbagliato, quindi è cambiato.",
"horizon.friends.wrong_code": "Qualcuno ha provato un codice sbagliato.",
"horizon.friends.relay_stopped": "Troppi codici brevi errati, quindi il relè è spento finché non condividi di nuovo. Gli amici possono ancora unirsi con il codice completo.",
"horizon.friends.code_ready": "Il tuo codice di invito è pronto: Menu di gioco, Gioca con gli amici. Copialo e invialo ai tuoi amici.",
"horizon.friends.share_failed": "Impossibile condividere il mondo: %s",
"horizon.friends.finding_route": "Scoprire come gli amici possono contattarti...",
"horizon.osk.shift": "Cambio",
"horizon.osk.space": "Spazio",
"horizon.osk.delete": "Elimina",
@@ -236,7 +236,11 @@
"horizon.mods.open_folder": "Modフォルダーを開く",
"horizon.shader_options.profile": "プロフィール",
"horizon.agent.copy_details": "接続詳細のコピー",
"horizon.multiplayer.join": "参加する",
"horizon.multiplayer.cancel_reconnecting": "再接続のキャンセル",
"horizon.multiplayer.join_friend": "友達に加わる",
"horizon.multiplayer.invite_code": "招待コード",
"horizon.multiplayer.relay": "リレー(オプション)",
"Preset": "プリセット",
"LOD Distance": "LOD距離",
"Far Detail": "遠くの詳細",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "オフライン プロファイルはこのインスタンスに属します",
"horizon.splitscreen.profiles.move": "遊ぶ場所を移動する",
"horizon.splitscreen.profiles.move_place": "プレイする場所を移動: %s",
"horizon.friends.title": "友達と遊ぶ",
"horizon.friends.hint": "フレンドは、タイトル画面のフレンドボタンの後、ダイレクト接続、またはランチャーのプレイページにコードを貼り付けます。",
"horizon.friends.copied": "コピーされました",
"horizon.friends.copy_code": "コードをコピーする",
"horizon.friends.stop_sharing": "共有を停止する",
"horizon.friends.none_yet": "ここにはまだ友達がいません。",
"horizon.friends.here_now": "今ここ: %s",
"horizon.friends.share_intro": "招待コードを使用してこの世界を共有します。コードは LAN に開かれ、インターネット上の友人はコードを使用して参加します。弊社のサーバーは関与しておりません。",
"horizon.friends.start_sharing": "共有を開始する",
"horizon.friends.troubleshooting": "トラブルシューティング中...",
"horizon.friends.stopped": "招待コードの共有を停止しました。",
"horizon.friends.short_code_changed": "誰かが間違ったショートコードを試し続けたため、コードが変更されました。",
"horizon.friends.wrong_code": "誰かが間違ったコードを試みました。",
"horizon.friends.relay_stopped": "短いコードの入力ミスが多すぎるため、再び共有するまでリレーはオフです。友達は完全なコードなら参加できます。",
"horizon.friends.code_ready": "招待コードの準備が整いました: ゲーム メニュー、友達とプレイ。コピーして友達に送信してください。",
"horizon.friends.share_failed": "世界を共有できませんでした: %s",
"horizon.friends.finding_route": "友達があなたに連絡する方法を調べています…",
"horizon.osk.shift": "シフト",
"horizon.osk.space": "宇宙",
"horizon.osk.delete": "削除",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "გადაუშვით თამაში %s-ის გამოსაყენებლად: ისინი ამატებენ ბლოკებს, ნივთებს ან სამყაროს გენერაციას.",
"horizon.shader_options.profile": "პროფილი",
"horizon.agent.copy_details": "დააკოპირეთ კავშირის დეტალები",
"horizon.multiplayer.join": "შეუერთდი",
"horizon.multiplayer.cancel_reconnecting": "ხელახლა დაკავშირების გაუქმება",
"horizon.multiplayer.join_friend": "შეუერთდი მეგობარს",
"horizon.multiplayer.invite_code": "მოწვევის კოდი",
"horizon.multiplayer.relay": "რელე (სურვილისამებრ)",
"Preset": "წინასწარ დაყენებული",
"LOD Distance": "LOD მანძილი",
"Far Detail": "შორეული დეტალი",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "ოფლაინ პროფილები ეკუთვნის ამ შემთხვევას",
"horizon.splitscreen.profiles.move": "იმოძრავეთ იქ, სადაც თამაშობთ",
"horizon.splitscreen.profiles.move_place": "გადაიტანეთ სადაც თამაშობთ: %s",
"horizon.friends.title": "ითამაშეთ მეგობრებთან ერთად",
"horizon.friends.hint": "მეგობრებმა ჩასვით კოდი სათაურის ეკრანის მეგობრების ღილაკის შემდეგ, პირდაპირი კავშირში ან გამშვების Play გვერდზე.",
"horizon.friends.copied": "კოპირებულია",
"horizon.friends.copy_code": "დააკოპირეთ კოდი",
"horizon.friends.stop_sharing": "შეწყვიტე გაზიარება",
"horizon.friends.none_yet": "აქ მეგობრები ჯერ არ არის.",
"horizon.friends.here_now": "აქ არის ახლა: %s",
"horizon.friends.share_intro": "გააზიარეთ ეს სამყარო მოწვევის კოდის მიღმა: ის იხსნება LAN-ზე და ინტერნეტში მყოფი მეგობრები უერთდებიან კოდით. არც ერთი ჩვენი სერვერი არ არის ჩართული.",
"horizon.friends.start_sharing": "დაიწყეთ გაზიარება",
"horizon.friends.troubleshooting": "პრობლემების აღმოფხვრა...",
"horizon.friends.stopped": "შეწყვიტა მოწვევის კოდის გაზიარება.",
"horizon.friends.short_code_changed": "ვიღაც ცდილობდა არასწორ მოკლე კოდს, ამიტომ ის შეიცვალა.",
"horizon.friends.wrong_code": "ვიღაცამ არასწორი კოდი სცადა.",
"horizon.friends.relay_stopped": "ძალიან ბევრი არასწორი მოკლე კოდი, ამიტომ რელე გამორთულია, სანამ ხელახლა არ გააზიარებთ. მეგობრებს მაინც შეუძლიათ შეერთება სრული კოდით.",
"horizon.friends.code_ready": "თქვენი მოწვევის კოდი მზად არის: თამაშის მენიუ, თამაში მეგობრებთან ერთად. დააკოპირეთ და გაუგზავნეთ თქვენს მეგობრებს.",
"horizon.friends.share_failed": "ვერ ვიზიარებ სამყაროს: %s",
"horizon.friends.finding_route": "იპოვნეთ როგორ დაგიკავშირდნენ მეგობრები…",
"horizon.osk.shift": "ცვლა",
"horizon.osk.space": "სივრცე",
"horizon.osk.delete": "წაშლა",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s қолдану үшін ойынды қайта іске қосыңыз: олар блоктар, заттар немесе әлем генерациясын қосады.",
"horizon.shader_options.profile": "Профиль",
"horizon.agent.copy_details": "Қосылым мәліметтерін көшіру",
"horizon.multiplayer.join": "Қосылыңыз",
"horizon.multiplayer.cancel_reconnecting": "Қайта қосылудан бас тарту",
"horizon.multiplayer.join_friend": "Досқа қосылу",
"horizon.multiplayer.invite_code": "Шақыру коды",
"horizon.multiplayer.relay": "Эстафета (міндетті емес)",
"Preset": "Алдын ала орнатылған",
"LOD Distance": "LOD қашықтығы",
"Far Detail": "Алыс бөлшектер",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профильдер осы данаға жатады",
"horizon.splitscreen.profiles.move": "Ойнайтын жерге көшіңіз",
"horizon.splitscreen.profiles.move_place": "Ойнайтын жерге көшіңіз: %s",
"horizon.friends.title": "Достармен ойнау",
"horizon.friends.hint": "Достар кодты тақырып экранындағы \"Достар\" түймесінен кейін, \"Тікелей қосылым\" бөліміне немесе іске қосу құралының \"Ойнату\" бетіне қояды.",
"horizon.friends.copied": "Көшірілген",
"horizon.friends.copy_code": "Кодты көшіру",
"horizon.friends.stop_sharing": "Бөлісуді тоқтату",
"horizon.friends.none_yet": "Бұл жерде әлі достар жоқ.",
"horizon.friends.here_now": "Мұнда қазір: %s",
"horizon.friends.share_intro": "Шақыру кодының артында осы әлемді бөлісіңіз: ол LAN желісіне ашылады және интернеттегі достар кодпен қосылады. Біздің серверіміз қатыспайды.",
"horizon.friends.start_sharing": "Бөлісуді бастау",
"horizon.friends.troubleshooting": "Ақаулықтарды жою...",
"horizon.friends.stopped": "Шақыру кодын бөлісуді тоқтатты.",
"horizon.friends.short_code_changed": "Біреу қате қысқа кодты қолданып көрді, сондықтан ол өзгерді.",
"horizon.friends.wrong_code": "Біреу қате кодты қолданып көрді.",
"horizon.friends.relay_stopped": "Қате қысқа кодтар тым көп болды, сондықтан сіз қайта бөліскенше реле өшірулі. Достар толық кодпен әлі де қосыла алады.",
"horizon.friends.code_ready": "Шақыру коды дайын: Ойын мәзірі, Достармен ойнау. Оны көшіріп, достарыңызға жіберіңіз.",
"horizon.friends.share_failed": "Әлемді бөлісу мүмкін болмады: %s",
"horizon.friends.finding_route": "Достар сізге қалай хабарласа алатынын анықтау...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Ғарыш",
"horizon.osk.delete": "Жою",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s ಅನ್ವಯಿಸಲು ಆಟವನ್ನು ಮರುಪ್ರಾರಂಭಿಸಿ: ಅವು ಬ್ಲಾಕ್‌ಗಳು, ವಸ್ತುಗಳು ಅಥವಾ ಜಗತ್ತಿನ ಉತ್ಪಾದನೆಯನ್ನು ಸೇರಿಸುತ್ತವೆ.",
"horizon.shader_options.profile": "ಪ್ರೊಫೈಲ್",
"horizon.agent.copy_details": "ಸಂಪರ್ಕ ವಿವರಗಳನ್ನು ನಕಲಿಸಿ",
"horizon.multiplayer.join": "ಸೇರಿಕೊಳ್ಳಿ",
"horizon.multiplayer.cancel_reconnecting": "ಮರುಸಂಪರ್ಕವನ್ನು ರದ್ದುಮಾಡಿ",
"horizon.multiplayer.join_friend": "ಸ್ನೇಹಿತನನ್ನು ಸೇರಿ",
"horizon.multiplayer.invite_code": "ಆಹ್ವಾನ ಕೋಡ್",
"horizon.multiplayer.relay": "ರಿಲೇ (ಐಚ್ಛಿಕ)",
"Preset": "ಮೊದಲೇ ಹೊಂದಿಸಲಾಗಿದೆ",
"LOD Distance": "LOD ದೂರ",
"Far Detail": "ದೂರದ ವಿವರ",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "ಆಫ್‌ಲೈನ್ ಪ್ರೊಫೈಲ್‌ಗಳು ಈ ನಿದರ್ಶನಕ್ಕೆ ಸೇರಿವೆ",
"horizon.splitscreen.profiles.move": "ನೀವು ಆಡುವ ಸ್ಥಳಕ್ಕೆ ಸರಿಸಿ",
"horizon.splitscreen.profiles.move_place": "ನೀವು ಆಡುವ ಸ್ಥಳಕ್ಕೆ ಸರಿಸಿ: %s",
"horizon.friends.title": "ಸ್ನೇಹಿತರೊಂದಿಗೆ ಆಟವಾಡಿ",
"horizon.friends.hint": "ಶೀರ್ಷಿಕೆ ಪರದೆಯ ಸ್ನೇಹಿತರ ಬಟನ್ ನಂತರ, ನೇರ ಸಂಪರ್ಕದಲ್ಲಿ ಅಥವಾ ಲಾಂಚರ್‌ನ ಪ್ಲೇ ಪುಟದಲ್ಲಿ ಸ್ನೇಹಿತರು ಕೋಡ್ ಅನ್ನು ಅಂಟಿಸಿ.",
"horizon.friends.copied": "ನಕಲು ಮಾಡಲಾಗಿದೆ",
"horizon.friends.copy_code": "ಕೋಡ್ ನಕಲಿಸಿ",
"horizon.friends.stop_sharing": "ಹಂಚಿಕೊಳ್ಳುವುದನ್ನು ನಿಲ್ಲಿಸಿ",
"horizon.friends.none_yet": "ಇಲ್ಲಿ ಇನ್ನೂ ಸ್ನೇಹಿತರಿಲ್ಲ.",
"horizon.friends.here_now": "ಇಲ್ಲಿ ಈಗ: %s",
"horizon.friends.share_intro": "ಆಹ್ವಾನ ಕೋಡ್‌ನ ಹಿಂದೆ ಈ ಜಗತ್ತನ್ನು ಹಂಚಿಕೊಳ್ಳಿ: ಇದು LAN ಗೆ ತೆರೆಯುತ್ತದೆ ಮತ್ತು ಇಂಟರ್ನೆಟ್‌ನಲ್ಲಿರುವ ಸ್ನೇಹಿತರು ಕೋಡ್‌ನೊಂದಿಗೆ ಸೇರಿಕೊಳ್ಳುತ್ತಾರೆ. ನಮ್ಮ ಯಾವುದೇ ಸರ್ವರ್ ಭಾಗಿಯಾಗಿಲ್ಲ.",
"horizon.friends.start_sharing": "ಹಂಚಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ",
"horizon.friends.troubleshooting": "ದೋಷನಿವಾರಣೆ...",
"horizon.friends.stopped": "ಆಹ್ವಾನ ಕೋಡ್ ಹಂಚಿಕೊಳ್ಳುವುದನ್ನು ನಿಲ್ಲಿಸಲಾಗಿದೆ.",
"horizon.friends.short_code_changed": "ಯಾರೋ ತಪ್ಪು ಶಾರ್ಟ್ ಕೋಡ್ ಅನ್ನು ಪ್ರಯತ್ನಿಸುತ್ತಲೇ ಇದ್ದಾರೆ, ಆದ್ದರಿಂದ ಅದು ಬದಲಾಗಿದೆ.",
"horizon.friends.wrong_code": "ಯಾರೋ ತಪ್ಪು ಕೋಡ್ ಅನ್ನು ಪ್ರಯತ್ನಿಸಿದ್ದಾರೆ.",
"horizon.friends.relay_stopped": "ತುಂಬಾ ತಪ್ಪು ಶಾರ್ಟ್ ಕೋಡ್‌ಗಳು, ಆದ್ದರಿಂದ ನೀವು ಮತ್ತೆ ಹಂಚಿಕೊಳ್ಳುವವರೆಗೆ ರಿಲೇ ಆಫ್ ಆಗಿದೆ. ಸ್ನೇಹಿತರು ಪೂರ್ಣ ಕೋಡ್‌ನಿಂದ ಇನ್ನೂ ಸೇರಬಹುದು.",
"horizon.friends.code_ready": "ನಿಮ್ಮ ಆಹ್ವಾನ ಕೋಡ್ ಸಿದ್ಧವಾಗಿದೆ: ಗೇಮ್ ಮೆನು, ಸ್ನೇಹಿತರೊಂದಿಗೆ ಆಟವಾಡಿ. ಅದನ್ನು ನಕಲಿಸಿ ಮತ್ತು ನಿಮ್ಮ ಸ್ನೇಹಿತರಿಗೆ ಕಳುಹಿಸಿ.",
"horizon.friends.share_failed": "ಜಗತ್ತನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ: %s",
"horizon.friends.finding_route": "ಸ್ನೇಹಿತರು ನಿಮ್ಮನ್ನು ಹೇಗೆ ತಲುಪಬಹುದು ಎಂಬುದನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ...",
"horizon.osk.shift": "ಶಿಫ್ಟ್",
"horizon.osk.space": "ಬಾಹ್ಯಾಕಾಶ",
"horizon.osk.delete": "ಅಳಿಸಿ",
@@ -238,7 +238,11 @@
"horizon.mods.open_folder": "모드 폴더 열기",
"horizon.shader_options.profile": "프로필",
"horizon.agent.copy_details": "연결 세부 정보 복사",
"horizon.multiplayer.join": "참가",
"horizon.multiplayer.cancel_reconnecting": "재연결 취소",
"horizon.multiplayer.join_friend": "친구 참가",
"horizon.multiplayer.invite_code": "초대 코드",
"horizon.multiplayer.relay": "릴레이 (선택 사항)",
"Preset": "프리셋",
"LOD Distance": "LOD 거리",
"Far Detail": "원거리 디테일",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "오프라인 프로필은 이 인스턴스에 속합니다.",
"horizon.splitscreen.profiles.move": "플레이 위치 이동",
"horizon.splitscreen.profiles.move_place": "플레이 위치 이동: %s",
"horizon.friends.title": "친구와 함께 플레이",
"horizon.friends.hint": "친구가 타이틀 화면의 친구 버튼, 직접 연결, 또는 런처의 플레이 페이지에서 코드를 입력합니다.",
"horizon.friends.copied": "복사됨",
"horizon.friends.copy_code": "코드 복사",
"horizon.friends.stop_sharing": "공유 중지",
"horizon.friends.none_yet": "아직 친구가 없습니다.",
"horizon.friends.here_now": "현재 접속 중: %s",
"horizon.friends.share_intro": "초대 코드를 통해 이 월드를 공유하세요: LAN으로 개방되며 인터넷상의 친구들이 코드로 참여할 수 있습니다. 당사의 서버는 개입하지 않습니다.",
"horizon.friends.start_sharing": "공유 시작",
"horizon.friends.troubleshooting": "문제 해결...",
"horizon.friends.stopped": "초대 코드 공유가 중지되었습니다.",
"horizon.friends.short_code_changed": "누군가 잘못된 짧은 코드를 계속 시도하여 코드가 변경되었습니다.",
"horizon.friends.wrong_code": "누군가 잘못된 코드를 입력했습니다.",
"horizon.friends.relay_stopped": "잘못된 짧은 코드가 너무 많아 다시 공유할 때까지 릴레이가 꺼집니다. 친구는 전체 코드로는 여전히 참가할 수 있습니다.",
"horizon.friends.code_ready": "초대 코드가 준비되었습니다: 게임 메뉴 - 친구와 함께 플레이. 코드를 복사하여 친구에게 보내세요.",
"horizon.friends.share_failed": "월드를 공유할 수 없습니다: %s",
"horizon.friends.finding_route": "친구가 접속할 수 있는 경로를 찾는 중...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "스페이스바",
"horizon.osk.delete": "삭제",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s колдонуу үчүн оюнду кайра баштаңыз: алар блокторду, буюмдарды же дүйнө генерациясын кошот.",
"horizon.shader_options.profile": "Профиль",
"horizon.agent.copy_details": "Туташуу чоо-жайын көчүрүү",
"horizon.multiplayer.join": "Кошулуу",
"horizon.multiplayer.cancel_reconnecting": "Кайра туташууну жокко чыгаруу",
"horizon.multiplayer.join_friend": "Доско кошулуңуз",
"horizon.multiplayer.invite_code": "Чакыруу коду",
"horizon.multiplayer.relay": "Реле (милдеттүү эмес)",
"Preset": "Алдын ала коюлган",
"LOD Distance": "LOD Дистанция",
"Far Detail": "Алыс деталь",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Оффлайн профилдери ушул инстанцияга таандык",
"horizon.splitscreen.profiles.move": "Кайда ойносоңуз, ошол жерге жылыңыз",
"horizon.splitscreen.profiles.move_place": "Ойногон жериңизди жылдырыңыз: %s",
"horizon.friends.title": "Достор менен ойно",
"horizon.friends.hint": "Достор кодду аталыш экранындагы \"Достор\" баскычынан кийин, Түз байланышта же ишке киргизгичтин Play бетине чапташат.",
"horizon.friends.copied": "Көчүрүлгөн",
"horizon.friends.copy_code": "Кодду көчүрүү",
"horizon.friends.stop_sharing": "Бөлүшүүнү токтотуу",
"horizon.friends.none_yet": "Бул жерде азырынча достор жок.",
"horizon.friends.here_now": "Бул жерде: %s",
"horizon.friends.share_intro": "Чакыруу кодунун артында бул дүйнөнү бөлүшүңүз: ал LANга ачылат жана интернеттеги достор код менен кошулат. Биздин эч кандай сервер катышпайт.",
"horizon.friends.start_sharing": "Бөлүшүүнү баштоо",
"horizon.friends.troubleshooting": "Көйгөйлөр аныкталууда...",
"horizon.friends.stopped": "Чакыруу кодун бөлүшүүнү токтотту.",
"horizon.friends.short_code_changed": "Кимдир бирөө туура эмес кыска кодду аракет кыла бергендиктен, ал өзгөрдү.",
"horizon.friends.wrong_code": "Кимдир бирөө туура эмес кодду аракет кылды.",
"horizon.friends.relay_stopped": "Туура эмес кыска коддор өтө көп болгондуктан, кайра бөлүшпөйүнчө реле өчүк. Достар толук код менен кошула алышат.",
"horizon.friends.code_ready": "Чакыруу коду даяр: Оюн менюсу, Достор менен ойноо. Аны көчүрүп, досторуңузга жөнөтүңүз.",
"horizon.friends.share_failed": "Дүйнөнү бөлүшө алган жок: %s",
"horizon.friends.finding_route": "Достор сиз менен кантип байланыша аларын издөө…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Космос",
"horizon.osk.delete": "Жок кылуу",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Ludum rursus incipe ut %s applices: caudices, res aut generationem mundi addunt.",
"horizon.shader_options.profile": "Profilum",
"horizon.agent.copy_details": "Exemplum Connection Details",
"horizon.multiplayer.join": "Iunge",
"horizon.multiplayer.cancel_reconnecting": "Reconiunctionem abrumpe",
"horizon.multiplayer.join_friend": "Iungere amico",
"horizon.multiplayer.invite_code": "invitare Code",
"horizon.multiplayer.relay": "Nullam (libitum)",
"Preset": "Praescriptum",
"LOD Distance": "D procul",
"Far Detail": "Absit Detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Online profiles pertinent ad hoc exempli gratia",
"horizon.splitscreen.profiles.move": "Movere quo ludere",
"horizon.splitscreen.profiles.move_place": "Movere quo ludo:%s",
"horizon.friends.title": "Ludere cum amicis",
"horizon.friends.hint": "Amici crustulum codicem post titulum screen scriptorum amici conjunctionem, in Direct Connection, vel in pagina Launculi Play.",
"horizon.friends.copied": "Exscriptum",
"horizon.friends.copy_code": "Exemplar Code",
"horizon.friends.stop_sharing": "Socius subsisto",
"horizon.friends.none_yet": "Nondum hic amici.",
"horizon.friends.here_now": "Hic nunc: %s",
"horizon.friends.share_intro": "Share hunc mundum post codicem invitare: aperit LAN, et amicos in interrete cum codice coniunge. Nullus cultor noster involvitur.",
"horizon.friends.start_sharing": "Satus Socius",
"horizon.friends.troubleshooting": "Fermentum...",
"horizon.friends.stopped": "Constitit invitare codicem communicantes.",
"horizon.friends.short_code_changed": "Perperam aliquis brevem codicem tentabat, sic mutavit.",
"horizon.friends.wrong_code": "Conatus codice aliquis iniuriam.",
"horizon.friends.relay_stopped": "Nimis multi codices breves falsi: relay exstinctum donec iterum communices. Amici tamen codice pleno iungere possunt.",
"horizon.friends.code_ready": "Codicem tuum invitare paratum est: Ludus Menu, lude cum amicis. Effingo eam et mitte amicis tuis.",
"horizon.friends.share_failed": "Non potuit communicare mundum:%s",
"horizon.friends.finding_route": "Invenire quomodo amici ad vos pervenire possunt…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Spatium",
"horizon.osk.delete": "Delere",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Start d'Spill nei, fir %s z'iwwerhuelen: si füüge Blocken, Objeten oder Weltgeneréierung dobäi.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopie Verbindung Detailer",
"horizon.multiplayer.join": "Maacht mat",
"horizon.multiplayer.cancel_reconnecting": "Ofbriechen Reconnecting",
"horizon.multiplayer.join_friend": "Maacht mat engem Frënd",
"horizon.multiplayer.invite_code": "Invitéieren Code",
"horizon.multiplayer.relay": "Relais (optional)",
"Preset": "Preset",
"LOD Distance": "LOD Distanz",
"Far Detail": "Wäit Detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline Profiler gehéieren zu dëser Instanz",
"horizon.splitscreen.profiles.move": "Beweegt wou Dir spillt",
"horizon.splitscreen.profiles.move_place": "Beweegt wou Dir spillt: %s",
"horizon.friends.title": "Spill mat Frënn",
"horizon.friends.hint": "Frënn Paste de Code nom Titelbildschierm Frënn Knäppchen, an Direct Connection, oder op der Play Säit vum Starter.",
"horizon.friends.copied": "Kopéiert",
"horizon.friends.copy_code": "Kopie Code",
"horizon.friends.stop_sharing": "Stop deelen",
"horizon.friends.none_yet": "Hei nach keng Frënn.",
"horizon.friends.here_now": "Hei elo: %s",
"horizon.friends.share_intro": "Deelt dës Welt hannert engem Invitatiounscode: et mécht op LAN op, a Frënn um Internet si mat dem Code verbonnen. Kee Server vun eis ass involvéiert.",
"horizon.friends.start_sharing": "Start Deelen",
"horizon.friends.troubleshooting": "Feelerbehandlung...",
"horizon.friends.stopped": "Huet opgehalen den Invitatiounscode ze deelen.",
"horizon.friends.short_code_changed": "Een huet ëmmer e falsche Kuerzcode probéiert, also huet et geännert.",
"horizon.friends.wrong_code": "Een huet e falsche Code probéiert.",
"horizon.friends.relay_stopped": "Ze vill falsch Kuerzcoden, dofir ass de Relais aus, bis Dir nees deelt. Frënn kënnen nach ëmmer mam vollen Code bäitrieden.",
"horizon.friends.code_ready": "Ären Invitatiounscode ass prett: Spillmenü, Spill mat Frënn. Kopéiert et a schéckt et un Är Frënn.",
"horizon.friends.share_failed": "Konnt d'Welt net deelen: %s",
"horizon.friends.finding_route": "Fannt wéi Frënn Iech erreechen ...",
"horizon.osk.shift": "Verréckelung",
"horizon.osk.space": "Raum",
"horizon.osk.delete": "Läschen",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Herstart ‘t spel um %s te laote wèrke: ze veuge blokke, veurwerpe of wereldgeneratie toe.",
"horizon.shader_options.profile": "Profiel",
"horizon.agent.copy_details": "Kopieer verbindingsdetails",
"horizon.multiplayer.join": "Sluit aan",
"horizon.multiplayer.cancel_reconnecting": "Herverbinding annulere",
"horizon.multiplayer.join_friend": "Doe dich aan bij un vrund",
"horizon.multiplayer.invite_code": "Uitnodigingscode",
"horizon.multiplayer.relay": "Relais (optioneel)",
"Preset": "Veurgestèld",
"LOD Distance": "LOD-aafstand",
"Far Detail": "Wied detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profiele behure tot dit exemplaar",
"horizon.splitscreen.profiles.move": "Verplaots boe geer speelt",
"horizon.splitscreen.profiles.move_place": "Verplaots boe geer speelt: %s",
"horizon.friends.title": "Speel mit vrun",
"horizon.friends.hint": "Vrun plak de code nao de Vriend knop op ‘t titelsjerm, in Directe Verbinding of op de Afspeelpagina vaan de launcher.",
"horizon.friends.copied": "Gekopieerd",
"horizon.friends.copy_code": "Kopiecode",
"horizon.friends.stop_sharing": "Stop mit deile",
"horizon.friends.none_yet": "Heej nog gein vrun.",
"horizon.friends.here_now": "Hei noe: %s",
"horizon.friends.share_intro": "Deil deze wereld achter ‘n oetnodigingscode: ‘t geit open veur LAN, en vrun op ‘t internet gaon mit de code. Gein server vaan ós is betrokke.",
"horizon.friends.start_sharing": "Begin mit deile",
"horizon.friends.troubleshooting": "Probleemoplossinge...",
"horizon.friends.stopped": "Is gestop mit ‘t deile vaan de oetnodigingscode.",
"horizon.friends.short_code_changed": "Iemes bleef ‘n verkierde korte code probere, dus ‘t veranderde.",
"horizon.friends.wrong_code": "Iemes heet ‘n verkeerde code geprobeerd.",
"horizon.friends.relay_stopped": "Te väöl verkierde korte codes, dus de relais steit oet totdat se weer deils. Vrun kinne nog ummer mit de volledige code binnekómme.",
"horizon.friends.code_ready": "Uw oetnodigingscode is klaor: Spelmenu, Speel mit vrun. Kopieer ‘t en sjik ‘t nao dien vrun.",
"horizon.friends.share_failed": "Kon de wereld neet deile: %s",
"horizon.friends.finding_route": "Zoe wie vrun dich kinne bereike…",
"horizon.osk.shift": "Verschuiving",
"horizon.osk.space": "Ruimte",
"horizon.osk.delete": "Wisse",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinizia el giœugh per aplicà %s: i giuntan blocch, oggett o generaziun del mund.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Copia i detai de la cunnesiun",
"horizon.multiplayer.join": "Partecipa",
"horizon.multiplayer.cancel_reconnecting": "Annulla la riconnession",
"horizon.multiplayer.join_friend": "Unis-te a un amig",
"horizon.multiplayer.invite_code": "Codex de l'invito",
"horizon.multiplayer.relay": "Relè (facultatif)",
"Preset": "Preimpostad",
"LOD Distance": "Distanza LOD",
"Far Detail": "Detagli luntan",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "I profil fœura linea fan part de chesta istanza",
"horizon.splitscreen.profiles.move": "Spusta indué giœghet",
"horizon.splitscreen.profiles.move_place": "Spusta indué giœghet: %s",
"horizon.friends.title": "Giœgar cunt i amì",
"horizon.friends.hint": "I amis incollan el codes dopu el buttun Amis de la scherma del titul, en Cunnession diretta o sü la pagina Play del lanciador.",
"horizon.friends.copied": "Copià",
"horizon.friends.copy_code": "Codèss de copia",
"horizon.friends.stop_sharing": "Ferma de condivider",
"horizon.friends.none_yet": "Ancamò nissun amis chi.",
"horizon.friends.here_now": "Qui adess: %s",
"horizon.friends.share_intro": "Condividi chestu mund deré a un codes de invito: se derva a la LAN e i amis sü Internet se unisen cunt el codes. Nissun noster server l’è coinvolt.",
"horizon.friends.start_sharing": "Cumincià a condivider",
"horizon.friends.troubleshooting": "Risoluziun di prublem...",
"horizon.friends.stopped": "Fermà de condivider el codèss de invito.",
"horizon.friends.short_code_changed": "Quaivun g’ha continuà a pruvar un codes curt sbajaa, inscì l’è cambià.",
"horizon.friends.wrong_code": "Quaivun g’ha pruvà un codes sbajaa.",
"horizon.friends.relay_stopped": "Trope codes curt sbajaa, donca el relè l'è spent fin quand te condividet ancamò. I amis pœden entrà ancamò cunt el codes cumplet.",
"horizon.friends.code_ready": "El tò codes de invito l’è pront: Menu del giœugh, Giœugh cunt i amì. Copia-la e manda-la ai tò amis.",
"horizon.friends.share_failed": "Pudeva minga cundivider el mund: %s",
"horizon.friends.finding_route": "Truvà cuma i amis pœden rivà a ti...",
"horizon.osk.shift": "Maiusc",
"horizon.osk.space": "Spazi",
"horizon.osk.delete": "Eliminar",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "ຣີສະຕາດເກມເພື່ອນຳໃຊ້ %s: ພວກມັນເພີ່ມບຼັອກ, ສິ່ງຂອງ ຫຼື ການສ້າງໂລກ.",
"horizon.shader_options.profile": "ໂປຣໄຟລ໌",
"horizon.agent.copy_details": "ສຳເນົາລາຍລະອຽດການເຊື່ອມຕໍ່",
"horizon.multiplayer.join": "ເຂົ້າຮ່ວມ",
"horizon.multiplayer.cancel_reconnecting": "ຍົກເລີກການເຊື່ອມຕໍ່ຄືນໃໝ່",
"horizon.multiplayer.join_friend": "ເຂົ້າຮ່ວມເພື່ອນ",
"horizon.multiplayer.invite_code": "ລະຫັດເຊີນ",
"horizon.multiplayer.relay": "Relay (ທາງເລືອກ)",
"Preset": "ຕັ້ງໄວ້ລ່ວງໜ້າ",
"LOD Distance": "LOD ໄລຍະທາງ",
"Far Detail": "ລາຍລະອຽດໄກ",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "ໂປຣໄຟລ໌ອອບລາຍເປັນຂອງຕົວຢ່າງນີ້",
"horizon.splitscreen.profiles.move": "ຍ້າຍບ່ອນທີ່ທ່ານຫຼິ້ນ",
"horizon.splitscreen.profiles.move_place": "ຍ້າຍບ່ອນທີ່ທ່ານຫຼິ້ນ: %s",
"horizon.friends.title": "ຫຼິ້ນກັບຫມູ່ເພື່ອນ",
"horizon.friends.hint": "ໝູ່ວາງລະຫັດຫຼັງຈາກປຸ່ມໝູ່ຂອງໜ້າຈໍຫົວຂໍ້, ໃນການເຊື່ອມຕໍ່ໂດຍກົງ, ຫຼືໃນໜ້າຫຼິ້ນຂອງຕົວເປີດໃຊ້.",
"horizon.friends.copied": "ສຳເນົາແລ້ວ",
"horizon.friends.copy_code": "ສຳເນົາລະຫັດ",
"horizon.friends.stop_sharing": "ຢຸດການແບ່ງປັນ",
"horizon.friends.none_yet": "ບໍ່ມີໝູ່ຢູ່ບ່ອນນີ້ເທື່ອ.",
"horizon.friends.here_now": "ດຽວນີ້: %s",
"horizon.friends.share_intro": "ແບ່ງປັນໂລກນີ້ຢູ່ເບື້ອງຫຼັງລະຫັດເຊີນ: ມັນເປີດຢູ່ໃນ LAN, ແລະຫມູ່ເພື່ອນໃນອິນເຕີເນັດເຂົ້າຮ່ວມກັບລະຫັດ. ບໍ່ມີເຄື່ອງແມ່ຂ່າຍຂອງພວກເຮົາມີສ່ວນຮ່ວມ.",
"horizon.friends.start_sharing": "ເລີ່ມການແບ່ງປັນ",
"horizon.friends.troubleshooting": "ການແກ້ໄຂບັນຫາ...",
"horizon.friends.stopped": "ຢຸດການແບ່ງປັນລະຫັດເຊີນແລ້ວ.",
"horizon.friends.short_code_changed": "ມີຄົນພະຍາຍາມໃຊ້ລະຫັດສັ້ນຜິດ, ສະນັ້ນມັນຈຶ່ງປ່ຽນໄປ.",
"horizon.friends.wrong_code": "ມີຄົນພະຍາຍາມລະຫັດຜິດ.",
"horizon.friends.relay_stopped": "ລະຫັດສັ້ນຜິດຫຼາຍເກີນໄປ, ດັ່ງນັ້ນ relay ຈຶ່ງປິດຈົນກວ່າທ່ານຈະແບ່ງປັນອີກຄັ້ງ. ໝູ່ເພື່ອນຍັງສາມາດເຂົ້າຮ່ວມດ້ວຍລະຫັດເຕັມໄດ້.",
"horizon.friends.code_ready": "ລະຫັດເຊີນຂອງທ່ານພ້ອມແລ້ວ: ເມນູເກມ, ຫຼິ້ນກັບໝູ່. ຄັດລອກມັນແລະສົ່ງໃຫ້ຫມູ່ເພື່ອນຂອງທ່ານ.",
"horizon.friends.share_failed": "ບໍ່ສາມາດແບ່ງປັນໂລກໄດ້: %s",
"horizon.friends.finding_route": "ຊອກຫາວິທີທີ່ໝູ່ສາມາດເຂົ້າຫາທ່ານ...",
"horizon.osk.shift": "ເລື່ອນ",
"horizon.osk.space": "ຊ່ອງ",
"horizon.osk.delete": "ລຶບ",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Paleiskite žaidimą iš naujo, kad pritaikytumėte %s: jie prideda blokų, daiktų ar pasaulio generavimą.",
"horizon.shader_options.profile": "Profilis",
"horizon.agent.copy_details": "Nukopijuokite ryšio informaciją",
"horizon.multiplayer.join": "Prisijunk",
"horizon.multiplayer.cancel_reconnecting": "Atšaukti prisijungimą iš naujo",
"horizon.multiplayer.join_friend": "Prisijunk prie draugo",
"horizon.multiplayer.invite_code": "Kvietimo kodas",
"horizon.multiplayer.relay": "Relė (neprivaloma)",
"Preset": "Iš anksto nustatytas",
"LOD Distance": "LOD atstumas",
"Far Detail": "Tolima detalė",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Šiam atvejui priklauso profiliai neprisijungus",
"horizon.splitscreen.profiles.move": "Perkelkite ten, kur žaidžiate",
"horizon.splitscreen.profiles.move_place": "Perkelkite ten, kur žaidžiate: %s",
"horizon.friends.title": "Žaisk su draugais",
"horizon.friends.hint": "Draugai įklijuoja kodą po pavadinimo ekrano mygtuko „Draugai“, tiesioginiame prisijungime arba paleidimo priemonės „Play“ puslapyje.",
"horizon.friends.copied": "Nukopijuota",
"horizon.friends.copy_code": "Kopijuoti kodą",
"horizon.friends.stop_sharing": "Sustabdyti bendrinimą",
"horizon.friends.none_yet": "Draugų čia dar nėra.",
"horizon.friends.here_now": "Čia dabar: %s",
"horizon.friends.share_intro": "Bendrinkite šį pasaulį naudodami kvietimo kodą: jis atidaromas LAN, o draugai internete prisijungia naudodami kodą. Joks mūsų serveris nedalyvauja.",
"horizon.friends.start_sharing": "Pradėti bendrinti",
"horizon.friends.troubleshooting": "Trikčių šalinimas...",
"horizon.friends.stopped": "Nustojo bendrinti kvietimo kodą.",
"horizon.friends.short_code_changed": "Kažkas vis bandė neteisingą trumpąjį kodą, todėl jis pasikeitė.",
"horizon.friends.wrong_code": "Kažkas bandė neteisingą kodą.",
"horizon.friends.relay_stopped": "Per daug neteisingų trumpųjų kodų, todėl relė išjungta, kol vėl bendrinsite. Draugai vis tiek gali prisijungti su visu kodu.",
"horizon.friends.code_ready": "Jūsų kvietimo kodas paruoštas: žaidimų meniu, žaiskite su draugais. Nukopijuokite ir nusiųskite draugams.",
"horizon.friends.share_failed": "Nepavyko pasidalinti pasauliu: %s",
"horizon.friends.finding_route": "Sužinokite, kaip draugai gali su jumis susisiekti…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Erdvė",
"horizon.osk.delete": "Ištrinti",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Restartējiet spēli, lai piemērotu %s: tie pievieno blokus, priekšmetus vai pasaules ģenerēšanu.",
"horizon.shader_options.profile": "Profils",
"horizon.agent.copy_details": "Kopējiet savienojuma informāciju",
"horizon.multiplayer.join": "Pievienojieties",
"horizon.multiplayer.cancel_reconnecting": "Atcelt savienojuma atjaunošanu",
"horizon.multiplayer.join_friend": "Pievienojieties draugam",
"horizon.multiplayer.invite_code": "Uzaicinājuma kods",
"horizon.multiplayer.relay": "Relejs (pēc izvēles)",
"Preset": "Iepriekš iestatīts",
"LOD Distance": "LOD attālums",
"Far Detail": "Tāla detaļa",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Šai instancei pieder bezsaistes profili",
"horizon.splitscreen.profiles.move": "Pārvietojieties, kur spēlējat",
"horizon.splitscreen.profiles.move_place": "Pārvietojieties, kur spēlējat: %s",
"horizon.friends.title": "Spēlējiet ar draugiem",
"horizon.friends.hint": "Draugi ielīmē kodu aiz virsraksta ekrāna pogas Draugi, tiešajā savienojumā vai palaišanas programmas Play lapā.",
"horizon.friends.copied": "Kopēts",
"horizon.friends.copy_code": "Kopēt kodu",
"horizon.friends.stop_sharing": "Pārtraukt kopīgošanu",
"horizon.friends.none_yet": "Šeit vēl nav draugu.",
"horizon.friends.here_now": "Šeit tagad: %s",
"horizon.friends.share_intro": "Kopīgojiet šo pasauli aiz uzaicinājuma koda: tā tiek atvērta LAN, un draugi internetā pievienojas ar kodu. Neviens mūsu serveris nav iesaistīts.",
"horizon.friends.start_sharing": "Sāciet kopīgot",
"horizon.friends.troubleshooting": "Problēmu novēršana...",
"horizon.friends.stopped": "Uzaicinājuma koda kopīgošana tika pārtraukta.",
"horizon.friends.short_code_changed": "Kāds turpināja mēģināt ievadīt nepareizu īso kodu, tāpēc tas mainījās.",
"horizon.friends.wrong_code": "Kāds mēģināja ievadīt nepareizu kodu.",
"horizon.friends.relay_stopped": "Pārāk daudz nepareizu īso kodu, tāpēc relejs ir izslēgts, līdz kopīgojat vēlreiz. Draugi joprojām var pievienoties ar pilnu kodu.",
"horizon.friends.code_ready": "Jūsu ielūguma kods ir gatavs: Spēļu izvēlne, Spēlējiet ar draugiem. Kopējiet to un nosūtiet draugiem.",
"horizon.friends.share_failed": "Nevarēja kopīgot pasauli: %s",
"horizon.friends.finding_route": "Noskaidro, kā draugi var ar jums sazināties…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Kosmoss",
"horizon.osk.delete": "Dzēst",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Рестартирајте ја играта за да се примени %s: тие додаваат блокови, предмети или генерирање на свет.",
"horizon.shader_options.profile": "Профил",
"horizon.agent.copy_details": "Копирај ги деталите за поврзување",
"horizon.multiplayer.join": "Приклучи се",
"horizon.multiplayer.cancel_reconnecting": "Откажи повторно поврзување",
"horizon.multiplayer.join_friend": "Придружете се на пријател",
"horizon.multiplayer.invite_code": "Код за покана",
"horizon.multiplayer.relay": "Реле (опционално)",
"Preset": "Претходно поставено",
"LOD Distance": "LOD далечина",
"Far Detail": "Далечни детали",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлајн профилите припаѓаат на овој пример",
"horizon.splitscreen.profiles.move": "Движете се каде што играте",
"horizon.splitscreen.profiles.move_place": "Преместете се каде што играте: %s",
"horizon.friends.title": "Играјте со пријателите",
"horizon.friends.hint": "Пријателите го залепуваат кодот по копчето Пријатели на насловниот екран, во Директна врска или на страницата Play на стартерот.",
"horizon.friends.copied": "Копирано",
"horizon.friends.copy_code": "Копирај код",
"horizon.friends.stop_sharing": "Стоп за споделување",
"horizon.friends.none_yet": "Сè уште нема пријатели овде.",
"horizon.friends.here_now": "Еве сега: %s",
"horizon.friends.share_intro": "Споделете го овој свет зад кодот за покана: се отвора на LAN и пријателите на интернет се придружуваат со кодот. Ниту еден наш сервер не е вклучен.",
"horizon.friends.start_sharing": "Започнете со споделување",
"horizon.friends.troubleshooting": "Решавање проблеми...",
"horizon.friends.stopped": "Престана да го споделува кодот за покана.",
"horizon.friends.short_code_changed": "Некој постојано пробуваше погрешен краток код, па се смени.",
"horizon.friends.wrong_code": "Некој пробал погрешен код.",
"horizon.friends.relay_stopped": "Премногу погрешни кратки кодови, па релето е исклучено додека повторно не споделите. Пријателите сепак можат да се приклучат со целосниот код.",
"horizon.friends.code_ready": "Вашиот код за покана е подготвен: Мени за игра, Играјте со пријателите. Копирајте го и испратете го на вашите пријатели.",
"horizon.friends.share_failed": "Не можев да го споделам светот: %s",
"horizon.friends.finding_route": "Откривате како пријателите можат да дојдат до вас…",
"horizon.osk.shift": "Смена",
"horizon.osk.space": "Простор",
"horizon.osk.delete": "Избриши",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "%s-г хэрэглэхийн тулд тоглоомыг дахин эхлүүлнэ: тэд блок, зүйл эсвэл дэлхий үүсгэлт нэмдэг.",
"horizon.shader_options.profile": "Профайл",
"horizon.agent.copy_details": "Холболтын мэдээллийг хуулах",
"horizon.multiplayer.join": "Нэгдэх",
"horizon.multiplayer.cancel_reconnecting": "Дахин холбогдохыг цуцлах",
"horizon.multiplayer.join_friend": "Найзтайгаа нэгдээрэй",
"horizon.multiplayer.invite_code": "Урилгын код",
"horizon.multiplayer.relay": "Реле (заавал биш)",
"Preset": "Урьдчилан тохируулсан",
"LOD Distance": "LOD зай",
"Far Detail": "Алс дэлгэрэнгүй",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профайл нь энэ жишээнд хамаарна",
"horizon.splitscreen.profiles.move": "Тоглож буй газраа нүү",
"horizon.splitscreen.profiles.move_place": "Тоглож буй газраа шилжүүлээрэй: %s",
"horizon.friends.title": "Найзуудтайгаа тогло",
"horizon.friends.hint": "Найзууд кодыг гарчгийн дэлгэцийн \"Найзууд\" товчны ард, \"Шууд холболт\" хэсэгт эсвэл эхлүүлэгчийн Play хуудсанд оруулна.",
"horizon.friends.copied": "Хуулсан",
"horizon.friends.copy_code": "Код хуулах",
"horizon.friends.stop_sharing": "Хуваалцахаа зогсоо",
"horizon.friends.none_yet": "Одоохондоо энд найз алга.",
"horizon.friends.here_now": "Одоо энд: %s",
"horizon.friends.share_intro": "Урилгын кодын ард энэ ертөнцийг хуваалцаарай: энэ нь LAN-д нээгдэж, интернетэд байгаа найзууд кодоор нэгдэнэ. Манай сервер оролцдоггүй.",
"horizon.friends.start_sharing": "Хуваалцаж эхлэх",
"horizon.friends.troubleshooting": "Алдааг олж засварлаж байна...",
"horizon.friends.stopped": "Урилгын кодыг хуваалцахаа больсон.",
"horizon.friends.short_code_changed": "Хэн нэгэн буруу богино код оролдсоор байгаад өөрчлөгдсөн.",
"horizon.friends.wrong_code": "Хэн нэгэн буруу код оролдсон байна.",
"horizon.friends.relay_stopped": "Хэт олон буруу богино код оруулсан тул дахин хуваалцах хүртэл реле унтарсан. Найзууд бүтэн кодоор орж болно.",
"horizon.friends.code_ready": "Таны урилгын код бэлэн боллоо: Тоглоомын цэс, Найзуудтайгаа тогло. Үүнийг хуулж аваад найзууддаа илгээнэ үү.",
"horizon.friends.share_failed": "Дэлхийг хуваалцаж чадсангүй: %s",
"horizon.friends.finding_route": "Найзууд тантай хэрхэн холбогдож болохыг хайж байна...",
"horizon.osk.shift": "Шилжилт",
"horizon.osk.space": "Орон зай",
"horizon.osk.delete": "Устгах",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Mulakan semula permainan untuk menggunakan %s: ia menambah blok, item atau penjanaan dunia.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Salin Butiran Sambungan",
"horizon.multiplayer.join": "Sertai",
"horizon.multiplayer.cancel_reconnecting": "Batalkan Penyambungan Semula",
"horizon.multiplayer.join_friend": "Sertai Rakan",
"horizon.multiplayer.invite_code": "Kod Jemputan",
"horizon.multiplayer.relay": "Relay (pilihan)",
"Preset": "Pratetap",
"LOD Distance": "Jarak LOD",
"Far Detail": "Perincian Jauh",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Profil luar talian tergolong dalam contoh ini",
"horizon.splitscreen.profiles.move": "Bergerak ke tempat anda bermain",
"horizon.splitscreen.profiles.move_place": "Bergerak ke tempat anda bermain: %s",
"horizon.friends.title": "Bermain dengan Kawan",
"horizon.friends.hint": "Rakan tampal kod selepas butang Rakan skrin tajuk, dalam Sambungan Terus atau pada halaman Main pelancar.",
"horizon.friends.copied": "disalin",
"horizon.friends.copy_code": "Salin Kod",
"horizon.friends.stop_sharing": "Berhenti Berkongsi",
"horizon.friends.none_yet": "Belum ada kawan di sini.",
"horizon.friends.here_now": "Di sini sekarang: %s",
"horizon.friends.share_intro": "Kongsi dunia ini di sebalik kod jemputan: ia dibuka kepada LAN, dan rakan di Internet menyertai kod tersebut. Tiada pelayan kami terlibat.",
"horizon.friends.start_sharing": "Mula Berkongsi",
"horizon.friends.troubleshooting": "Menyelesaikan masalah...",
"horizon.friends.stopped": "Berhenti berkongsi kod jemputan.",
"horizon.friends.short_code_changed": "Seseorang terus mencuba kod pendek yang salah, jadi ia berubah.",
"horizon.friends.wrong_code": "Seseorang mencuba kod yang salah.",
"horizon.friends.relay_stopped": "Terlalu banyak kod pendek yang salah, jadi geganti dimatikan sehingga anda berkongsi semula. Rakan masih boleh menyertai dengan kod penuh.",
"horizon.friends.code_ready": "Kod jemputan anda sudah sedia: Menu Permainan, Main dengan Rakan. Salin dan hantar kepada rakan anda.",
"horizon.friends.share_failed": "Tidak dapat berkongsi dunia: %s",
"horizon.friends.finding_route": "Mencari cara rakan boleh menghubungi anda…",
"horizon.osk.shift": "Beralih",
"horizon.osk.space": "Angkasa",
"horizon.osk.delete": "Padam",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Erġa' ibda l-logħba biex tapplika %s: iżidu blokki, oġġetti jew ġenerazzjoni tad-dinja.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Ikkopja Dettalji tal-Konnessjoni",
"horizon.multiplayer.join": "Ingħaqad",
"horizon.multiplayer.cancel_reconnecting": "Ikkanċella l-Konnessjoni mill-ġdid",
"horizon.multiplayer.join_friend": "Ingħaqad ma' Ħabib",
"horizon.multiplayer.invite_code": "Stieden Kodiċi",
"horizon.multiplayer.relay": "Relay (mhux obbligatorju)",
"Preset": "Issettjati minn qabel",
"LOD Distance": "LOD Distanza",
"Far Detail": "Imbiegħed Dettall",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Il-profili offline jappartjenu għal din l-istanza",
"horizon.splitscreen.profiles.move": "Imxi fejn tilgħab",
"horizon.splitscreen.profiles.move_place": "Ċaqlaq fejn tilgħab: %s",
"horizon.friends.title": "Ilgħab mal-Ħbieb",
"horizon.friends.hint": "Ħbieb waħħal il-kodiċi wara l-buttuna Ħbieb tal-iskrin tat-titlu, f'Konnessjoni Diretta, jew fuq il-paġna Play tal-lanċjar.",
"horizon.friends.copied": "Ikkopjati",
"horizon.friends.copy_code": "Kopja tal-Kodiċi",
"horizon.friends.stop_sharing": "Waqqaf il-Qsim",
"horizon.friends.none_yet": "Għadu m'hemmx ħbieb hawn.",
"horizon.friends.here_now": "Hawnhekk issa: %s",
"horizon.friends.share_intro": "Aqsam din id-dinja wara kodiċi tal-istedina: tiftaħ għal LAN, u ħbieb fuq l-internet jingħaqdu mal-kodiċi. L-ebda server tagħna mhu involut.",
"horizon.friends.start_sharing": "Ibda taqsam",
"horizon.friends.troubleshooting": "Issolvi l-problemi...",
"horizon.friends.stopped": "Waqaf taqsam il-kodiċi tal-istedina.",
"horizon.friends.short_code_changed": "Xi ħadd baqa' jipprova kodiċi qasir ħażin, għalhekk inbidel.",
"horizon.friends.wrong_code": "Xi ħadd ipprova kodiċi ħażin.",
"horizon.friends.relay_stopped": "Wisq kodiċi qosra ħżiena, għalhekk ir-relay huwa mitfi sakemm terġa' taqsam. Il-ħbieb xorta jistgħu jingħaqdu bil-kodiċi sħiħ.",
"horizon.friends.code_ready": "Il-kodiċi tal-istedina tiegħek lest: Menu tal-Logħba, Ilgħab mal-Ħbieb. Ikkopjaha u ibgħatha lill-ħbieb tiegħek.",
"horizon.friends.share_failed": "Ma setgħetx naqsam id-dinja: %s",
"horizon.friends.finding_route": "Issib kif il-ħbieb jistgħu jilħquk...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "L-ispazju",
"horizon.osk.delete": "Ħassar",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Herstart het spel om %s toe te passen: ze voegen blokken, items of wereldgeneratie toe.",
"horizon.shader_options.profile": "Profiel",
"horizon.agent.copy_details": "Kopieer verbindingsgegevens",
"horizon.multiplayer.join": "Doe mee",
"horizon.multiplayer.cancel_reconnecting": "Annuleren Opnieuw verbinden",
"horizon.multiplayer.join_friend": "Sluit je aan bij een vriend",
"horizon.multiplayer.invite_code": "Uitnodigingscode",
"horizon.multiplayer.relay": "relais (optioneel)",
"Preset": "Voorinstelling",
"LOD Distance": "LOD-afstand",
"Far Detail": "Verre details",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profielen behoren tot deze instantie",
"horizon.splitscreen.profiles.move": "Verplaats waar je speelt",
"horizon.splitscreen.profiles.move_place": "Verplaatsen waar je speelt: %s",
"horizon.friends.title": "Speel met vrienden",
"horizon.friends.hint": "Vrienden plakken de code na de knop Vrienden in het titelscherm, in Directe verbinding of op de Play-pagina van het opstartprogramma.",
"horizon.friends.copied": "Gekopieerd",
"horizon.friends.copy_code": "Kopieer code",
"horizon.friends.stop_sharing": "Stop met delen",
"horizon.friends.none_yet": "Nog geen vrienden hier.",
"horizon.friends.here_now": "Hier nu: %s",
"horizon.friends.share_intro": "Deel deze wereld achter een uitnodigingscode: deze wordt geopend voor LAN en vrienden op internet doen mee met de code. Er is geen server van ons bij betrokken.",
"horizon.friends.start_sharing": "Begin met delen",
"horizon.friends.troubleshooting": "Problemen oplossen...",
"horizon.friends.stopped": "Het delen van de uitnodigingscode is gestopt.",
"horizon.friends.short_code_changed": "Iemand probeerde steeds een verkeerde shortcode, dus het veranderde.",
"horizon.friends.wrong_code": "Iemand heeft een verkeerde code geprobeerd.",
"horizon.friends.relay_stopped": "Te veel verkeerde shortcodes, dus het relais staat uit tot je opnieuw deelt. Vrienden kunnen nog steeds met de volledige code meedoen.",
"horizon.friends.code_ready": "Je uitnodigingscode is klaar: Gamemenu, Spelen met vrienden. Kopieer het en stuur het naar je vrienden.",
"horizon.friends.share_failed": "Kon de wereld niet delen: %s",
"horizon.friends.finding_route": "Ontdek hoe vrienden u kunnen bereiken...",
"horizon.osk.shift": "Verschuiving",
"horizon.osk.space": "Ruimte",
"horizon.osk.delete": "Verwijderen",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Start spillet på nytt for å bruke %s: de legger til blokker, gjenstander eller verdensgenerering.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopier tilkoblingsdetaljer",
"horizon.multiplayer.join": "Bli med",
"horizon.multiplayer.cancel_reconnecting": "Avbryt tilkobling på nytt",
"horizon.multiplayer.join_friend": "Bli med en venn",
"horizon.multiplayer.invite_code": "Invitasjonskode",
"horizon.multiplayer.relay": "Relé (valgfritt)",
"Preset": "Forhåndsinnstilt",
"LOD Distance": "LOD Avstand",
"Far Detail": "Langt detalj",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Frakoblede profiler tilhører denne forekomsten",
"horizon.splitscreen.profiles.move": "Flytt dit du spiller",
"horizon.splitscreen.profiles.move_place": "Flytt dit du spiller: %s",
"horizon.friends.title": "Spill med venner",
"horizon.friends.hint": "Venner limer inn koden etter tittelskjermens Venner-knapp, i Direct Connection eller på startprogrammets Play-side.",
"horizon.friends.copied": "Kopiert",
"horizon.friends.copy_code": "Kopier kode",
"horizon.friends.stop_sharing": "Slutt å dele",
"horizon.friends.none_yet": "Ingen venner her ennå.",
"horizon.friends.here_now": "Her nå: %s",
"horizon.friends.share_intro": "Del denne verden bak en invitasjonskode: den åpnes til LAN, og venner på internett blir med med koden. Ingen server av oss er involvert.",
"horizon.friends.start_sharing": "Begynn å dele",
"horizon.friends.troubleshooting": "Feilsøking...",
"horizon.friends.stopped": "Sluttet å dele invitasjonskoden.",
"horizon.friends.short_code_changed": "Noen fortsatte å prøve en feil kort kode, så den endret seg.",
"horizon.friends.wrong_code": "Noen prøvde feil kode.",
"horizon.friends.relay_stopped": "For mange feil korte koder, så reléet er av til du deler på nytt. Venner kan fortsatt bli med med den fulle koden.",
"horizon.friends.code_ready": "Invitasjonskoden din er klar: Spillmeny, Spill med venner. Kopier den og send den til vennene dine.",
"horizon.friends.share_failed": "Kunne ikke dele verden: %s",
"horizon.friends.finding_route": "Finner hvordan venner kan nå deg …",
"horizon.osk.shift": "Skift",
"horizon.osk.space": "Plass",
"horizon.osk.delete": "Slett",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reaviatz lo jòc per aplicar %s : apondon de blòts, d'objèctes o de generacion del mond.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copiar los detalhs de connexion",
"horizon.multiplayer.join": "Inscrivètz-vos",
"horizon.multiplayer.cancel_reconnecting": "Anullar la reconnexion",
"horizon.multiplayer.join_friend": "Rejonhètz un amic",
"horizon.multiplayer.invite_code": "Còde d'invitacion",
"horizon.multiplayer.relay": "Relè (facultatiu)",
"Preset": "Predefinit",
"LOD Distance": "Distància LOD",
"Far Detail": "Detalh luènh",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Los perfils fòra linha apartenon a aquesta instància",
"horizon.splitscreen.profiles.move": "Desplaçatz-vos ont jògatz",
"horizon.splitscreen.profiles.move_place": "Desplaçatz-vos ont jògatz: %s",
"horizon.friends.title": "Jugar amb los amics",
"horizon.friends.hint": "Los amics pegan lo còde après lo boton Amics de l'ecran de títol, dins la connexion dirècta, o sus la pagina de reproduccion del lançaire.",
"horizon.friends.copied": "Copiat",
"horizon.friends.copy_code": "Còde de còpia",
"horizon.friends.stop_sharing": "Arrèsta de partejar",
"horizon.friends.none_yet": "Pas d'amics aicí encara.",
"horizon.friends.here_now": "Aquí ara: %s",
"horizon.friends.share_intro": "Partejatz aquel mond darrièr un còde d'invitacion: se dobrís sus la LAN, e los amics sus internet se jonhon amb lo còde. Cap de servidor nòstre es pas implicat.",
"horizon.friends.start_sharing": "Començatz de partejar",
"horizon.friends.troubleshooting": "Resolucion de problèmas...",
"horizon.friends.stopped": "Arrestat de partejar lo còde d'invitacion.",
"horizon.friends.short_code_changed": "Qualqu'un contunhèt d'ensajar un còde cort incorrècte, alara cambièt.",
"horizon.friends.wrong_code": "Qualqu'un a ensajat un còde incorrècte.",
"horizon.friends.relay_stopped": "Tròp de còdes corts erronèus, doncas lo relais es desactivat fins que partejatz de nòu. Los amics pòdon encara rejónher amb lo còde complet.",
"horizon.friends.code_ready": "Vòstre còde d'invitacion es prèst: Menut de jòc, Jogar amb d'amics. Copiatz-lo e mandatz-lo a vòstres amics.",
"horizon.friends.share_failed": "Poguèt pas partejar lo mond: %s",
"horizon.friends.finding_route": "Trobar cossí los amics pòdon vos contactar...",
"horizon.osk.shift": "Desplaçar",
"horizon.osk.space": "Espaci",
"horizon.osk.delete": "Suprimir",
@@ -209,7 +209,11 @@
"horizon.mods.switch.restart": "Uruchom grę ponownie, aby zastosować %s: dodają bloki, przedmioty lub generowanie świata.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopiuj dane połączenia",
"horizon.multiplayer.join": "Dołącz",
"horizon.multiplayer.cancel_reconnecting": "Anuluj ponowne łączenie",
"horizon.multiplayer.join_friend": "Dołącz do znajomego",
"horizon.multiplayer.invite_code": "Kod zaproszenia",
"horizon.multiplayer.relay": "Przekaźnik (opcjonalnie)",
"Preset": "Profil",
"LOD Distance": "Zasięg LOD",
"Far Detail": "Dalekie detale",
@@ -296,6 +300,7 @@
"horizon.extras.wheel_cycles_settings": "Kółko zmienia ustawienia",
"horizon.extras.pack_browser": "Przeglądarka paczek zasobów",
"horizon.extras.music_page.tooltip": "Muzyka i dźwięki zyskują stronę Muzyka…: odtwórz dowolną wbudowaną ścieżkę teraz lub wyłącz którąś, by gra przestała ją wybierać. Nic się nie zmienia, dopóki nie wyłączysz ścieżki.",
"horizon.friends.relay_stopped": "Zbyt wiele błędnych krótkich kodów, więc przekaźnik jest wyłączony do ponownego udostępnienia. Znajomi nadal mogą dołączyć pełnym kodem.",
"horizon.extras.pack_browser.tooltip": "Wybór paczek zasobów zyskuje przycisk Dodaj, który przeszukuje Modrinth i instaluje paczkę w folderze paczek. Wyłączone: gra nigdy nie łączy się z Modrinth.",
"horizon.splitscreen.setup.monitor": "Monitor %s",
"horizon.splitscreen.setup.monitor_unknown": "monitor",
@@ -552,6 +557,22 @@
"horizon.splitscreen.profiles.offline_note": "Profile offline należą do tej instancji",
"horizon.splitscreen.profiles.move": "Zmień miejsce gry",
"horizon.splitscreen.profiles.move_place": "Zmień miejsce gry: %s",
"horizon.friends.title": "Graj ze znajomymi",
"horizon.friends.hint": "Znajomi wklejają kod po kliknięciu przycisku Znajomi na ekranie tytułowym, w Połączeniu bezpośrednim lub na stronie Graj w launcherze.",
"horizon.friends.copied": "Skopiowano",
"horizon.friends.copy_code": "Kopiuj kod",
"horizon.friends.stop_sharing": "Przestań udostępniać",
"horizon.friends.none_yet": "Nie ma jeszcze żadnych znajomych.",
"horizon.friends.here_now": "Obecnie: %s",
"horizon.friends.share_intro": "Udostępnij ten świat za pomocą kodu zaproszenia: otwiera się w sieci LAN, a znajomi przez internet dołączają za pomocą kodu. Nie korzystamy z żadnego naszego serwera.",
"horizon.friends.start_sharing": "Zacznij udostępniać",
"horizon.friends.troubleshooting": "Rozwiązywanie problemów…",
"horizon.friends.stopped": "Przestano udostępniać kod zaproszenia.",
"horizon.friends.short_code_changed": "Ktoś wciąż wpisywał zły krótki kod, więc został zmieniony.",
"horizon.friends.wrong_code": "Ktoś wpisał zły kod.",
"horizon.friends.code_ready": "Twój kod zaproszenia jest gotowy: Menu gry, Graj ze znajomymi. Skopiuj go i wyślij znajomym.",
"horizon.friends.share_failed": "Nie udało się udostępnić świata: %s",
"horizon.friends.finding_route": "Sprawdzanie, jak znajomi mogą się z tobą połączyć…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Spacja",
"horizon.osk.delete": "Usuń",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinicie o jogo para aplicar %s: eles adicionam blocos, itens ou geração de mundo.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copiar detalhes da conexão",
"horizon.multiplayer.join": "Junte-se",
"horizon.multiplayer.cancel_reconnecting": "Cancelar reconexão",
"horizon.multiplayer.join_friend": "Junte-se a um amigo",
"horizon.multiplayer.invite_code": "Código de convite",
"horizon.multiplayer.relay": "Relé (opcional)",
"Preset": "Predefinido",
"LOD Distance": "Distância de LOD",
"Far Detail": "Detalhe distante",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Perfis off-line pertencem a esta instância",
"horizon.splitscreen.profiles.move": "Mova-se para onde você joga",
"horizon.splitscreen.profiles.move_place": "Mova-se para onde você joga: %s",
"horizon.friends.title": "Jogue com amigos",
"horizon.friends.hint": "Amigos colam o código após o botão Amigos da tela de título, no Direct Connection ou na página Play do inicializador.",
"horizon.friends.copied": "Copiado",
"horizon.friends.copy_code": "Copiar código",
"horizon.friends.stop_sharing": "Pare de compartilhar",
"horizon.friends.none_yet": "Nenhum amigo aqui ainda.",
"horizon.friends.here_now": "Aqui agora: %s",
"horizon.friends.share_intro": "Compartilhe este mundo por meio de um código de convite: ele abre para LAN e amigos na internet entram com o código. Nenhum servidor nosso está envolvido.",
"horizon.friends.start_sharing": "Comece a compartilhar",
"horizon.friends.troubleshooting": "Solução de problemas...",
"horizon.friends.stopped": "Parou de compartilhar o código de convite.",
"horizon.friends.short_code_changed": "Alguém continuou tentando um código curto errado, então ele mudou.",
"horizon.friends.wrong_code": "Alguém tentou um código errado.",
"horizon.friends.relay_stopped": "Muitos códigos curtos errados, então o relé fica desligado até você compartilhar de novo. Amigos ainda podem entrar com o código completo.",
"horizon.friends.code_ready": "Seu código de convite está pronto: Menu do Jogo, Jogue com Amigos. Copie e envie para seus amigos.",
"horizon.friends.share_failed": "Não foi possível compartilhar o mundo: %s",
"horizon.friends.finding_route": "Descobrir como os amigos podem entrar em contato com você…",
"horizon.osk.shift": "Mudança",
"horizon.osk.space": "Espaço",
"horizon.osk.delete": "Excluir",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reinicia o jogo para aplicar %s: adicionam blocos, itens ou geração do mundo.",
"horizon.shader_options.profile": "Perfil",
"horizon.agent.copy_details": "Copiar detalhes de ligação",
"horizon.multiplayer.join": "Entrar",
"horizon.multiplayer.cancel_reconnecting": "Cancelar religação",
"horizon.multiplayer.join_friend": "Juntar-se a um amigo",
"horizon.multiplayer.invite_code": "Código de convite",
"horizon.multiplayer.relay": "Relay (opcional)",
"Preset": "Predefinição",
"LOD Distance": "Distância LOD",
"Far Detail": "Detalhe distante",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Os perfis offline pertencem a esta instância",
"horizon.splitscreen.profiles.move": "Mover local de jogo",
"horizon.splitscreen.profiles.move_place": "Mover local de jogo: %s",
"horizon.friends.title": "Jogar com amigos",
"horizon.friends.hint": "Os amigos colam o código após o botão Amigos do ecrã de título, em Ligação Direta, ou na página Jogar do launcher.",
"horizon.friends.copied": "Copiado",
"horizon.friends.copy_code": "Copiar código",
"horizon.friends.stop_sharing": "Parar partilha",
"horizon.friends.none_yet": "Ainda sem amigos aqui.",
"horizon.friends.here_now": "Aqui agora: %s",
"horizon.friends.share_intro": "Partilha este mundo através de um código de convite: abre para LAN e os amigos na internet juntam-se com o código. Nenhum servidor nosso está envolvido.",
"horizon.friends.start_sharing": "Iniciar partilha",
"horizon.friends.troubleshooting": "Resolução de problemas...",
"horizon.friends.stopped": "Partilha do código de convite interrompida.",
"horizon.friends.short_code_changed": "Alguém tentou repetidamente um código curto incorreto, por isso este foi alterado.",
"horizon.friends.wrong_code": "Alguém tentou um código incorreto.",
"horizon.friends.relay_stopped": "Demasiados códigos curtos errados, por isso o relay está desligado até partilhares novamente. Os amigos ainda podem entrar com o código completo.",
"horizon.friends.code_ready": "O teu código de convite está pronto: Menu do Jogo, Jogar com Amigos. Copia-o e envia-o aos teus amigos.",
"horizon.friends.share_failed": "Não foi possível partilhar o mundo: %s",
"horizon.friends.finding_route": "A determinar como os amigos podem aceder...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Espaço",
"horizon.osk.delete": "Eliminar",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Repornește jocul pentru a aplica %s: adaugă blocuri, obiecte sau generare de lume.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Copiați detaliile conexiunii",
"horizon.multiplayer.join": "Alăturați-vă",
"horizon.multiplayer.cancel_reconnecting": "Anulează reconectarea",
"horizon.multiplayer.join_friend": "Alăturați-vă unui prieten",
"horizon.multiplayer.invite_code": "Cod de invitație",
"horizon.multiplayer.relay": "releu (optional)",
"Preset": "Presetat",
"LOD Distance": "Distanța LOD",
"Far Detail": "Detaliu îndepărtat",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Profilurile offline aparțin acestei instanțe",
"horizon.splitscreen.profiles.move": "Mișcă-te unde te joci",
"horizon.splitscreen.profiles.move_place": "Mutați unde jucați: %s",
"horizon.friends.title": "Joacă-te cu prietenii",
"horizon.friends.hint": "Prietenii lipesc codul după butonul Prieteni din ecranul de titlu, în Conexiune directă sau pe pagina Play a lansatorului.",
"horizon.friends.copied": "Copiat",
"horizon.friends.copy_code": "Copiați codul",
"horizon.friends.stop_sharing": "Opriți distribuirea",
"horizon.friends.none_yet": "Niciun prieten aici încă.",
"horizon.friends.here_now": "Aici acum: %s",
"horizon.friends.share_intro": "Distribuie această lume din spatele unui cod de invitație: se deschide către LAN, iar prietenii de pe internet se alătură cu codul. Niciun server de-al nostru nu este implicat.",
"horizon.friends.start_sharing": "Începeți să distribuiți",
"horizon.friends.troubleshooting": "Se depanează...",
"horizon.friends.stopped": "S-a oprit distribuirea codului de invitație.",
"horizon.friends.short_code_changed": "Cineva a tot încercat un cod scurt greșit, așa că s-a schimbat.",
"horizon.friends.wrong_code": "Cineva a încercat un cod greșit.",
"horizon.friends.relay_stopped": "Prea multe coduri scurte greșite, așa că releul este oprit până când distribui din nou. Prietenii se pot alătura în continuare cu codul complet.",
"horizon.friends.code_ready": "Codul dvs. de invitație este gata: Meniu joc, Joacă cu prietenii. Copiați-l și trimiteți-l prietenilor dvs.",
"horizon.friends.share_failed": "Nu am putut împărtăși lumea: %s",
"horizon.friends.finding_route": "Aflați cum prietenii vă pot contacta...",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Spațiu",
"horizon.osk.delete": "Ștergeți",
@@ -209,7 +209,11 @@
"horizon.mods.switch.registries": "добавляет блоки, предметы или другие записи реестра",
"horizon.mods.switch.restart": "Перезапустите игру, чтобы применить %s: они добавляют блоки, предметы или генерацию мира.",
"horizon.agent.copy_details": "Скопировать данные подключения",
"horizon.multiplayer.join": "Подключиться",
"horizon.multiplayer.cancel_reconnecting": "Отменить переподключение",
"horizon.multiplayer.join_friend": "Играть с другом",
"horizon.multiplayer.invite_code": "Код приглашения",
"horizon.multiplayer.relay": "Ретранслятор (необязательно)",
"Preset": "Пресет",
"LOD Distance": "Дистанция LOD",
"Far Detail": "Детализация вдали",
@@ -362,6 +366,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн-профили принадлежат этому экземпляру",
"horizon.splitscreen.profiles.move": "Сменить место игры",
"horizon.splitscreen.profiles.move_place": "Сменить место игры: %s",
"horizon.friends.title": "Играть с друзьями",
"horizon.friends.hint": "Друзья вставляют код после кнопки «Друзья» на титульном экране, в «Прямом подключении» или на странице «Играть» в лаунчере.",
"horizon.friends.copied": "Скопировано",
"horizon.friends.copy_code": "Копировать код",
"horizon.friends.stop_sharing": "Прекратить доступ",
"horizon.friends.none_yet": "Здесь пока нет друзей.",
"horizon.friends.here_now": "Сейчас здесь: %s",
"horizon.friends.share_intro": "Откройте этот мир по коду приглашения: он открывается в локальную сеть, а друзья в интернете подключаются по коду. Наши серверы не участвуют.",
"horizon.friends.start_sharing": "Открыть доступ",
"horizon.friends.troubleshooting": "Решение проблем...",
"horizon.friends.stopped": "Доступ по коду приглашения закрыт.",
"horizon.friends.short_code_changed": "Кто-то подряд вводил неверный короткий код, поэтому он изменился.",
"horizon.friends.wrong_code": "Кто-то ввёл неверный код.",
"horizon.friends.relay_stopped": "Слишком много неверных коротких кодов, поэтому ретранслятор выключен, пока вы не откроете доступ снова. Друзья всё ещё могут войти по полному коду.",
"horizon.friends.code_ready": "Ваш код приглашения готов: меню игры, «Играть с друзьями». Скопируйте его и отправьте друзьям.",
"horizon.friends.share_failed": "Не удалось открыть мир: %s",
"horizon.friends.finding_route": "Ищем, как друзья могут к вам подключиться…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Пробел",
"horizon.osk.delete": "Удалить",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Оонньууну өссө оҥостон %s холбоот: кинилэр блоктары, предметтэри эбэтэр аан дойду үөскээһинин эбэллэр.",
"horizon.shader_options.profile": "Профиль",
"horizon.agent.copy_details": "Холбоһуу сиһилиитин көһөр",
"horizon.multiplayer.join": "Кыттыс",
"horizon.multiplayer.cancel_reconnecting": "Хата холбоһууну тохтот",
"horizon.multiplayer.join_friend": "Доҕоргор холбос",
"horizon.multiplayer.invite_code": "Ыҥырыы куода",
"horizon.multiplayer.relay": "Реле (опциональнай)",
"Preset": "Предустановка",
"LOD Distance": "LOD ырааҕа",
"Far Detail": "Ыраах сиһилии",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Офлайн профиллар бу экземплярга киирэллэр",
"horizon.splitscreen.profiles.move": "Оонньуур сиригэр көһүҥ",
"horizon.splitscreen.profiles.move_place": "Оонньуур сиригэр көһөр: %s",
"horizon.friends.title": "Доҕотторгун кытта оонньоо",
"horizon.friends.hint": "Доҕоттор коду титул экранын Доҕоттор кнопкатын кэнниттэн, Прямой сибээскэ эбэтэр лаунчер Оонньуу страницатыгар киллэрэллэр.",
"horizon.friends.copied": "Копированнай",
"horizon.friends.copy_code": "Код копията",
"horizon.friends.stop_sharing": "Үлэһиттэри тохтотуҥ",
"horizon.friends.none_yet": "Манна доҕоттор суохтар.",
"horizon.friends.here_now": "Билигин манна: %s",
"horizon.friends.share_intro": "Ыҥырыы кодун кэннигэр баар аан дойдуну үллэст: LAN-ҥа аһыллар, уонна интернетка баар доҕоттор кодунан холбоһоллор. Биһиги биир да сервербит кыттыбат.",
"horizon.friends.start_sharing": "Үлэһиттэри саҕалаа",
"horizon.friends.troubleshooting": "Кыһалҕалары быһаарыы...",
"horizon.friends.stopped": "Ыҥырыы кодун үллэстиини тохтоппут.",
"horizon.friends.short_code_changed": "Ким эрэ сыыһа кылгас коду боруобалыыра, онон уларыйбыта.",
"horizon.friends.wrong_code": "Ким эрэ сыыһа коду оҥорон көрбүт.",
"horizon.friends.relay_stopped": "Элбэх сыыһа кылгас код, ол иһин relay эмиэ үллэстэриҥ саҕана уһуллубут. Доҕоттор толору кодонан киириэхтэрин сөп.",
"horizon.friends.code_ready": "Ыҥырыы кодуҥ бэлэм: Оонньуу менюта, Доҕотторгун кытта оонньоо. Ону көһөрөн баран доҕотторгор ыыт.",
"horizon.friends.share_failed": "Аан дойдуну үллэстэр кыаҕым суох: %s",
"horizon.friends.finding_route": "Доҕоттор эйиэхэ хайдах тиийиэхтэрин сөбүн булуу...",
"horizon.osk.shift": "Смена",
"horizon.osk.space": "Космос",
"horizon.osk.delete": "Соттор",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Álggat spealu ođđasit vai %s atnojit: dat lasihit lohkkiid, ávdnasiid dahje máilmmibuvttadeami.",
"horizon.shader_options.profile": "Profiila",
"horizon.agent.copy_details": "Kopiere oktavuođadieđuid",
"horizon.multiplayer.join": "Searvva",
"horizon.multiplayer.cancel_reconnecting": "Heaittihit fas čatnama",
"horizon.multiplayer.join_friend": "Searvva ovtta skihpárii",
"horizon.multiplayer.invite_code": "Bovdehuskoda",
"horizon.multiplayer.relay": "Rele (válljejuvvon)",
"Preset": "Ovdalgihtii mearriduvvon",
"LOD Distance": "LOD-gaska",
"Far Detail": "Guhkkin detáljat",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline-profiillat gullet dán instánsii",
"horizon.splitscreen.profiles.move": "Sirdde dohko gosa speallat",
"horizon.splitscreen.profiles.move_place": "Sirdde dohko gosa speallat: %s",
"horizon.friends.title": "Speallat ustibiiguin",
"horizon.friends.hint": "Friends liibmet koda maŋŋel nammačájáhusa Friends-boalu, Direct Connection:as dahje álggaheaddji Play-siiddus.",
"horizon.friends.copied": "Kopieren",
"horizon.friends.copy_code": "Kopiere koda",
"horizon.friends.stop_sharing": "Heaittit juohkima",
"horizon.friends.none_yet": "Eai leat skihpárat dáppe vuos.",
"horizon.friends.here_now": "Dáppe dál: %s",
"horizon.friends.share_intro": "Juohkit dán máilmmi bovdehuskoda duohken: dat rahppo LAN:ii, ja skihpárat interneahtas servet kodain. Ii oktage min bálvaleaddji leat mielde.",
"horizon.friends.start_sharing": "Álggat juohkit",
"horizon.friends.troubleshooting": "Vealaheapmi...",
"horizon.friends.stopped": "Heaittihan bovdehuskoda juohkima.",
"horizon.friends.short_code_changed": "Muhtin geahččalii ain boastut oanehis koda, nu ahte dat rievddai.",
"horizon.friends.wrong_code": "Muhtin geahččalii boastut koda.",
"horizon.friends.relay_stopped": "Ollu boastut oanehis kodat, nu ahte rele lea heaittihuvvon gitta dassážii go juohkit ođđasit. Skihpárat sáhttet ain searvat olles kodain.",
"horizon.friends.code_ready": "Du bovdehuskoda lea gárvvis: Speallanmenu, Speallan ustibiiguin. Kopiere dan ja sádde dan iežat skihpáriidda.",
"horizon.friends.share_failed": "Ii sáhttán juohkit máilmmi: %s",
"horizon.friends.finding_route": "Gávdnat mo skihpárat sáhttet olahit du...",
"horizon.osk.shift": "Sirdin",
"horizon.osk.space": "Ruovttu",
"horizon.osk.delete": "Slette",
@@ -213,7 +213,11 @@
"horizon.mods.switch.restart": "Reštartuj hru, aby sa %s prejavili: pridávajú bloky, predmety alebo generovanie sveta.",
"horizon.shader_options.profile": "Profil",
"horizon.agent.copy_details": "Kopírovať podrobnosti o pripojení",
"horizon.multiplayer.join": "Pripojte sa",
"horizon.multiplayer.cancel_reconnecting": "Zrušiť opätovné pripojenie",
"horizon.multiplayer.join_friend": "Pridajte sa k priateľovi",
"horizon.multiplayer.invite_code": "Pozývací kód",
"horizon.multiplayer.relay": "relé (voliteľné)",
"Preset": "Prednastavené",
"LOD Distance": "LOD Vzdialenosť",
"Far Detail": "Ďaleký detail",
@@ -458,6 +462,23 @@
"horizon.splitscreen.profiles.offline_note": "Offline profily patria k tejto inštancii",
"horizon.splitscreen.profiles.move": "Pohybujte sa tam, kde hráte",
"horizon.splitscreen.profiles.move_place": "Presuňte sa tam, kde hráte: %s",
"horizon.friends.title": "Hrajte s priateľmi",
"horizon.friends.hint": "Priatelia prilepia kód za tlačidlo Priatelia na titulnej obrazovke, do priameho pripojenia alebo na stránku Play spúšťača.",
"horizon.friends.copied": "Skopírované",
"horizon.friends.copy_code": "Kopírovať kód",
"horizon.friends.stop_sharing": "Zastaviť zdieľanie",
"horizon.friends.none_yet": "Zatiaľ tu nie sú žiadni priatelia.",
"horizon.friends.here_now": "Teraz tu: %s",
"horizon.friends.share_intro": "Zdieľajte tento svet pomocou pozývacieho kódu: otvára sa na LAN a priatelia na internete sa pripájajú pomocou kódu. Nie je zapojený žiadny náš server.",
"horizon.friends.start_sharing": "Začnite zdieľať",
"horizon.friends.troubleshooting": "Riešenie problémov...",
"horizon.friends.stopped": "Zdieľanie pozývacieho kódu bolo zastavené.",
"horizon.friends.short_code_changed": "Niekto stále skúšal nesprávny krátky kód, takže sa to zmenilo.",
"horizon.friends.wrong_code": "Niekto skúsil nesprávny kód.",
"horizon.friends.relay_stopped": "Príliš mnoho nesprávnych krátkych kódov, takže relé je vypnuté, kým znova nezdieľaš. Priatelia sa stále môžu pripojiť s úplným kódom.",
"horizon.friends.code_ready": "Váš pozývací kód je pripravený: Herné menu, Hrajte s priateľmi. Skopírujte ho a pošlite svojim priateľom.",
"horizon.friends.share_failed": "Nepodarilo sa zdieľať svet: %s",
"horizon.friends.finding_route": "Zistite, ako vás môžu priatelia kontaktovať…",
"horizon.osk.shift": "Shift",
"horizon.osk.space": "Priestor",
"horizon.osk.delete": "Odstrániť",
Loaded 100 of 448 files, more files were not shown because too many files have changed in this diff. Show more