Merge remote-tracking branch 'origin/pvp-safe/wire-stream-harness' into pvp/wire-stream-legacy

This commit is contained in:
Horizon agent committed 2026-11-05 23:11:05 +01:00
commit a35ea8b72a
359 files changed
+21579 -1793

No files matched your search

+1
View File
@@ -35,6 +35,7 @@ Feature → files → harness for the most-changed areas: [docs/architecture.md]
- **No hardcoded user-facing strings.** Keep UI translation-ready from the start. In the launcher (`launcher/`), wrap visible text with `tr("...")` or `trf("... {arg} ...", &[("arg", &val)])` from `crate::i18n` instead of raw string literals or `format!`. In the game, use translation keys (`Text::tr`, `lang::get`), never hardcoded English strings.
- **Claim before you start**: comment `/claim` on the issue (no issue yet: open one, then claim it). An assigned
issue is taken: pick another. `/unclaim` when you stop; a claim with no open PR linking it is released after 5 days.
- **Controllers reach what registers.** Draw controls with a registering helper (`ui::button`, `settings_shell::foot_button`); `graphics_style::button` and `screen_draw::button` only paint, and registering one part of a screen ends its crosshair, so register all of it.
## Crates
Generated
+1
View File
@@ -1413,6 +1413,7 @@ dependencies = [
"horizon-client-render",
"horizon-command",
"horizon-core",
"horizon-cosmetics",
"horizon-dualsense",
"horizon-friends",
"horizon-hdr",
@@ -314,6 +314,8 @@ pub const ACTIONS: &[(&str, Option<Button>)] = &[
("key.screenshot", None),
("key.toggleGui", None),
("key.smoothCamera", None),
// Horizon's emote wheel: no button is free by default; the stick's cursor picks.
("key.emote", None),
];
/// How a bindable action reaches the game: one of its own handlers, shared
@@ -23,6 +23,8 @@ pub const MAPPINGS: &[(&str, &str, &str)] = &[
("key.pickItem", "key.mouse.middle", "gameplay"),
("key.command", "key.keyboard.slash", "multiplayer"),
("key.friends", "key.keyboard.o", "multiplayer"),
// Horizon's emote wheel (docs/cosmetics.md), on a key vanilla leaves free.
("key.emote", "key.keyboard.b", "multiplayer"),
("key.socialInteractions", "key.keyboard.p", "multiplayer"),
("key.toggleGui", "key.keyboard.f1", "misc"),
(
+2
View File
@@ -18,6 +18,8 @@ horizon-client-core = { path = "../horizon-client-core" }
horizon-client-input = { path = "../horizon-client-input" }
horizon-client-render = { path = "../horizon-client-render" }
horizon-command = { path = "../horizon-command" }
# Emotes pose the player model (`Mob::emote`, `mobs::anim::setup`).
horizon-cosmetics = { path = "../horizon-cosmetics" }
horizon-items = { path = "../horizon-items" }
horizon-core = { path = "../horizon-core" }
# `horizon-ctl mcp`: the Model Context Protocol, shared with the launcher and the server.
+19 -17
View File
@@ -164,10 +164,10 @@ pub struct Extras {
/// Cosmetics (`horizon_cosmetics`, off unless enabled), the lines `horizon_cosmetics::prefs`
/// shares with the launcher's Wardrobe: Show my cosmetics (the account's, sent to the service;
/// on by default), how much of other players' to show (no line until chosen:
/// `effective_others`), and their auras and trails (off by default).
/// `effective_others`), and whether their trails and auras are hidden (off by default).
pub cosmetics_mine: bool,
pub cosmetics_others: Option<horizon_cosmetics::prefs::Others>,
pub cosmetics_auras: bool,
pub cosmetics_hide_fx: bool,
/// My cosmetics in single player too (`cosmeticsSolo`, off by default): the window's own server
/// names the player by their offline profile, which the service doesn't know, so their own
/// cosmetics and name tag style show only with this on.
@@ -235,7 +235,7 @@ impl Default for Extras {
music_page: false,
cosmetics_mine: true,
cosmetics_others: None,
cosmetics_auras: false,
cosmetics_hide_fx: false,
cosmetics_solo: false,
cosmetics_owner: false,
horizon_marks: true,
@@ -349,7 +349,7 @@ impl Extras {
e.cosmetics_others =
horizon_cosmetics::prefs::Others::parse(value).or(e.cosmetics_others)
}
"cosmeticsAuras" => e.cosmetics_auras = flag(e.cosmetics_auras),
"cosmeticsHideFx" => e.cosmetics_hide_fx = flag(e.cosmetics_hide_fx),
"cosmeticsSolo" => e.cosmetics_solo = flag(e.cosmetics_solo),
horizon_cosmetics::prefs::MARKS => e.horizon_marks = flag(e.horizon_marks),
horizon_cosmetics::prefs::LISTED => e.horizon_listed = flag(e.horizon_listed),
@@ -363,7 +363,7 @@ impl Extras {
}
pub fn serialize(&self) -> String {
let mut text = format!(
"packBrowser:{}\npregen:{}\nfullbright:{}\ndynamicLights:{}\nzoom:{}\nzoomKey:{}\nzoomLevel:{}\nzoomSmooth:{}\nzoomSensitivity:{}\nlodZoomDetail:{}\nfps:{}\nfpsCorner:{}\nfpsLows:{}\nkeystrokes:{}\nkeystrokesCorner:{}\nkeystrokesCps:{}\nmovedToMods:{}\nminimap:{}\nminimapCorner:{}\nminimapSize:{}\nminimapShape:{}\nminimapZoom:{}\nminimapRotate:{}\nautoReconnect:{}\nuiSoundReserve:{}\nownNameTag:{}\nhideBlockParticles:{}\nmouseTweaks:{}\nmouseTweaksWheel:{}\nsort:{}\nsortKey:{}\nchatAnimation:{}\nchatIndicator:{}\n{}:{}\nagentControl:{}\nreproKeys:{}\ndiscordPresence:{}\nsplitscreen:{}\nsplitscreenTwo:{}\nsplitscreenThree:{}\nsplitscreenNames:{}\nwheelCyclesSettings:{}\nmusicOff:{}\nmusicPage:{}\ncosmeticsMine:{}\n{}cosmeticsAuras:{}\ncosmeticsSolo:{}\n{}:{}\n{}:{}\n{}:{}\n",
"packBrowser:{}\npregen:{}\nfullbright:{}\ndynamicLights:{}\nzoom:{}\nzoomKey:{}\nzoomLevel:{}\nzoomSmooth:{}\nzoomSensitivity:{}\nlodZoomDetail:{}\nfps:{}\nfpsCorner:{}\nfpsLows:{}\nkeystrokes:{}\nkeystrokesCorner:{}\nkeystrokesCps:{}\nmovedToMods:{}\nminimap:{}\nminimapCorner:{}\nminimapSize:{}\nminimapShape:{}\nminimapZoom:{}\nminimapRotate:{}\nautoReconnect:{}\nuiSoundReserve:{}\nownNameTag:{}\nhideBlockParticles:{}\nmouseTweaks:{}\nmouseTweaksWheel:{}\nsort:{}\nsortKey:{}\nchatAnimation:{}\nchatIndicator:{}\n{}:{}\nagentControl:{}\nreproKeys:{}\ndiscordPresence:{}\nsplitscreen:{}\nsplitscreenTwo:{}\nsplitscreenThree:{}\nsplitscreenNames:{}\nwheelCyclesSettings:{}\nmusicOff:{}\nmusicPage:{}\ncosmeticsMine:{}\n{}cosmeticsHideFx:{}\ncosmeticsSolo:{}\n{}:{}\n{}:{}\n{}:{}\n",
bool_text(self.pack_browser),
bool_text(self.pregen),
bool_text(self.fullbright),
@@ -417,7 +417,7 @@ impl Extras {
// Written once the player chose.
self.cosmetics_others
.map_or(String::new(), |o| format!("cosmeticsOthers:{}\n", o.name())),
bool_text(self.cosmetics_auras),
bool_text(self.cosmetics_hide_fx),
bool_text(self.cosmetics_solo),
horizon_cosmetics::prefs::MARKS,
bool_text(self.horizon_marks),
@@ -598,7 +598,7 @@ pub enum Item {
/// Shown only while cosmetics are enabled (`horizon_cosmetics::enabled`).
CosmeticsMine,
CosmeticsOthers,
CosmeticsAuras,
CosmeticsHideFx,
CosmeticsSolo,
HorizonMarks,
HorizonMe,
@@ -638,7 +638,7 @@ pub fn rows() -> Vec<Result<Item, &'static str>> {
Ok(CosmeticsMine),
Ok(CosmeticsSolo),
Ok(CosmeticsOthers),
Ok(CosmeticsAuras),
Ok(CosmeticsHideFx),
Ok(HorizonMarks),
Ok(HorizonMe),
]);
@@ -672,7 +672,7 @@ impl Item {
Item::Pregen => "horizon.extras.pregen",
Item::CosmeticsMine => "horizon.extras.cosmetics_mine",
Item::CosmeticsOthers => "horizon.extras.cosmetics_others",
Item::CosmeticsAuras => "horizon.extras.cosmetics_auras",
Item::CosmeticsHideFx => "horizon.extras.cosmetics_hide_fx",
Item::CosmeticsSolo => "horizon.extras.cosmetics_solo",
Item::HorizonMarks => "horizon.extras.horizon_marks",
Item::HorizonMe => "horizon.extras.horizon_me",
@@ -705,7 +705,7 @@ impl Item {
Item::Pregen => "horizon.extras.pregen.tooltip",
Item::CosmeticsMine => "horizon.extras.cosmetics_mine.tooltip",
Item::CosmeticsOthers => "horizon.extras.cosmetics_others.tooltip",
Item::CosmeticsAuras => "horizon.extras.cosmetics_auras.tooltip",
Item::CosmeticsHideFx => "horizon.extras.cosmetics_hide_fx.tooltip",
Item::CosmeticsSolo => "horizon.extras.cosmetics_solo.tooltip",
Item::HorizonMarks => "horizon.extras.horizon_marks.tooltip",
Item::HorizonMe => "horizon.extras.horizon_me.tooltip",
@@ -747,7 +747,7 @@ impl Item {
Item::Pregen => "Chunk pregeneration",
Item::CosmeticsMine => "My cosmetics",
Item::CosmeticsOthers => "Other players' cosmetics",
Item::CosmeticsAuras => "Others' auras and trails",
Item::CosmeticsHideFx => "Hide other players' trails and auras",
Item::CosmeticsSolo => "In single player",
Item::HorizonMarks => "Horizon logos",
Item::HorizonMe => "Show me as Horizon",
@@ -766,7 +766,7 @@ impl Item {
Fullbright | DynamicLights | OwnNameTag | HideBlockParticles | MouseTweaks | Sort
| AutoReconnect | NoAi | AgentControl | ReproKeys | DiscordPresence | Splitscreen
| ChatAnimation | WheelCyclesSettings | MusicPage | PackBrowser | CosmeticsMine
| CosmeticsOthers | CosmeticsAuras | CosmeticsSolo | HorizonMarks | HorizonMe
| CosmeticsOthers | CosmeticsHideFx | CosmeticsSolo | HorizonMarks | HorizonMe
| Pregen => {
return None;
}
@@ -834,7 +834,9 @@ impl Item {
Item::CosmeticsOthers => {
"What other Horizon players wear: everything, only their name tag styles, or nothing. Hidden unless you own cosmetics, until you choose. Hidden, the game never asks what they wear."
}
Item::CosmeticsAuras => "Auras and trails other players wear. Off by default.",
Item::CosmeticsHideFx => {
"Other players' trails and auras stay hidden; their other cosmetics still show. Off by default."
}
Item::CosmeticsSolo => {
"Show your cosmetics and your name tag's badge in your single-player worlds too (your name tag with Own name tag). Off: only on servers."
}
@@ -872,7 +874,7 @@ impl Item {
| Item::PackBrowser => Some(Cost::None),
Item::CosmeticsMine
| Item::CosmeticsOthers
| Item::CosmeticsAuras
| Item::CosmeticsHideFx
| Item::CosmeticsSolo
| Item::HorizonMarks
| Item::HorizonMe => Some(Cost::Low),
@@ -902,7 +904,7 @@ impl Item {
Item::WheelCyclesSettings => e.wheel_cycles_settings,
Item::PackBrowser => e.pack_browser,
Item::Pregen => e.pregen,
Item::CosmeticsAuras => e.cosmetics_auras,
Item::CosmeticsHideFx => e.cosmetics_hide_fx,
Item::CosmeticsSolo => e.cosmetics_solo,
Item::HorizonMarks => e.horizon_marks,
Item::HorizonMe => e.horizon_listed,
@@ -967,7 +969,7 @@ impl Item {
let o = e.effective_others();
e.cosmetics_others = Some(if back { o.next().next() } else { o.next() });
}
Item::CosmeticsAuras => e.cosmetics_auras = !e.cosmetics_auras,
Item::CosmeticsHideFx => e.cosmetics_hide_fx = !e.cosmetics_hide_fx,
Item::CosmeticsSolo => e.cosmetics_solo = !e.cosmetics_solo,
Item::HorizonMarks => e.horizon_marks = !e.horizon_marks,
Item::HorizonMe => e.horizon_listed = !e.horizon_listed,
@@ -996,7 +998,7 @@ mod tests {
..Extras::default()
};
assert_eq!(
(e.effective_others(), e.cosmetics_auras, e.cosmetics_mine),
(e.effective_others(), e.cosmetics_hide_fx, e.cosmetics_mine),
(Others::Shown, false, true)
);
Item::CosmeticsOthers.cycle(&mut e, false);
+33 -4
View File
@@ -12227,7 +12227,8 @@ mod tests {
}
}
/// Every WGSL shader file translates to HLSL as wgpu's DirectX 12 backend
/// writes it for FXC (shader model 5.1), entry point by entry point.
/// writes it for FXC (shader model 5.1), entry point by entry point, and
/// every shader the OpenGL backend runs also translates to GLSL.
#[test]
fn shaders_translate_to_hlsl_for_directx_12_and_glsl_for_opengl() {
fn wgsl_files(dir: &std::path::Path, out: &mut Vec<std::path::PathBuf>) {
@@ -12277,6 +12278,14 @@ mod tests {
}
}
let mut glsl_checked = 0;
// Shaders the OpenGL backend runs must translate: skipping the ones
// that fail hides exactly the bug where a shader GL needs cannot
// compile (#9448).
let mut glsl_failed = Vec::new();
let mut translated = std::collections::HashSet::new();
// naga's GLSL writer gives an image one sampler, and the HUD's glint
// samples one image through two; one failed entry does not hide the rest.
let known_unsupported = [("hud.wgsl", "fs_cit_glint")];
for (path, text) in sources {
// entity.wgsl comes after the overlay's constants (entity_shader).
let module = naga::front::wgsl::parse_str(&text)
@@ -12377,11 +12386,18 @@ mod tests {
Default::default(),
)
.and_then(|mut w| w.write());
// Some shaders use features GLSL cannot express (depth textureLoad): GL does
// not run them. The ones it does run must translate, checked below.
if glsl_result.is_err() {
let name = path.file_name().and_then(|n| n.to_str()).unwrap_or("");
if let Err(e) = glsl_result {
if !known_unsupported.contains(&(name, entry.name.as_str())) {
glsl_failed.push(format!(
"{} {} (GLSL {version}): {e}",
path.display(),
entry.name
));
}
continue;
}
translated.insert((name.to_owned(), entry.name.clone()));
glsl_checked += 1;
assert!(
!glsl.contains("ARB_arrays_of_arrays"),
@@ -12392,6 +12408,19 @@ mod tests {
}
}
}
assert!(
glsl_failed.is_empty(),
"shaders the OpenGL backend runs must translate:\n{}",
glsl_failed.join("\n")
);
// These read the world's depth through `textureLoad`; before #9448 their
// depth binding could not translate, so TAA and the blit never came up.
for (file, entry) in [("world_post.wgsl", "fs_taa"), ("pack_post.wgsl", "fs_blit")] {
assert!(
translated.contains(&(file.to_owned(), entry.to_owned())),
"{file} {entry} must translate to GLSL"
);
}
assert!(glsl_checked >= 10, "{glsl_checked} GLSL translations");
}
#[test]
+1 -1
View File
@@ -287,7 +287,7 @@ impl Cull {
0,
fragment,
wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Depth,
sample_type: wgpu::TextureSampleType::Float { filterable: false },
view_dimension: wgpu::TextureViewDimension::D2,
multisampled: false,
},
@@ -114,8 +114,10 @@ fn see(t: u32) {
}
}
// Phase 1's depth, where the test runs in the shader (gfx/cull.rs).
@group(1) @binding(0) var depth: texture_depth_2d;
// Phase 1's depth, where the test runs in the shader (gfx/cull.rs). A depth
// view bound as an unfilterable float: naga's GLSL backend cannot `textureLoad`
// a depth texture, and the texel is the same value.
@group(1) @binding(0) var depth: texture_2d<f32>;
// The world pass's reversed depth test, greater or equal passing, made here:
// where it cannot be forced before a shader that writes storage, a fragment
@@ -123,7 +125,7 @@ fn see(t: u32) {
// runs only for the fragments that pass it.
@fragment
fn fs_box(in: Box) {
if in.position.z >= textureLoad(depth, vec2<u32>(in.position.xy), 0) {
if in.position.z >= textureLoad(depth, vec2<u32>(in.position.xy), 0).r {
see(in.test);
}
}
@@ -52,7 +52,9 @@ struct Params {
@group(0) @binding(0) var<uniform> params: Params;
@group(0) @binding(1) var linear_clamp: sampler;
@group(0) @binding(2) var input_depth: texture_depth_2d;
// A depth view bound as unfilterable float: naga's GLSL backend cannot
// `textureLoad` a depth texture, and the texel is the same value.
@group(0) @binding(2) var input_depth: texture_2d<f32>;
@group(0) @binding(3) var current_color: texture_2d<f32>;
@group(0) @binding(4) var previous_color: texture_2d<f32>;
@group(0) @binding(5) var dilated_depth_out: texture_storage_2d<r32float, write>;
@@ -333,7 +335,7 @@ fn load_input_depth(p: vec2<i32>) -> f32 {
if !is_on_screen(p, params.render_size) {
return 0.0;
}
return textureLoad(input_depth, p, 0);
return textureLoad(input_depth, p, 0).r;
}
@compute @workgroup_size(8, 8)
@@ -12,7 +12,9 @@ struct Params {
};
@group(0) @binding(0) var<uniform> params: Params;
@group(0) @binding(1) var depth: texture_depth_2d;
// A depth view bound as unfilterable float: naga's GLSL backend cannot
// `textureLoad` a depth texture, and the texel is the same value.
@group(0) @binding(1) var depth: texture_2d<f32>;
@group(0) @binding(2) var atlas: texture_2d<f32>;
@group(0) @binding(3) var atlas_sampler: sampler;
@@ -38,7 +40,7 @@ struct Out {
// xy: the motion vector in UV (to where the pixel was last frame, FSR's convention), z: 1.
@fragment fn fs_motion(in: Out) -> @location(0) vec4<f32> {
let stored = textureLoad(depth, vec2<i32>(in.clip.xy), 0);
let stored = textureLoad(depth, vec2<i32>(in.clip.xy), 0).r;
let tolerance = stored * 1e-3 + 1e-7;
// Not what the world shows here: a transparent texel, or behind something.
if in.translucent != 0u {
@@ -1172,6 +1172,14 @@ pub fn frame_inputs(
let k = super::native_shadow::distortion(s.distance, s.resolution);
2.0 * s.distance / s.resolution.max(1) as f32 * (1.0 - k)
}),
// Shader API 0.2's display fields, which 0.1 packs don't declare: SDR's values, also
// with HDR on, until HDR output is served for 0.2 packs.
hdr: 0,
headroom: 1.0,
paper_white: 80.0,
peak: 80.0,
black_level: 0.0,
padding: [0; 3],
}
}
@@ -16,14 +16,16 @@ const MAPPED: u8 = 3;
const ROW: u32 = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
const SHADER: &str = "
@group(0) @binding(0) var depth: texture_depth_2d;
// A depth view bound as unfilterable float: naga's GLSL backend cannot
// `textureLoad` a depth texture, and the texel is the same value.
@group(0) @binding(0) var depth: texture_2d<f32>;
@vertex fn vs(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
let p = vec2<f32>(f32((i << 1u) & 2u), f32(i & 2u));
return vec4<f32>(p * 2.0 - 1.0, 0.0, 1.0);
}
@fragment fn fs() -> @location(0) vec4<f32> {
let centre = vec2<i32>(textureDimensions(depth) / 2u);
return vec4<f32>(textureLoad(depth, centre, 0), 0.0, 0.0, 1.0);
return vec4<f32>(textureLoad(depth, centre, 0).r, 0.0, 0.0, 1.0);
}
";
@@ -64,7 +66,7 @@ impl CenterDepth {
binding: 0,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Depth,
sample_type: wgpu::TextureSampleType::Float { filterable: false },
view_dimension: wgpu::TextureViewDimension::D2,
multisampled: false,
},
@@ -433,6 +433,14 @@ struct Mips {
levels: Vec<(wgpu::TextureView, wgpu::BindGroup)>,
}
/// The picture a pack's `final` draws at the world's size while the window is another: it is
/// copied onto the window once, after the pack's passes, as the game's own post pass does
/// without a pack.
struct FinalTarget {
size: [u32; 2],
view: wgpu::TextureView,
}
struct Targets {
size: [u32; 2],
/// A and B of each buffer used.
@@ -664,6 +672,12 @@ pub struct PackPost {
blit_group: Option<([wgpu::TextureView; 2], wgpu::BindGroup)>,
/// Shows colortex0 when the pack has no `final` (OQ-5).
copy: (wgpu::RenderPipeline, wgpu::BindGroupLayout),
/// Copies the picture `final` drew at the world's size onto the window: no flip, it is
/// already in the screen's rows.
upscale: (wgpu::RenderPipeline, wgpu::BindGroupLayout),
/// The picture `final` draws while the world's size is not the window's.
final_target: Option<FinalTarget>,
screen: wgpu::TextureFormat,
uniforms: FrameUniforms,
}
@@ -2724,7 +2738,7 @@ impl PackPost {
},
&[
texture_entry(0, float),
texture_entry(1, wgpu::TextureSampleType::Depth),
texture_entry(1, wgpu::TextureSampleType::Float { filterable: false }),
],
&blit_targets,
// GL's window depth, written for depthtex0 and the terrain's depth test.
@@ -2751,6 +2765,20 @@ impl PackPost {
&[target(screen)],
None,
);
let upscale = helper(
device,
"vs_screen",
"fs_copy",
&[
texture_entry(0, float),
entry(
2,
wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
),
],
&[target(screen)],
None,
);
let filterable = |b: usize| {
formats[b].sample_type(None, Some(device.features()))
== Some(wgpu::TextureSampleType::Float { filterable: true })
@@ -2952,6 +2980,9 @@ impl PackPost {
}),
blit,
copy,
upscale,
final_target: None,
screen,
uniforms: {
let mut u = FrameUniforms::default();
u.atlas = world.atlas.map_or([0; 2], |a| a.1);
@@ -4484,6 +4515,35 @@ impl PackPost {
terrain: &mut TerrainDraw<'_>,
) {
self.resize(device, size);
// A resolution scale leaves the picture smaller (or larger) than the window: the pack's
// `final` draws it at the picture's size, and one copy takes it to the window (#9291).
let final_view = if size != window && self.passes.iter().any(|p| p.group == Group::Final) {
if self.final_target.as_ref().is_none_or(|t| t.size != size) {
let texture = device.create_texture(&wgpu::TextureDescriptor {
label: Some("Shader pack final"),
size: wgpu::Extent3d {
width: size[0],
height: size[1],
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: self.screen,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT
| wgpu::TextureUsages::TEXTURE_BINDING,
view_formats: &[],
});
self.final_target = Some(FinalTarget {
size,
view: texture.create_view(&Default::default()),
});
}
self.final_target.as_ref().map(|t| t.view.clone())
} else {
self.final_target = None;
None
};
if let Some((layout, ids, rects)) = &self.block_ids {
// A page that grew has a new buffer.
self.page_groups
@@ -4788,8 +4848,8 @@ impl PackPost {
self.mips_valid |= stale;
let final_pass = pass.group == Group::Final;
// A pass writing buffers of a size of their own draws at that size (they share it).
// `final` draws the picture at the world's size; a copy takes it to the window.
let out = match pass.writes.first() {
_ if final_pass => window,
Some(&(_, b)) => self.targets.as_ref().map_or(size, |t| t.sizes[b]),
None => size,
};
@@ -4812,7 +4872,7 @@ impl PackPost {
overwrite
};
if final_pass {
attachments.push(attach(screen, overwrite));
attachments.push(attach(final_view.as_ref().unwrap_or(screen), overwrite));
shown = true;
} else if pass.sink {
attachments.push(attach(&targets.sink, ops));
@@ -4895,6 +4955,31 @@ impl PackPost {
rp.set_pipeline(&self.copy.0);
rp.set_bind_group(0, &group, &[]);
rp.draw(0..3, 0..1);
} else if let Some(picture) = &final_view {
// The picture at the world's size onto the window: one upscale, smoothly.
let group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Shader pack final"),
layout: &self.upscale.1,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::TextureView(picture),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Sampler(&self.linear),
},
],
});
let mut rp = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: Some("Shader pack final"),
color_attachments: &[attach(screen, overwrite)],
timestamp_writes: self.timing.as_mut().and_then(|t| t.writes("final copy")),
..Default::default()
});
rp.set_pipeline(&self.upscale.0);
rp.set_bind_group(0, &group, &[]);
rp.draw(0..3, 0..1);
}
}
}
@@ -9,7 +9,9 @@ fn vs_full(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
}
@group(0) @binding(0) var source: texture_2d<f32>;
@group(0) @binding(1) var world_depth: texture_depth_2d;
// A depth view read as an unfilterable float: naga's GLSL backend cannot
// `textureLoad` a depth texture, and the texel is the same either way.
@group(0) @binding(1) var world_depth: texture_2d<f32>;
struct World {
@location(0) color: vec4<f32>,
@@ -24,7 +26,7 @@ fn fs_blit(@builtin(position) p: vec4<f32>) -> World {
let at = vec2<i32>(i32(p.x), size.y - 1 - i32(p.y));
var out: World;
out.color = textureLoad(source, at, 0);
out.depth = 1.0 - textureLoad(world_depth, at, 0);
out.depth = 1.0 - textureLoad(world_depth, at, 0).r;
return out;
}
@@ -49,6 +51,13 @@ fn vs_uv(@builtin(vertex_index) i: u32) -> Full {
return Full(vec4<f32>(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, 0.0, 1.0), vec2<f32>(uv.x, 1.0 - uv.y));
}
// The screen's own rows: a picture a shader pack's `final` drew (not a GL-rows buffer).
@vertex
fn vs_screen(@builtin(vertex_index) i: u32) -> Full {
let uv = vec2<f32>(f32((i << 1u) & 2u), f32(i & 2u));
return Full(vec4<f32>(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, 0.0, 1.0), uv);
}
@fragment
fn fs_copy(v: Full) -> @location(0) vec4<f32> {
return textureSample(source, linear, v.uv);
@@ -43,6 +43,64 @@ fn a_pack_without_final_reads_the_replaced_world_colour() {
replacement(Change::Colour, false);
}
/// A Resolution Scale leaves the pack's picture smaller than the window. Its `final` draws at
/// the picture's size and one copy upsizes it to the window (#9291), so a final that fetches
/// its pixel by `gl_FragCoord` (as Photon's does) covers every pixel, not a quarter of them.
#[test]
fn a_scaled_picture_fills_the_whole_window() {
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(&wgpu::DeviceDescriptor {
required_limits: adapter.limits(),
..Default::default()
})) else {
return;
};
eprintln!("scaled picture adapter: {:?}", adapter.get_info());
let picture = [4, 2];
let window = [8, 4];
let colour = texture(&device, picture, T::Rgba8Unorm);
let depth = texture(&device, picture, T::Depth32Float);
clear(&device, &queue, &colour, &depth, [32, 64, 16, 255], 0.25);
let mut post = pack_with(
&device,
&queue,
&adapter,
&colour,
&[
(
"final.vsh",
"#version 120\nvoid main(){gl_Position=ftransform();}",
),
(
"final.fsh",
"#version 330 compatibility\nuniform sampler2D colortex0;\nvoid main(){gl_FragColor=texelFetch(colortex0,ivec2(gl_FragCoord.xy),0);}",
),
],
);
let hud = HudBatch::new(window);
let pixels = render(
&device,
&queue,
&mut post,
&colour,
&depth,
&frame(&hud),
picture,
window,
);
// Independently specified: the world's colour at every window pixel.
let wrong = pixels.iter().filter(|p| **p != [32, 64, 16, 255]).count();
assert_eq!(
wrong,
0,
"{wrong} of {} pixels are not the picture",
pixels.len()
);
}
fn replacement(change: Change, final_shader: bool) {
let instance = crate::gfx::test_gpu::instance();
let Ok(adapter) = pollster::block_on(instance.request_adapter(&Default::default())) else {
@@ -62,7 +120,9 @@ fn replacement(change: Change, final_shader: bool) {
let mut post = pack(&device, &queue, &adapter, &colour, final_shader);
let hud = HudBatch::new(size);
let frame = frame(&hud);
let initial = render(&device, &queue, &mut post, &colour, &depth, &frame, size);
let initial = render(
&device, &queue, &mut post, &colour, &depth, &frame, size, size,
);
let expected = if final_shader {
[32, 64, 191, 255]
} else {
@@ -93,9 +153,13 @@ fn replacement(change: Change, final_shader: bool) {
0.75
};
clear(&device, &queue, &colour, &depth, pixel, reverse_depth);
let actual = render(&device, &queue, &mut post, &colour, &depth, &frame, size);
let actual = render(
&device, &queue, &mut post, &colour, &depth, &frame, size, size,
);
let mut fresh = pack(&device, &queue, &adapter, &colour, final_shader);
let reference = render(&device, &queue, &mut fresh, &colour, &depth, &frame, size);
let reference = render(
&device, &queue, &mut fresh, &colour, &depth, &frame, size, size,
);
// Independently specified RG channels and GL depth (1 - reverse-Z), in UNORM8.
let expected = if !final_shader {
[160, 96, 48, 255]
@@ -178,13 +242,8 @@ fn pack(
lightmap: &wgpu::TextureView,
final_shader: bool,
) -> PackPost {
let mut zip = zip::ZipWriter::new(Cursor::new(Vec::new()));
let options = zip::write::SimpleFileOptions::default();
zip.start_file("shaders/shaders.properties", options)
.unwrap();
zip.write_all(b"oldLighting=false\n").unwrap();
if final_shader {
for (name, source) in [
let programs: &[(&str, &str)] = if final_shader {
&[
(
"final.vsh",
"#version 120\nvarying vec2 uv;\nvoid main(){gl_Position=ftransform();uv=gl_MultiTexCoord0.xy;}",
@@ -193,10 +252,29 @@ fn pack(
"final.fsh",
"#version 120\nvarying vec2 uv;uniform sampler2D colortex0;uniform sampler2D depthtex0;\nvoid main(){gl_FragColor=vec4(texture2D(colortex0,uv).rg,texture2D(depthtex0,uv).r,1.0);}",
),
] {
zip.start_file(format!("shaders/{name}"), options).unwrap();
zip.write_all(source.as_bytes()).unwrap();
}
]
} else {
&[]
};
pack_with(device, queue, adapter, lightmap, programs)
}
/// A pack of `programs` (`name`, GLSL source) over `lightmap`.
fn pack_with(
device: &wgpu::Device,
queue: &wgpu::Queue,
adapter: &wgpu::Adapter,
lightmap: &wgpu::TextureView,
programs: &[(&str, &str)],
) -> PackPost {
let mut zip = zip::ZipWriter::new(Cursor::new(Vec::new()));
let options = zip::write::SimpleFileOptions::default();
zip.start_file("shaders/shaders.properties", options)
.unwrap();
zip.write_all(b"oldLighting=false\n").unwrap();
for (name, source) in programs {
zip.start_file(format!("shaders/{name}"), options).unwrap();
zip.write_all(source.as_bytes()).unwrap();
}
let pack = horizon_shaders::Pack::from_zip_bytes(
"original-world-inputs",
@@ -241,12 +319,13 @@ fn render(
depth: &wgpu::TextureView,
frame: &Frame,
size: [u32; 2],
window: [u32; 2],
) -> Vec<[u8; 4]> {
let screen = texture(device, size, T::Rgba8Unorm);
let screen = texture(device, window, T::Rgba8Unorm);
let stride = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
let read = device.create_buffer(&wgpu::BufferDescriptor {
label: None,
size: u64::from(stride * size[1]),
size: u64::from(stride * window[1]),
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
@@ -261,7 +340,7 @@ fn render(
frame,
&Default::default(),
size,
size,
window,
&[],
&mut |_, _, _, _| {},
);
@@ -285,7 +364,7 @@ fn render(
.unwrap()
.chunks_exact(stride as usize)
.flat_map(|row| {
row[..size[0] as usize * 4]
row[..window[0] as usize * 4]
.as_chunks::<4>()
.0
.iter()
@@ -319,7 +319,7 @@ mod tests {
#[test]
fn a_native_weather_stage_validates() {
use horizon_shader_api::stages::StageKind;
let source = StageKind::Weather.prelude()
let source = StageKind::Weather.prelude(horizon_shader_api::Api::V0_1)
+ "fn weather(input: WeatherInput) -> vec4<f32> {\n \
return input.color * vec4(input.light, input.position.x, f32(input.snow));\n}\n";
let text = native_source(&source);
@@ -43,9 +43,7 @@ struct TaaUniform {
jitter: [f32; 4],
}
/// TAA's GPU resources, absent when the device cannot compile the shader
/// (the OpenGL backend's naga GLSL emitter does not support `textureLoad`
/// from depth textures).
/// TAA's GPU resources, absent when the device cannot compile the shader.
struct TaaResources {
layout: wgpu::BindGroupLayout,
pipeline: wgpu::RenderPipeline,
@@ -146,9 +144,6 @@ impl Post {
cache: None,
})
};
// The OpenGL backend's GLSL translator does not support textureLoad
// from depth textures: on devices running through OpenGL (such as older
// Intel GPUs on Linux), TAA cannot compile its pipeline.
let taa_resources = {
let taa_layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("Horizon TAA bindings"),
@@ -161,7 +156,9 @@ impl Post {
count: None,
},
texture(2, float),
texture(3, wgpu::TextureSampleType::Depth),
// A depth view through an unfilterable float binding: the
// texel is the same, and the GLSL backend can read it.
texture(3, wgpu::TextureSampleType::Float { filterable: false }),
wgpu::BindGroupLayoutEntry {
binding: 4,
visibility: wgpu::ShaderStages::FRAGMENT,
+45 -1
View File
@@ -1232,7 +1232,8 @@ impl HudAtlas {
.ok();
let animation = animation_of(mcmeta.as_deref());
// An animated strip keeps its first frame.
let frames = name.starts_with("block/") || name.starts_with("item/");
let frames =
animation.is_some() || name.starts_with("block/") || name.starts_with("item/");
let (w, h, pixels) = if frames {
first_frame(image, animation.as_ref())
} else {
@@ -3495,6 +3496,49 @@ mod tests {
let banner = atlas.sprites["custom/banner"];
assert_eq!(banner.texels((atlas.width, atlas.height)), (16, 32));
}
#[test]
fn an_animated_gui_sprite_packs_its_first_frame_and_animates() {
let root =
std::env::temp_dir().join(format!("horizon-atlas-gui-anim-{}", std::process::id()));
let sprites = root.join("assets/minecraft/textures/gui/sprites/icon");
fs::create_dir_all(&sprites).unwrap();
// A GUI sprite like icon/music_notes: 4 frames stacked vertically (16x64),
// with animation metadata, and a still 16x32 texture beside it.
write_strip(
&sprites.join("music_notes.png"),
16,
64,
&[
[10, 20, 30, 255],
[40, 50, 60, 255],
[70, 80, 90, 255],
[100, 110, 120, 255],
],
Some(r#"{"animation": {"frametime": 2}}"#),
);
write_strip(
&sprites.join("static_badge.png"),
16,
32,
&[[9, 9, 9, 255]],
None,
);
let atlas = HudAtlas::build(&root).unwrap();
let _ = fs::remove_dir_all(&root);
let rect = atlas.sprites["gui/sprites/icon/music_notes"];
// One frame, not the whole 16x64 strip squeezed into a slot.
assert_eq!(rect.texels((atlas.width, atlas.height)), (16, 16));
assert_eq!(texel_at(&atlas, rect, 0, 15), [10, 20, 30, 255]);
let (_, animation) = atlas
.sprite_animations
.iter()
.find(|(r, _)| r.u0 == rect.u0 && r.v0 == rect.v0)
.expect("the gui sprite animates");
assert_eq!(animation.frame_count(), 4);
// A still texture there stays whole.
let static_badge = atlas.sprites["gui/sprites/icon/static_badge"];
assert_eq!(static_badge.texels((atlas.width, atlas.height)), (16, 32));
}
/// A resource root with one plain item texture and these CIT files (relative path, contents).
fn cit_root(name: &str, files: &[(&str, &str)]) -> PathBuf {
let root =
+1
View File
@@ -63,6 +63,7 @@ pub mod menu_blur;
pub mod mesher;
pub mod minimap;
pub mod mipmap;
pub mod mod_browser;
pub mod mod_list;
pub mod model_library;
pub mod models;
@@ -0,0 +1,189 @@
//! What Options > Mods > Browse mods shows (docs/design/mod-hotload.md): the
//! registry's content mods this game installs, a search over them, and the one
//! whose page is open. The game fills it from a worker
//! (`horizon_client::mod_registry`, `game/mod_browser.rs`); the options screen
//! only reads it and asks for installs through its events.
/// One project of the registry, as the list and its page show it.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Listing {
pub id: String,
pub name: String,
pub summary: String,
/// Markdown, shown as plain text.
pub description: String,
pub authors: Vec<String>,
pub license: String,
pub categories: Vec<String>,
pub tags: Vec<String>,
/// The version this game would install, its date and changelog.
pub version: String,
pub published: String,
pub changelog: String,
pub downloads: u64,
/// The project's page on the website.
pub page: String,
/// The version installed in this game folder, if any.
pub installed: Option<String>,
}
impl Listing {
/// Whether a search for `query` (already lower case) finds it: its name,
/// id, summary, authors, categories or tags.
pub fn matches(&self, query: &str) -> bool {
let query = query.trim();
query.is_empty()
|| [&self.name, &self.id, &self.summary]
.into_iter()
.chain(&self.authors)
.chain(&self.categories)
.chain(&self.tags)
.any(|field| field.to_lowercase().contains(query))
}
/// Installed, but not the version the registry offers now.
pub fn has_update(&self) -> bool {
self.installed
.as_ref()
.is_some_and(|installed| *installed != self.version)
}
}
/// Where the browser is.
#[derive(Clone, Debug, Default, PartialEq)]
pub enum Status {
/// Not asked yet.
#[default]
Idle,
/// The index is being read.
Loading,
/// The projects are listed.
Ready,
/// The index couldn't be read: why, in English (shown inside a translated line).
Failed(String),
}
#[derive(Clone, Debug, Default)]
pub struct ModBrowser {
pub status: Status,
pub listings: Vec<Listing>,
/// The project an install runs for.
pub installing: Option<String>,
/// The last install's outcome, already translated, for the page it ran on.
pub message: Option<(String, bool)>,
}
impl ModBrowser {
/// The listings a search for `query` finds, by index into `listings`.
pub fn found(&self, query: &str) -> Vec<usize> {
let query = query.to_lowercase();
(0..self.listings.len())
.filter(|&i| self.listings[i].matches(&query))
.collect()
}
pub fn listing(&self, id: &str) -> Option<&Listing> {
self.listings.iter().find(|l| l.id == id)
}
}
/// A project's markdown description as lines of plain text for the page:
/// heading marks, emphasis and list bullets dropped, links shown as their text,
/// blank lines and fences left out.
pub fn plain_lines(markdown: &str) -> Vec<String> {
let mut out = Vec::new();
for line in markdown.lines() {
let line = line.trim();
if line.is_empty() || line.starts_with("```") || line.starts_with("<!--") {
continue;
}
let line = line.trim_start_matches('#').trim_start();
let line = match line.strip_prefix("- ").or_else(|| line.strip_prefix("* ")) {
Some(rest) => format!("• {rest}"),
None => line.to_owned(),
};
let line = links_as_text(&line).replace("**", "").replace('`', "");
if !line.is_empty() {
out.push(line);
}
}
out
}
/// `[text](url)` → `text`, `![alt](url)` → nothing.
fn links_as_text(line: &str) -> String {
let mut out = String::with_capacity(line.len());
let mut rest = line;
while let Some(open) = rest.find('[') {
let Some(close) = rest[open..].find("](").map(|c| open + c) else {
break;
};
let Some(end) = rest[close..].find(')').map(|e| close + e) else {
break;
};
let image = open > 0 && rest[..open].ends_with('!');
out.push_str(&rest[..if image { open - 1 } else { open }]);
if !image {
out.push_str(&rest[open + 1..close]);
}
rest = &rest[end + 1..];
}
out.push_str(rest);
out
}
#[cfg(test)]
mod tests {
use super::*;
fn listing(id: &str, tags: &[&str]) -> Listing {
Listing {
id: id.into(),
name: id.to_uppercase(),
summary: format!("All about {id}"),
tags: tags.iter().map(|t| (*t).to_owned()).collect(),
version: "1.0".into(),
..Listing::default()
}
}
#[test]
fn a_search_finds_names_tags_and_categories_in_any_case() {
let mut pipes = listing("pipes", &["tech"]);
pipes.categories = vec!["technology".into()];
let browser = ModBrowser {
listings: vec![listing("ruby", &["gems"]), pipes],
..ModBrowser::default()
};
assert_eq!(browser.found(""), [0, 1]);
assert_eq!(browser.found("RUBY"), [0]);
assert_eq!(browser.found("gems"), [0]);
assert_eq!(browser.found("techno"), [1]);
assert!(browser.found("nothing like it").is_empty());
}
#[test]
fn an_update_is_another_version_than_the_installed_one() {
let mut l = listing("ruby", &[]);
assert!(!l.has_update());
l.installed = Some("1.0".into());
assert!(!l.has_update());
l.installed = Some("0.9".into());
assert!(l.has_update());
}
#[test]
fn markdown_reads_as_plain_lines() {
let text = "# Ruby\n\nAdds **rubies**. See [the wiki](https://x.y).\n\n![shot](https://x.y/a.png)\n- one\n* two\n```\ncode\n```\n";
assert_eq!(
plain_lines(text),
[
"Ruby",
"Adds rubies. See the wiki.",
"• one",
"• two",
"code"
]
);
}
}
+306 -60
View File
@@ -31,6 +31,30 @@ fn percent(caption: &str, value: f32) -> Text {
],
)
}
/// `text` cut into lines of at most `width` characters, at spaces where it has them.
fn wrap(text: &str, width: usize) -> Vec<String> {
let mut lines = Vec::new();
let mut line = String::new();
for word in text.split_whitespace() {
let len = line.chars().count();
if len > 0 && len + 1 + word.chars().count() > width {
lines.push(std::mem::take(&mut line));
}
if !line.is_empty() {
line.push(' ');
}
line.push_str(word);
while line.chars().count() > width {
let rest: String = line.chars().skip(width).collect();
line = line.chars().take(width).collect();
lines.push(std::mem::replace(&mut line, rest));
}
}
if !line.is_empty() {
lines.push(line);
}
lines
}
fn on_off(v: bool) -> Text {
tr(if v { "options.on" } else { "options.off" })
}
@@ -1254,6 +1278,10 @@ pub enum Page {
Font,
Packs,
Mods,
/// Browse mods: the registry's content mods, searched (`mod_browser`).
ModBrowser,
/// One registry project's page: `OptionsUi::mod_project`.
ModProject,
/// A native mod's settings page: its index in `mods.installed`.
NativeMod(usize),
/// Horizon's shader packs, either kind (`shader_pack_list`).
@@ -1332,6 +1360,12 @@ enum Act {
NativeKey(usize, usize),
NativeButton(usize, usize),
OpenModFolder,
/// Browse mods: the page of listing `.0` of `mod_browser`.
ModProject(usize),
/// The open project page's Install or Update.
InstallMod,
/// The open project page's page on the website.
OpenModPage,
/// Accessibility's "Accessibility Help" link
/// (`AccessibilityOptionsScreen.addFooter`'s openLinkButton).
AccessibilityHelp,
@@ -1468,6 +1502,12 @@ pub enum Event {
/// Data Packs' Open Pack Folder: create the folder if needed and open it.
OpenDataPackFolder(std::path::PathBuf),
OpenModFolder,
/// Browse mods opened: read the registry's index into `mod_browser`.
BrowseMods,
/// Install (or update) the registry's content mod with this id.
InstallMod(String),
/// Open a registry project's page on the website.
OpenModPage(String),
/// Accessibility's Help link: confirm and open
/// `CommonLinks.ACCESSIBILITY_HELP` over the options screen.
AccessibilityHelp,
@@ -1578,6 +1618,10 @@ pub struct OptionsUi {
language_choice: Option<String>,
language_search: ui::EditBox,
pub(crate) settings_search: ui::EditBox,
/// Browse mods: the registry's projects, filled by the game.
pub mod_browser: crate::mod_browser::ModBrowser,
/// The project whose page is open (`Page::ModProject`).
pub mod_project: String,
/// Horizon's `packBrowser` extra: the pack screen's Add button.
pub pack_browser: bool,
/// Packs: the packs found and the selection the screen opens with.
@@ -1666,6 +1710,8 @@ impl Default for OptionsUi {
language_choice: None,
language_search: search,
settings_search,
mod_browser: Default::default(),
mod_project: String::new(),
pack_browser: false,
pack_infos: Vec::new(),
pack_selection: Vec::new(),
@@ -2156,7 +2202,10 @@ impl OptionsUi {
}
fn settings_search_active(&self) -> bool {
self.settings_search.focused
&& matches!(self.page(), Page::Video | Page::Controls | Page::KeyBinds)
&& matches!(
self.page(),
Page::Video | Page::Controls | Page::KeyBinds | Page::ModBrowser
)
}
/// Whether the resource pack screen is open (not Create World's data packs on the same
/// page).
@@ -2297,7 +2346,10 @@ impl OptionsUi {
self.focus = None;
self.focus_from_keyboard = false;
self.can_change_value = false;
if matches!(page, Page::Video | Page::Controls | Page::KeyBinds) {
if matches!(
page,
Page::Video | Page::Controls | Page::KeyBinds | Page::ModBrowser
) {
self.settings_search.set_value("");
self.settings_search.focused = false;
}
@@ -2423,6 +2475,8 @@ impl OptionsUi {
Page::Font => "options.font.title",
Page::Packs => "resourcePack.title",
Page::Mods => "horizon.pages.mods",
Page::ModBrowser => "horizon.mods.browse.title",
Page::ModProject => "horizon.mods.browse.project",
Page::NativeMod(_) => "Mod Settings",
Page::ShaderPacks => "horizon.pages.shader_packs",
Page::ShaderOptions | Page::NativePackOptions(..) => "horizon.pages.shader_options",
@@ -2489,6 +2543,144 @@ impl OptionsUi {
filtered
}
/// Browse mods: what the registry offers this game, by the search box.
fn mod_browser_rows(&self) -> Vec<Row> {
use crate::mod_browser::Status;
let b = &self.mod_browser;
match &b.status {
Status::Idle | Status::Loading => {
return vec![Row::Note(lang::get("horizon.mods.browse.loading"))];
}
Status::Failed(why) => {
return vec![Row::Note(lang::tr("horizon.mods.browse.failed", &[why]))];
}
Status::Ready => {}
}
let found = b.found(&self.settings_search.value);
if found.is_empty() {
return vec![Row::Note(lang::get("horizon.mods.browse.none"))];
}
let mut rows = Vec::new();
for i in found {
let l = &b.listings[i];
let mut label = Text::literal(format!("{} {}", l.name, l.version));
if l.has_update() {
label = label.append(tr("horizon.mods.browse.has_update"));
} else if l.installed.is_some() {
label = label.append(tr("horizon.mods.browse.is_installed"));
}
rows.push(Row::Buttons(
button(0.0, 0.0, 310.0, label, Act::ModProject(i)),
None,
));
rows.extend(wrap(&l.summary, 64).into_iter().take(1).map(Row::Note));
}
rows
}
/// A registry project's page: what it is, Install or Update, its switch
/// once installed, its description and changelog.
fn mod_project_rows(&self, s: &Settings) -> Vec<Row> {
let b = &self.mod_browser;
let Some(l) = b.listing(&self.mod_project) else {
return vec![Row::Note(lang::get("horizon.mods.browse.none"))];
};
let mut rows = vec![Row::Note(format!("{} {}", l.name, l.version))];
let by = [
lang::tr("horizon.mods.browse.by", &[&l.authors.join(", ")]),
l.license.clone(),
l.published.clone(),
];
let by: Vec<&str> = by
.iter()
.map(String::as_str)
.filter(|t| !t.is_empty())
.collect();
rows.push(Row::Note(by.join(" · ")));
let labels: Vec<&str> = l
.categories
.iter()
.chain(&l.tags)
.map(String::as_str)
.collect();
if !labels.is_empty() {
rows.push(Row::Note(labels.join(", ")));
}
let installing = b.installing.as_deref() == Some(l.id.as_str());
let install = match (&l.installed, installing) {
(_, true) => inactive(button(
0.0,
0.0,
150.0,
tr("horizon.mods.browse.installing"),
Act::None,
)),
(None, false) => button(
0.0,
0.0,
150.0,
tr("horizon.mods.browse.install"),
Act::InstallMod,
),
(Some(_), false) if l.has_update() => button(
0.0,
0.0,
150.0,
tr("horizon.mods.browse.update"),
Act::InstallMod,
),
(Some(_), false) => inactive(button(
0.0,
0.0,
150.0,
tr("horizon.mods.browse.installed"),
Act::None,
)),
};
let page = button(
0.0,
0.0,
150.0,
tr("horizon.mods.browse.open_page"),
Act::OpenModPage,
);
let row = s.mods.installed.iter().position(|m| m.id == l.id && !m.dev);
match row.filter(|_| l.installed.is_some()) {
Some(i) => {
let label =
Text::literal(format!("{}: ", lang::get("horizon.mods.browse.enabled")))
.append(on_off(s.mods.is_on(i)));
let toggle = button(0.0, 0.0, 150.0, label, Act::ToggleMod(i));
rows.push(Row::Buttons(install, Some(toggle)));
rows.push(Row::Buttons(page, None));
}
None => rows.push(Row::Buttons(install, Some(page))),
}
if let Some((message, _)) = &b.message {
rows.extend(wrap(message, 64).into_iter().map(Row::Note));
}
let description = crate::mod_browser::plain_lines(if l.description.is_empty() {
&l.summary
} else {
&l.description
});
rows.extend(
description
.iter()
.flat_map(|line| wrap(line, 64))
.map(Row::Note),
);
let changelog = crate::mod_browser::plain_lines(&l.changelog);
if !changelog.is_empty() {
rows.push(Row::Heading("horizon.mods.browse.changelog".into()));
rows.extend(
changelog
.iter()
.flat_map(|line| wrap(line, 64))
.map(Row::Note),
);
}
rows
}
/// A native mod's page: its name, its keys as Key Binds rows (the
/// player's choice, else the default), then its buttons.
fn native_rows(&self, s: &Settings, i: usize) -> Vec<Row> {
@@ -2857,61 +3049,64 @@ impl OptionsUi {
}
Page::Font => pairs(&[Opt::ForceUnicode, Opt::JapaneseGlyphs]),
Page::Mods => {
let browse = button(
0.0,
0.0,
310.0,
tr("horizon.mods.browse"),
Act::Push(Page::ModBrowser),
);
let mut rows = vec![Row::Buttons(browse, None)];
if s.mods.installed.is_empty() {
return vec![Row::Header("horizon.mods.empty")];
rows.push(Row::Header("horizon.mods.empty"));
return rows;
}
s.mods
.installed
.iter()
.enumerate()
.map(|(i, installed)| {
let mut label = Text::option_name_value(
Text::literal(installed.title.clone()),
on_off(s.mods.is_on(i)),
rows.extend(s.mods.installed.iter().enumerate().map(|(i, installed)| {
let mut label = Text::option_name_value(
Text::literal(installed.title.clone()),
on_off(s.mods.is_on(i)),
);
if installed.problem.as_deref() == Some(crate::mod_list::NOT_BUILT) {
label = label.append(tr("horizon.mods.not_built"));
} else if installed.problem.is_some() {
label = label.append(tr("horizon.mods.stopped"));
} else if installed.dev {
label = label.append(tr("horizon.mods.dev"));
}
// A content mod's set feeds the block-state tables the
// open world's chunks were decoded with: changing it
// mid-world remaps their ids (Forge/Fabric freeze the
// registry before a world opens). A native mod toggles
// live through `native_on`, so it stays available.
let content = installed.native.is_none();
if self.in_world && content {
label = label.append(tr("horizon.mods.in_world"));
}
let dead = installed.dev || installed.id.is_empty() || self.in_world && content;
// Only native mods with actual settings need a second button.
if installed
.native
.as_ref()
.is_some_and(|page| !page.keys.is_empty() || !page.buttons.is_empty())
{
let toggle = button(0.0, 0.0, 150.0, label, Act::ToggleMod(i));
let settings = button(
0.0,
0.0,
150.0,
tr("horizon.mods.settings"),
Act::ModSettings(i),
);
if installed.problem.as_deref() == Some(crate::mod_list::NOT_BUILT) {
label = label.append(tr("horizon.mods.not_built"));
} else if installed.problem.is_some() {
label = label.append(tr("horizon.mods.stopped"));
} else if installed.dev {
label = label.append(tr("horizon.mods.dev"));
}
// A content mod's set feeds the block-state tables the
// open world's chunks were decoded with: changing it
// mid-world remaps their ids (Forge/Fabric freeze the
// registry before a world opens). A native mod toggles
// live through `native_on`, so it stays available.
let content = installed.native.is_none();
if self.in_world && content {
label = label.append(tr("horizon.mods.in_world"));
}
let dead =
installed.dev || installed.id.is_empty() || self.in_world && content;
// Only native mods with actual settings need a second button.
if installed
.native
.as_ref()
.is_some_and(|page| !page.keys.is_empty() || !page.buttons.is_empty())
{
let toggle = button(0.0, 0.0, 150.0, label, Act::ToggleMod(i));
let settings = button(
0.0,
0.0,
150.0,
tr("horizon.mods.settings"),
Act::ModSettings(i),
);
Row::Buttons(
if dead { inactive(toggle) } else { toggle },
Some(settings),
)
} else {
let widget = button(0.0, 0.0, 310.0, label, Act::ToggleMod(i));
Row::Buttons(if dead { inactive(widget) } else { widget }, None)
}
})
.collect()
Row::Buttons(if dead { inactive(toggle) } else { toggle }, Some(settings))
} else {
let widget = button(0.0, 0.0, 310.0, label, Act::ToggleMod(i));
Row::Buttons(if dead { inactive(widget) } else { widget }, None)
}
}));
rows
}
Page::ModBrowser => self.mod_browser_rows(),
Page::ModProject => self.mod_project_rows(s),
Page::NativeMod(i) => self.native_rows(s, i),
Page::ShaderPacks => {
if s.shader_packs.is_empty() {
@@ -2989,7 +3184,10 @@ impl OptionsUi {
let mut rows = ListRows::default();
let page = self.page();
let cx = (w / 2.0).floor();
if matches!(page, Page::Video | Page::Controls | Page::KeyBinds) {
if matches!(
page,
Page::Video | Page::Controls | Page::KeyBinds | Page::ModBrowser
) {
self.settings_search.x = cx - 100.0;
self.settings_search.y = 17.0;
}
@@ -3331,12 +3529,12 @@ impl OptionsUi {
// Drawn by `pack_screen`.
Page::Packs => {}
_ => {
if matches!(page, Page::Video | Page::Controls) {
if matches!(page, Page::Video | Page::Controls | Page::ModBrowser) {
top = 38.0;
}
out.push(Widget {
x: 0.0,
y: if matches!(page, Page::Video | Page::Controls) {
y: if matches!(page, Page::Video | Page::Controls | Page::ModBrowser) {
4.0
} else {
12.0
@@ -3915,23 +4113,30 @@ impl OptionsUi {
}
self.language_search = search;
}
if matches!(self.page(), Page::Video | Page::Controls | Page::KeyBinds) {
if matches!(
self.page(),
Page::Video | Page::Controls | Page::KeyBinds | Page::ModBrowser
) {
let mut search = self.settings_search.clone();
if self.focus == Some(FocusId::Search) {
search.focused = true;
}
search.draw(batch, atlas, None);
let hint = match self.page() {
Page::ModBrowser => "horizon.mods.browse.search",
_ => "horizon.options.search",
};
// Horizon's search box sits in the header, before the list.
crate::widgets::last_narratable(|n| {
n.order = -1;
if let crate::widgets::What::EditBox { message, .. } = &mut n.what {
*message = tr("horizon.options.search").plain();
*message = tr(hint).plain();
}
});
if search.value.is_empty() && !search.focused {
batch.text_styled(
atlas,
&tr("horizon.options.search").with_color(text::GRAY).italic(),
&tr(hint).with_color(text::GRAY).italic(),
search.text_x(),
search.text_y(),
u32::MAX,
@@ -4091,7 +4296,12 @@ impl OptionsUi {
self.size = size;
self.framebuffer = framebuffer;
let mut events = Vec::new();
if !drag && matches!(self.page(), Page::Video | Page::Controls | Page::KeyBinds) {
if !drag
&& matches!(
self.page(),
Page::Video | Page::Controls | Page::KeyBinds | Page::ModBrowser
)
{
let search = &mut self.settings_search;
search.focused = ui::hovered((x, y), search.x, search.y, search.width, search.height);
if search.focused {
@@ -4247,6 +4457,9 @@ impl OptionsUi {
if p == Page::Music {
events.push(Event::ListMusicTracks);
}
if p == Page::ModBrowser {
events.push(Event::BrowseMods);
}
self.push(p)
}
Act::Done => events.extend(self.back(s)),
@@ -4297,6 +4510,21 @@ impl OptionsUi {
}
Act::NativeButton(i, b) => events.push(Event::NativeButton(i, b)),
Act::OpenModFolder => events.push(Event::OpenModFolder),
Act::ModProject(i) => {
if let Some(listing) = self.mod_browser.listings.get(i) {
self.mod_project = listing.id.clone();
self.push(Page::ModProject);
}
}
Act::InstallMod => {
self.mod_browser.message = None;
events.push(Event::InstallMod(self.mod_project.clone()));
}
Act::OpenModPage => {
if let Some(l) = self.mod_browser.listing(&self.mod_project) {
events.push(Event::OpenModPage(l.page.clone()));
}
}
Act::PvpPreset => {
crate::pvp::apply_preset(s);
events.push(Event::Changed);
@@ -5202,6 +5430,9 @@ impl OptionsUi {
if p == Page::Music {
events.push(Event::ListMusicTracks);
}
if p == Page::ModBrowser {
events.push(Event::BrowseMods);
}
self.push(p);
}
Act::Done => {
@@ -5259,6 +5490,21 @@ impl OptionsUi {
}
Act::NativeButton(i, b) => events.push(Event::NativeButton(i, b)),
Act::OpenModFolder => events.push(Event::OpenModFolder),
Act::ModProject(i) => {
if let Some(listing) = self.mod_browser.listings.get(i) {
self.mod_project = listing.id.clone();
self.push(Page::ModProject);
}
}
Act::InstallMod => {
self.mod_browser.message = None;
events.push(Event::InstallMod(self.mod_project.clone()));
}
Act::OpenModPage => {
if let Some(l) = self.mod_browser.listing(&self.mod_project) {
events.push(Event::OpenModPage(l.page.clone()));
}
}
Act::PvpPreset => {
crate::pvp::apply_preset(s);
events.push(Event::Changed);
+13 -9
View File
@@ -17,6 +17,7 @@ use horizon_core::{
geometry::{Aabb, Axis, Vec3, trig},
random::{LegacyRandom, RandomSource},
};
use horizon_protocol::entity_data::PositionSource;
use horizon_world::block_collision::BlockCollisionRegistry;
use std::{
array,
@@ -50,9 +51,10 @@ pub struct ParticleOptions {
/// `GeyserParticleOptions.waterBlocks` and `GeyserBaseParticleOptions`'
/// `waterBlocks` and `burstImpulseBase` (0 where the type has none).
pub geyser: Option<(i32, f32)>,
/// `VibrationParticleOption`: the listener the signal flies to and its
/// arrival time in ticks (`ParticleEngine::vibration` is the same particle).
pub vibration: Option<([f64; 3], i32)>,
/// `VibrationParticleOption`: the listener's `PositionSource`, the point
/// the signal flies to and its arrival time in ticks
/// (`ParticleEngine::vibration` is the same particle).
pub vibration: Option<(PositionSource, [f64; 3], i32)>,
/// A native mod's own particle type, by its namespaced name (`mymod:spark`):
/// `SimpleParticleType` plus the provider `particles/<name>.json` names.
pub mod_particle: Option<String>,
@@ -94,10 +96,11 @@ impl ParticleOptions {
..Self::simple(ty)
}
}
/// `VibrationParticleOption(destination, arrivalInTicks)`.
pub fn vibration(dest: [f64; 3], ticks: i32) -> Self {
/// `VibrationParticleOption(destination, arrivalInTicks)`: the listener's
/// position source and the point this engine flies the signal to.
pub fn vibration(source: PositionSource, dest: [f64; 3], ticks: i32) -> Self {
Self {
vibration: Some((dest, ticks)),
vibration: Some((source, dest, ticks)),
..Self::simple(ParticleType::Vibration)
}
}
@@ -2988,8 +2991,8 @@ impl ParticleEngine {
// the listener the signal flies to and its arrival time; the sprite
// is the set's own draw from the engine's random.
T::Vibration => {
let (dest, ticks) = o.vibration?;
let mut q = Self::vibration_particle(p, dest, ticks);
let (_, dest, ticks) = o.vibration.as_ref()?;
let mut q = Self::vibration_particle(p, *dest, *ticks);
q.set = set;
q.sprite = self.sprite_from_set(ty);
q
@@ -5644,7 +5647,8 @@ mod tests {
#[test]
fn a_vibration_option_makes_the_signal_its_provider_draws() {
let mut engine = ParticleEngine::new(Path::new(""), &HashMap::new(), &HashSet::new());
let options = ParticleOptions::vibration([10.5, 70.5, -3.5], 20);
let options =
ParticleOptions::vibration(PositionSource::Block([10, 70, -4]), [10.5, 70.5, -3.5], 20);
// Within the camera's 32 blocks, so only the provider decides.
engine.add_with(&options, [0.5, 1.5, 0.5], [0.0; 3], false, false);
assert_eq!(engine.made().get("vibration"), Some(&1));
+191 -1
View File
@@ -575,8 +575,53 @@ pub struct Hud {
/// Hits in a row the server confirmed, until this player is hurt or 3 seconds pass.
pub combo: bool,
pub combo_corner: Corner,
/// Frames drawn in the last second.
pub fps: bool,
pub fps_corner: Corner,
/// Left and right clicks in the last second.
pub cps: bool,
pub cps_corner: Corner,
/// The movement keys, mouse buttons and jump, lit while held, with clicks per second.
pub keys: bool,
pub keys_corner: Corner,
/// The computer's local time.
pub clock: bool,
pub clock_corner: Corner,
/// How far the last hit landed from the eyes, for 3 seconds; it only measures.
pub reach: bool,
pub reach_corner: Corner,
/// Horizontal speed in blocks per second.
pub speed: bool,
pub speed_corner: Corner,
/// A dark box behind each widget.
pub background: bool,
/// The boxes' opacity, in percent.
pub opacity: u8,
/// The widgets' text colour (durability keeps its own).
pub text: Colour,
/// A shadow under the widgets' text, as vanilla's HUD text has.
pub shadow: bool,
}
impl Hud {
/// Whether any widget is on: with none, the HUD draws nothing and reads nothing.
pub fn any(&self) -> bool {
[
self.armour,
self.effects,
self.held,
self.ping,
self.coords,
self.server,
self.combo,
self.fps,
self.cps,
self.keys,
self.clock,
self.reach,
self.speed,
]
.contains(&true)
}
}
impl Default for Hud {
fn default() -> Self {
@@ -596,11 +641,35 @@ impl Default for Hud {
server_corner: Corner::TopLeft,
combo: false,
combo_corner: Corner::TopLeft,
fps: false,
fps_corner: Corner::TopLeft,
cps: false,
cps_corner: Corner::TopLeft,
keys: false,
keys_corner: Corner::BottomLeft,
clock: false,
clock_corner: Corner::TopRight,
reach: false,
reach_corner: Corner::TopLeft,
speed: false,
speed_corner: Corner::TopLeft,
background: true,
opacity: HUD_OPACITY,
text: Colour::White,
shadow: true,
}
}
}
pub use crate::extras::Corner;
/// The widgets' boxes at first: the extras' 0x78 alpha, 47%.
pub const HUD_OPACITY: u8 = 47;
pub const HUD_OPACITIES: (u8, u8) = (0, 100);
impl Hud {
/// The boxes' colour, ARGB.
pub fn background_argb(&self) -> u32 {
alpha(self.opacity) << 24
}
}
/// The value of the view options while they follow the world.
fn world_label() -> String {
crate::lang::get_or("horizon.pvp.view.world", "World's")
@@ -690,6 +759,8 @@ pub struct Pvp {
pub hud: Hud,
pub tweaks: Tweaks,
pub chat: ChatOptions,
/// Where each HUD widget sits and its size.
pub layout: crate::pvp_hud::Layout,
}
fn flag(value: &str, d: bool) -> bool {
match value {
@@ -743,6 +814,14 @@ impl Pvp {
"hudHeld" => u.held = flag(value, u.held),
"hudHeldCorner" => u.held_corner = Corner::parse(value, u.held_corner),
"hudBackground" => u.background = flag(value, u.background),
"hudOpacity" => u.opacity = num(value, HUD_OPACITIES, u.opacity),
"hudTextColour" => {
u.text = Colour::parse(value)
.filter(|c| *c != Colour::Inverted)
.unwrap_or(u.text)
}
"hudShadow" => u.shadow = flag(value, u.shadow),
"hudPlace" => self.layout.parse(value),
"hudPing" => u.ping = flag(value, u.ping),
"hudPingCorner" => u.ping_corner = Corner::parse(value, u.ping_corner),
"hudCoords" => u.coords = flag(value, u.coords),
@@ -751,6 +830,18 @@ impl Pvp {
"hudServerCorner" => u.server_corner = Corner::parse(value, u.server_corner),
"hudCombo" => u.combo = flag(value, u.combo),
"hudComboCorner" => u.combo_corner = Corner::parse(value, u.combo_corner),
"hudFps" => u.fps = flag(value, u.fps),
"hudFpsCorner" => u.fps_corner = Corner::parse(value, u.fps_corner),
"hudCps" => u.cps = flag(value, u.cps),
"hudCpsCorner" => u.cps_corner = Corner::parse(value, u.cps_corner),
"hudKeys" => u.keys = flag(value, u.keys),
"hudKeysCorner" => u.keys_corner = Corner::parse(value, u.keys_corner),
"hudClock" => u.clock = flag(value, u.clock),
"hudClockCorner" => u.clock_corner = Corner::parse(value, u.clock_corner),
"hudReach" => u.reach = flag(value, u.reach),
"hudReachCorner" => u.reach_corner = Corner::parse(value, u.reach_corner),
"hudSpeed" => u.speed = flag(value, u.speed),
"hudSpeedCorner" => u.speed_corner = Corner::parse(value, u.speed_corner),
"numericEnchants" => t.numeric_enchants = flag(value, t.numeric_enchants),
"lowFire" => t.fire_lower = num(value, FIRE_LOWER, t.fire_lower),
"shieldSize" => t.shield_size = num(value, SHIELD_SIZES, t.shield_size),
@@ -838,6 +929,34 @@ impl Pvp {
u.combo,
u.combo_corner.name(),
);
let _ = write!(
out,
"hudFps:{}\nhudFpsCorner:{}\nhudCps:{}\nhudCpsCorner:{}\nhudKeys:{}\nhudKeysCorner:{}\n",
u.fps,
u.fps_corner.name(),
u.cps,
u.cps_corner.name(),
u.keys,
u.keys_corner.name(),
);
let _ = write!(
out,
"hudClock:{}\nhudClockCorner:{}\nhudReach:{}\nhudReachCorner:{}\nhudSpeed:{}\nhudSpeedCorner:{}\n",
u.clock,
u.clock_corner.name(),
u.reach,
u.reach_corner.name(),
u.speed,
u.speed_corner.name(),
);
let _ = write!(
out,
"hudOpacity:{}\nhudTextColour:{}\nhudShadow:{}\n",
u.opacity,
u.text.name(),
u.shadow,
);
self.layout.serialize(out);
let t = &self.tweaks;
let _ = write!(
out,
@@ -955,7 +1074,25 @@ opts! {
HudCombo, "hud_combo", "Combo counter",
"Hits in a row the server confirmed, until you are hurt or 3 seconds pass without one.";
HudComboCorner, "hud_combo_corner", "Combo corner", "Where the combo shows.";
HudFps, "hud_fps", "FPS", "Frames drawn in the last second.";
HudFpsCorner, "hud_fps_corner", "FPS corner", "Where the FPS shows.";
HudCps, "hud_cps", "Clicks per second", "Your left and right clicks in the last second.";
HudCpsCorner, "hud_cps_corner", "CPS corner", "Where the clicks per second show.";
HudKeys, "hud_keys", "Keystrokes",
"Your movement keys, mouse buttons and jump, lit while you hold them, with clicks per second.";
HudKeysCorner, "hud_keys_corner", "Keystrokes corner", "Where the keystrokes show.";
HudClock, "hud_clock", "Clock", "Your computer's time.";
HudClockCorner, "hud_clock_corner", "Clock corner", "Where the clock shows.";
HudReach, "hud_reach", "Reach",
"How far from your eyes your last hit landed, for 3 seconds. It only measures: your reach stays vanilla's.";
HudReachCorner, "hud_reach_corner", "Reach corner", "Where the reach shows.";
HudSpeed, "hud_speed", "Speed", "How fast you move across the ground, in blocks per second.";
HudSpeedCorner, "hud_speed_corner", "Speed corner", "Where the speed shows.";
HudBackground, "hud_background", "Widget backgrounds", "A dark box behind each widget.";
HudOpacity, "hud_opacity", "Background opacity", "How dark the boxes behind the widgets are.";
HudTextColour, "hud_text_colour", "Text colour",
"The widgets' text colour. Durability keeps its green to red.";
HudShadow, "hud_shadow", "Text shadow", "A shadow under the widgets' text, as vanilla's HUD text has.";
NumericEnchants, "numeric_enchants", "Enchantment levels as numbers",
"Tooltips and the enchanting table show Sharpness 5 instead of Sharpness V.";
FireLower, "fire_lower", "Lower fire",
@@ -1030,7 +1167,22 @@ pub fn rows() -> Vec<Result<Opt, &'static str>> {
HudServerCorner,
HudCombo,
HudComboCorner,
HudFps,
HudFpsCorner,
HudCps,
HudCpsCorner,
HudKeys,
HudKeysCorner,
HudClock,
HudClockCorner,
HudReach,
HudReachCorner,
HudSpeed,
HudSpeedCorner,
HudBackground,
HudOpacity,
HudTextColour,
HudShadow,
]
.map(Ok),
);
@@ -1054,7 +1206,15 @@ impl Opt {
OutlineColour | OutlineOpacity | OutlineThickness | OutlineFill => Some(Outline),
HitColour | HitOpacity => Some(Hit),
HudArmour | HudEffects | HudHeld | HudPing | HudCoords | HudServer | HudCombo
| HudBackground | NumericEnchants => None,
| HudFps | HudCps | HudKeys | HudClock | HudReach | HudSpeed | HudBackground
| HudTextColour | HudShadow | NumericEnchants => None,
HudOpacity => Some(HudBackground),
HudFpsCorner => Some(HudFps),
HudCpsCorner => Some(HudCps),
HudKeysCorner => Some(HudKeys),
HudClockCorner => Some(HudClock),
HudReachCorner => Some(HudReach),
HudSpeedCorner => Some(HudSpeed),
FireLower | ShieldSize | TotemSize | GlintColour | ClearWater | ClearLava => None,
ViewTime | ViewWeather => None,
ChatTimestamps | ChatCompact | ChatCopy | ChatSearch => None,
@@ -1081,10 +1241,17 @@ impl Opt {
Opt::HudEffects => p.hud.effects,
Opt::HudHeld => p.hud.held,
Opt::HudBackground => p.hud.background,
Opt::HudShadow => p.hud.shadow,
Opt::HudPing => p.hud.ping,
Opt::HudCoords => p.hud.coords,
Opt::HudServer => p.hud.server,
Opt::HudCombo => p.hud.combo,
Opt::HudFps => p.hud.fps,
Opt::HudCps => p.hud.cps,
Opt::HudKeys => p.hud.keys,
Opt::HudClock => p.hud.clock,
Opt::HudReach => p.hud.reach,
Opt::HudSpeed => p.hud.speed,
Opt::NumericEnchants => p.tweaks.numeric_enchants,
Opt::ClearWater => p.tweaks.clear_water,
Opt::ClearLava => p.tweaks.clear_lava,
@@ -1124,6 +1291,14 @@ impl Opt {
Opt::HudCoordsCorner => corner_label(p.hud.coords_corner),
Opt::HudServerCorner => corner_label(p.hud.server_corner),
Opt::HudComboCorner => corner_label(p.hud.combo_corner),
Opt::HudFpsCorner => corner_label(p.hud.fps_corner),
Opt::HudCpsCorner => corner_label(p.hud.cps_corner),
Opt::HudKeysCorner => corner_label(p.hud.keys_corner),
Opt::HudClockCorner => corner_label(p.hud.clock_corner),
Opt::HudReachCorner => corner_label(p.hud.reach_corner),
Opt::HudSpeedCorner => corner_label(p.hud.speed_corner),
Opt::HudOpacity => format!("{}%", p.hud.opacity),
Opt::HudTextColour => p.hud.text.label(),
Opt::FireLower => match p.tweaks.fire_lower {
0 => crate::lang::get_or("Off", "Off"),
v => format!("{v}%"),
@@ -1191,6 +1366,9 @@ impl Opt {
Opt::HudHeld => u.held = !u.held,
Opt::HudHeldCorner => u.held_corner = corner(u.held_corner),
Opt::HudBackground => u.background = !u.background,
Opt::HudOpacity => u.opacity = step_by(u.opacity, HUD_OPACITIES, 10, back),
Opt::HudTextColour => u.text = u.text.step_solid(back),
Opt::HudShadow => u.shadow = !u.shadow,
Opt::HudPing => u.ping = !u.ping,
Opt::HudPingCorner => u.ping_corner = corner(u.ping_corner),
Opt::HudCoords => u.coords = !u.coords,
@@ -1199,6 +1377,18 @@ impl Opt {
Opt::HudServerCorner => u.server_corner = corner(u.server_corner),
Opt::HudCombo => u.combo = !u.combo,
Opt::HudComboCorner => u.combo_corner = corner(u.combo_corner),
Opt::HudFps => u.fps = !u.fps,
Opt::HudFpsCorner => u.fps_corner = corner(u.fps_corner),
Opt::HudCps => u.cps = !u.cps,
Opt::HudCpsCorner => u.cps_corner = corner(u.cps_corner),
Opt::HudKeys => u.keys = !u.keys,
Opt::HudKeysCorner => u.keys_corner = corner(u.keys_corner),
Opt::HudClock => u.clock = !u.clock,
Opt::HudClockCorner => u.clock_corner = corner(u.clock_corner),
Opt::HudReach => u.reach = !u.reach,
Opt::HudReachCorner => u.reach_corner = corner(u.reach_corner),
Opt::HudSpeed => u.speed = !u.speed,
Opt::HudSpeedCorner => u.speed_corner = corner(u.speed_corner),
Opt::NumericEnchants => p.tweaks.numeric_enchants = !p.tweaks.numeric_enchants,
Opt::FireLower => t.fire_lower = step_by(t.fire_lower, FIRE_LOWER, 10, back),
Opt::ShieldSize => t.shield_size = step_by(t.shield_size, SHIELD_SIZES, 10, back),
+451
View File
@@ -214,6 +214,320 @@ impl Combo {
}
}
/// Clicks per second: the presses of the last second, kept for the widgets that are on.
#[derive(Default)]
pub struct Clicks {
/// Press times in seconds, oldest first; at most [`Clicks::KEEP`].
times: std::collections::VecDeque<f64>,
}
impl Clicks {
/// More than any hand clicks in a second: the ring never grows past it.
const KEEP: usize = 64;
pub fn press(&mut self, now: f64) {
if self.times.len() == Self::KEEP {
self.times.pop_front();
}
self.times.push_back(now);
}
/// The presses in the second up to `now`.
pub fn per_second(&mut self, now: f64) -> u32 {
while self.times.front().is_some_and(|&t| now - t >= 1.0) {
self.times.pop_front();
}
self.times.len() as u32
}
}
/// Horizontal speed in blocks per second, from the player's own position sampled at most
/// every [`Speed::SAMPLE`] seconds (nothing is asked of the server).
#[derive(Default)]
pub struct Speed {
last: Option<([f64; 2], f64)>,
/// Tenths of a block per second.
tenths: u32,
}
impl Speed {
pub const SAMPLE: f64 = 0.25;
pub fn sample(&mut self, x: f64, z: f64, now: f64) -> u32 {
match self.last {
Some((_, at)) if now - at < Self::SAMPLE => {}
Some(([lx, lz], at)) => {
let d = ((x - lx).powi(2) + (z - lz).powi(2)).sqrt();
// A teleport or respawn isn't speed.
let v = d / (now - at);
self.tenths = if v > 200.0 {
0
} else {
(v * 10.0).round() as u32
};
self.last = Some(([x, z], now));
}
None => self.last = Some(([x, z], now)),
}
self.tenths
}
}
/// The reach display: how far the last hit this player made was, measured from the eyes to
/// the point the crosshair's ray met the target's box. It measures what the client already
/// computed for the attack and changes nothing about it.
#[derive(Default)]
pub struct Reach {
last: Option<(f64, f64)>,
}
impl Reach {
/// How long the last hit's distance stays shown.
pub const SHOWN: f64 = 3.0;
pub fn hit(&mut self, distance: f64, now: f64) {
self.last = Some((distance, now));
}
/// Hundredths of a block, while the last hit is recent.
pub fn hundredths(&self, now: f64) -> Option<u32> {
let (d, at) = self.last?;
(now - at <= Self::SHOWN).then(|| (d * 100.0).round() as u32)
}
}
/// `n` hundredths as "3.05".
pub fn hundredths(n: u32) -> String {
format!("{}.{:02}", n / 100, n % 100)
}
/// `n` tenths as "4.3".
pub fn tenths(n: u32) -> String {
format!("{}.{}", n / 10, n % 10)
}
/// The local time as "14:05".
pub fn clock(hour: u8, minute: u8) -> String {
format!("{hour:02}:{minute:02}")
}
/// The keystrokes widget's keys, in drawing order.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Key {
Forward,
Left,
Back,
Right,
Attack,
Use,
Jump,
}
impl Key {
pub const ALL: [Key; 7] = [
Key::Forward,
Key::Left,
Key::Back,
Key::Right,
Key::Attack,
Key::Use,
Key::Jump,
];
/// The key mapping it shows.
pub fn mapping(self) -> &'static str {
match self {
Key::Forward => "key.forward",
Key::Left => "key.left",
Key::Back => "key.back",
Key::Right => "key.right",
Key::Attack => "key.attack",
Key::Use => "key.use",
Key::Jump => "key.jump",
}
}
}
/// The keystrokes' key size and the gap between keys, in GUI pixels.
pub const KEY: f32 = 22.0;
pub const KEY_GAP: f32 = 2.0;
/// The space bar's height.
pub const SPACE: f32 = 12.0;
/// Where each key of the keystrokes widget sits in its box: W above A S D, the two mouse
/// buttons under them, the space bar at the bottom, as `(x, y, w, h)`.
pub fn key_rect(key: Key) -> (f32, f32, f32, f32) {
let step = KEY + KEY_GAP;
let full = 3.0 * KEY + 2.0 * KEY_GAP;
let half = (full - KEY_GAP) / 2.0;
match key {
Key::Forward => (step, 0.0, KEY, KEY),
Key::Left => (0.0, step, KEY, KEY),
Key::Back => (step, step, KEY, KEY),
Key::Right => (2.0 * step, step, KEY, KEY),
Key::Attack => (0.0, 2.0 * step, half, KEY),
Key::Use => (half + KEY_GAP, 2.0 * step, half, KEY),
Key::Jump => (0.0, 3.0 * step, full, SPACE),
}
}
/// The keystrokes widget's size.
pub fn keys_size() -> (f32, f32) {
let (_, y, w, h) = key_rect(Key::Jump);
(w, y + h)
}
/// The HUD widgets, for their places on screen ([`Layout`]).
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum WidgetId {
Armour,
Effects,
Held,
Ping,
Coords,
Server,
Combo,
Fps,
Cps,
Keys,
Clock,
Reach,
Speed,
}
impl WidgetId {
pub const ALL: [WidgetId; 13] = [
WidgetId::Armour,
WidgetId::Effects,
WidgetId::Held,
WidgetId::Ping,
WidgetId::Coords,
WidgetId::Server,
WidgetId::Combo,
WidgetId::Fps,
WidgetId::Cps,
WidgetId::Keys,
WidgetId::Clock,
WidgetId::Reach,
WidgetId::Speed,
];
pub fn name(self) -> &'static str {
match self {
WidgetId::Armour => "armour",
WidgetId::Effects => "effects",
WidgetId::Held => "held",
WidgetId::Ping => "ping",
WidgetId::Coords => "coords",
WidgetId::Server => "server",
WidgetId::Combo => "combo",
WidgetId::Fps => "fps",
WidgetId::Cps => "cps",
WidgetId::Keys => "keys",
WidgetId::Clock => "clock",
WidgetId::Reach => "reach",
WidgetId::Speed => "speed",
}
}
pub fn index(self) -> usize {
self as usize
}
}
/// Where a widget sits: in its corner, stacked with the others there (`at` is `None`), or at a
/// place the player dragged it to, as fractions of the room the screen leaves around the box
/// (0 at the left or top edge, 1 at the right or bottom), so it stays on screen at any size.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Place {
pub at: Option<(f32, f32)>,
/// Its size in percent.
pub scale: u8,
}
impl Default for Place {
fn default() -> Self {
Self {
at: None,
scale: 100,
}
}
}
pub const SCALES: (u8, u8) = (50, 200);
/// Every widget's place.
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct Layout(pub [Place; 13]);
impl Layout {
pub fn get(&self, id: WidgetId) -> Place {
self.0[id.index()]
}
pub fn get_mut(&mut self, id: WidgetId) -> &mut Place {
&mut self.0[id.index()]
}
/// One `hudPlace` value: `armour,0.25,0.5,150`, or `armour,corner,,150`.
pub fn parse(&mut self, value: &str) {
let mut parts = value.split(',');
let Some(id) = parts
.next()
.and_then(|n| WidgetId::ALL.into_iter().find(|w| w.name() == n))
else {
return;
};
let (x, y, scale) = (parts.next(), parts.next(), parts.next());
let frac = |v: Option<&str>| {
v.and_then(|v| v.parse::<f32>().ok())
.filter(|v| v.is_finite())
.map(|v| v.clamp(0.0, 1.0))
};
let place = self.get_mut(id);
place.at = frac(x).zip(frac(y));
if let Some(s) = scale.and_then(|s| s.parse::<u8>().ok()) {
place.scale = s.clamp(SCALES.0, SCALES.1);
}
}
/// The `hudPlace` lines of the widgets that left their corner or their size.
pub fn serialize(&self, out: &mut String) {
use std::fmt::Write;
for id in WidgetId::ALL {
let p = self.get(id);
if p == Place::default() {
continue;
}
let _ = match p.at {
Some((x, y)) => writeln!(out, "hudPlace:{},{x:.4},{y:.4},{}", id.name(), p.scale),
None => writeln!(out, "hudPlace:{},corner,,{}", id.name(), p.scale),
};
}
}
}
/// A box `w` x `h` placed at fractions `(fx, fy)` of the room left on a `screen`.
pub fn from_fractions((fx, fy): (f32, f32), (w, h): (f32, f32), screen: (f32, f32)) -> (f32, f32) {
(
(fx * (screen.0 - w).max(0.0)).round(),
(fy * (screen.1 - h).max(0.0)).round(),
)
}
/// The fractions that put a `w` x `h` box at `(x, y)` on a `screen`, kept on screen.
pub fn to_fractions((x, y): (f32, f32), (w, h): (f32, f32), screen: (f32, f32)) -> (f32, f32) {
let frac = |v: f32, room: f32| {
if room > 0.0 {
(v / room).clamp(0.0, 1.0)
} else {
0.0
}
};
(frac(x, screen.0 - w), frac(y, screen.1 - h))
}
/// How near, in GUI pixels, an edge must come to another to snap to it.
pub const SNAP: f32 = 4.0;
/// Snaps a box's start `x` of length `w` along one axis of length `screen`: to the screen's
/// edges and middle, and to the edges of the `others` boxes (`(start, length)`), where one
/// is within [`SNAP`]. Returns the new start and the line it snapped to, if any.
pub fn snap(x: f32, w: f32, screen: f32, others: &[(f32, f32)]) -> (f32, Option<f32>) {
let mut best: Option<(f32, f32, f32)> = None;
let mut consider = |start: f32, line: f32| {
let d = (start - x).abs();
if d <= SNAP && best.is_none_or(|(b, _, _)| d < b) {
best = Some((d, start, line));
}
};
// The screen's edges, with the corners' margin, and its middle.
consider(2.0, 0.0);
consider(screen - 2.0 - w, screen);
consider((screen - w) / 2.0, screen / 2.0);
for &(o, ow) in others {
// Side by side, or lined up on the same edge.
consider(o + ow, o + ow);
consider(o - w, o);
consider(o, o);
consider(o + ow - w, o + ow);
}
match best {
Some((_, start, line)) => (start.clamp(0.0, (screen - w).max(0.0)), Some(line)),
None => (x.clamp(0.0, (screen - w).max(0.0)), None),
}
}
#[cfg(test)]
mod tests {
use super::*;
@@ -338,4 +652,141 @@ mod tests {
assert_eq!(h, 18.0 + 10.0 + 20.0 + 2.0 * PAD - 2.0);
assert!(size(&[]) == (0.0, 0.0));
}
#[test]
fn clicks_count_the_presses_of_the_last_second() {
let mut c = Clicks::default();
for t in [0.0, 0.1, 0.5, 0.9] {
c.press(t);
}
assert_eq!(c.per_second(0.95), 4);
// 1.0 s after the first press it has left the window.
assert_eq!(c.per_second(1.0), 3);
assert_eq!(c.per_second(1.6), 1);
assert_eq!(c.per_second(5.0), 0);
// The ring never keeps more than 64 presses.
for i in 0..200 {
c.press(10.0 + f64::from(i) * 0.001);
}
assert_eq!(c.per_second(10.2), 64);
}
#[test]
fn speed_is_horizontal_blocks_per_second_between_samples() {
let mut s = Speed::default();
assert_eq!(s.sample(0.0, 0.0, 0.0), 0);
// Sprinting: 5.612 blocks per second along x, with a jump (y is ignored).
assert_eq!(s.sample(0.5, 0.0, 0.1), 0, "too soon for a new sample");
assert_eq!(s.sample(1.403, 0.0, 0.25), 56);
// 3 east and 4 south in a second: 5 blocks per second.
assert_eq!(s.sample(1.403 + 3.0, 4.0, 1.25), 50);
// A teleport reads as standing still.
assert_eq!(s.sample(1000.0, 4.0, 1.5), 0);
assert_eq!(tenths(56), "5.6");
}
#[test]
fn reach_shows_the_last_hit_for_three_seconds() {
let mut r = Reach::default();
assert_eq!(r.hundredths(0.0), None);
r.hit(2.954, 1.0);
assert_eq!(r.hundredths(1.5), Some(295));
assert_eq!(hundredths(295), "2.95");
assert_eq!(hundredths(300), "3.00");
assert_eq!(r.hundredths(4.1), None);
}
#[test]
fn the_clock_reads_hours_and_minutes() {
assert_eq!(clock(14, 5), "14:05");
assert_eq!(clock(0, 0), "00:00");
}
#[test]
fn keystrokes_keys_tile_their_box_without_overlap() {
let (w, h) = keys_size();
assert_eq!((w, h), (70.0, 3.0 * 24.0 + 12.0));
for (i, a) in Key::ALL.iter().enumerate() {
let (x, y, kw, kh) = key_rect(*a);
assert!(
x >= 0.0 && y >= 0.0 && x + kw <= w && y + kh <= h,
"{a:?} inside"
);
for b in &Key::ALL[i + 1..] {
let (bx, by, bw, bh) = key_rect(*b);
let apart = x + kw <= bx || bx + bw <= x || y + kh <= by || by + bh <= y;
assert!(apart, "{a:?} and {b:?} overlap");
}
}
}
#[test]
fn places_round_trip_and_only_moved_widgets_are_written() {
let mut l = Layout::default();
let mut text = String::new();
l.serialize(&mut text);
assert_eq!(text, "", "a vanilla layout writes nothing");
*l.get_mut(WidgetId::Keys) = Place {
at: Some((0.25, 1.0)),
scale: 150,
};
l.get_mut(WidgetId::Fps).scale = 75;
l.serialize(&mut text);
assert_eq!(
text,
"hudPlace:fps,corner,,75\nhudPlace:keys,0.2500,1.0000,150\n"
);
let mut back = Layout::default();
for line in text.lines() {
back.parse(line.split_once(':').unwrap().1);
}
assert_eq!(back, l);
// Out of range values are clamped, unknown widgets and bad numbers ignored.
back.parse("speed,-3,7,250");
assert_eq!(back.get(WidgetId::Speed).at, Some((0.0, 1.0)));
assert_eq!(back.get(WidgetId::Speed).scale, 200);
back.parse("radar,0.5,0.5,100");
back.parse("clock,NaN,0.5,100");
assert_eq!(back.get(WidgetId::Clock).at, None);
}
#[test]
fn fractions_keep_a_box_on_screen_at_any_size() {
let screen = (480.0, 270.0);
let at = to_fractions((100.0, 50.0), (80.0, 20.0), screen);
assert_eq!(from_fractions(at, (80.0, 20.0), screen), (100.0, 50.0));
// A box at the right edge stays at the right edge on a wider screen.
let right = to_fractions((400.0, 0.0), (80.0, 20.0), screen);
assert_eq!(right, (1.0, 0.0));
assert_eq!(
from_fractions(right, (80.0, 20.0), (960.0, 540.0)),
(880.0, 0.0)
);
// Dragged past the edge: kept inside.
assert_eq!(
to_fractions((-30.0, 900.0), (80.0, 20.0), screen),
(0.0, 1.0)
);
}
#[test]
fn boxes_snap_to_screen_edges_middle_and_each_other() {
// Near the left margin.
assert_eq!(snap(4.5, 50.0, 480.0, &[]), (2.0, Some(0.0)));
// Centred: the middle of 480 for a 50-wide box starts at 215.
assert_eq!(snap(213.0, 50.0, 480.0, &[]), (215.0, Some(240.0)));
// Beside another box (100..160): its start goes to 160.
assert_eq!(
snap(163.0, 50.0, 480.0, &[(100.0, 60.0)]),
(160.0, Some(160.0))
);
// Lined up with its left edge.
assert_eq!(
snap(98.0, 50.0, 480.0, &[(100.0, 60.0)]),
(100.0, Some(100.0))
);
// Too far from anything: stays, but never off screen.
assert_eq!(snap(300.0, 50.0, 480.0, &[(100.0, 60.0)]), (300.0, None));
assert_eq!(snap(470.0, 50.0, 480.0, &[]), (430.0, None));
}
}
+15 -3
View File
@@ -836,7 +836,14 @@ impl<G: ChunkGenerator> Source for Jobs<G> {
Job::Mesh(..) => 5,
_ => 6,
};
(kind, crate::spans::thread_cpu().unwrap_or_default())
// The other jobs (saves, light views, freed meshes) are many and short: counted, not
// timed, so the clock reads don't cost more than they do.
let cpu = if kind == 6 {
std::time::Duration::ZERO
} else {
crate::spans::thread_cpu().unwrap_or_default()
};
(kind, cpu)
});
let _tag = horizon_threads::heap_tag(match &job.job {
Job::Generate(..) => "stream.generate",
@@ -865,8 +872,13 @@ impl<G: ChunkGenerator> Source for Jobs<G> {
} else {
kind
};
let cpu = crate::spans::thread_cpu().unwrap_or_default();
job_stats::add(kind, cpu.saturating_sub(started).as_nanos() as u64);
let nanos = if kind == 6 {
0
} else {
let cpu = crate::spans::thread_cpu().unwrap_or_default();
cpu.saturating_sub(started).as_nanos() as u64
};
job_stats::add(kind, nanos);
}
if let Some(done) = done {
self.shared.done.send(done);
+43 -1
View File
@@ -614,7 +614,12 @@ fn button_with_room(
room: f32,
narration: impl FnOnce([f32; 4]) -> crate::widgets::Narratable,
) {
crate::widgets::record(&label.plain(), [x, y, w, h], active);
let plain = label.plain();
crate::widgets::record(&plain, [x, y, w, h], active);
// An icon button has no label to record, and A presses it all the same.
if active && plain.trim().is_empty() {
crate::widgets::target([x, y, w, h]);
}
crate::widgets::narratable(|| narration([x, y, w, h]).hovered(hover));
crate::widgets::widget_cursor(hover, active);
let sprite = if !active {
@@ -1846,6 +1851,43 @@ mod tests {
assert_eq!(scrolled_left(10.0, 40.0, 1_000), 10.0 - offset);
}
/// A controller reaches an icon button only through its target, and can't press a disabled one.
#[test]
fn an_active_icon_button_is_a_focus_target_and_a_disabled_one_is_not() {
let atlas = atlas();
let mut batch = HudBatch::new([640, 480]);
// Whatever this thread drew before is the last frame's, then gone.
crate::widgets::end_frame(u64::MAX - 1);
button(
&mut batch,
&atlas,
10.0,
20.0,
20.0,
20.0,
&Text::empty(),
true,
false,
);
button(
&mut batch,
&atlas,
40.0,
20.0,
20.0,
20.0,
&Text::empty(),
false,
false,
);
crate::widgets::end_frame(u64::MAX);
let targets: Vec<[f32; 4]> = crate::widgets::last_targets()
.iter()
.map(|t| t.rect)
.collect();
assert_eq!(targets, [[10.0, 20.0, 20.0, 20.0]]);
}
#[test]
fn a_glyph_leaves_a_label_that_fits_centred() {
let atlas = atlas();
@@ -65,7 +65,11 @@ struct Taa {
jitter: vec4<f32>,
};
@group(0) @binding(2) var history: texture_2d<f32>;
@group(0) @binding(3) var depth: texture_depth_2d;
// The world's depth as an unfilterable float texture: naga's GLSL backend
// cannot emit `textureLoad` from a depth texture, and a depth view bound as
// `TextureSampleType::Float { filterable: false }` gives the same texel on
// every backend.
@group(0) @binding(3) var depth: texture_2d<f32>;
@group(0) @binding(4) var<uniform> taa: Taa;
// Catmull-Rom over the history in 5 bilinear taps: sharper than one under motion.
@@ -113,7 +117,7 @@ fn sample_history(uv: vec2<f32>) -> vec3<f32> {
let c = textureLoad(world, q, 0).rgb;
lo = min(lo, c);
hi = max(hi, c);
near = max(near, textureLoad(depth, q, 0));
near = max(near, textureLoad(depth, q, 0).r);
}
}
let ndc = vec2(in.uv.x * 2.0 - 1.0, 1.0 - in.uv.y * 2.0);
@@ -472,8 +472,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Versteek: elke Horizon-speler sien jou sonder jou skoonheidsmiddels, jy ingesluit. Dieselfde skakelaar as die lanseerder se klerekas.",
"horizon.extras.cosmetics_others": "Ander spelers se skoonheidsmiddels",
"horizon.extras.cosmetics_others.tooltip": "Wat ander Horizon-spelers dra: alles, net hul naamplaatjiestyle, of niks. Versteek, die speletjie vra nooit wat hulle dra nie.",
"horizon.extras.cosmetics_auras": "Ander se aura's en roetes",
"horizon.extras.cosmetics_auras.tooltip": "Auras en roetes wat ander spelers dra. Af by verstek.",
"horizon.extras.cosmetics_hide_fx": "Versteek ander spelers se spore en auras",
"horizon.extras.cosmetics_hide_fx.tooltip": "Ander spelers se spore en auras bly versteek; hul ander kosmetiese items wys steeds. By verstek af.",
"horizon.extras.cosmetics.shown": "Getoon",
"horizon.extras.cosmetics.hidden": "Versteek",
"horizon.extras.cosmetics.name_tags": "Slegs naamplaatjies"
@@ -491,8 +491,8 @@
"horizon.extras.cosmetics_mine.tooltip": "مخفي: يراك كل لاعب في Horizon بدون مستحضرات التجميل الخاصة بك، بما في ذلك أنت. نفس مفتاح خزانة المشغل.",
"horizon.extras.cosmetics_others": "مستحضرات التجميل للاعبين الآخرين",
"horizon.extras.cosmetics_others.tooltip": "ما يرتديه لاعبو Horizon الآخرون: كل شيء، فقط أنماط بطاقة الاسم الخاصة بهم، أو لا شيء. مخفيًا، اللعبة لا تسأل أبدًا عما يرتدونه.",
"horizon.extras.cosmetics_auras": "هالات ومسارات الآخرين",
"horizon.extras.cosmetics_auras.tooltip": "الهالات والمسارات التي يرتديها اللاعبون الآخرون. إيقاف بشكل افتراضي.",
"horizon.extras.cosmetics_hide_fx": "إخفاء آثار وهالات اللاعبين الآخرين",
"horizon.extras.cosmetics_hide_fx.tooltip": "تبقى آثار وهالات اللاعبين الآخرين مخفية؛ وتظل مستحضراتهم الأخرى ظاهرة. معطّل افتراضيًا.",
"horizon.extras.cosmetics.shown": "معروض",
"horizon.extras.cosmetics.hidden": "مخفي",
"horizon.extras.cosmetics.name_tags": "علامات الاسم فقط"
@@ -463,8 +463,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Gizli: hər Horizon oyunçu sizi kosmetikanız olmadan görür. Başlatma şkafı ilə eyni açar.",
"horizon.extras.cosmetics_others": "Digər oyunçuların kosmetikası",
"horizon.extras.cosmetics_others.tooltip": "Digər Horizon oyunçular nə geyinirlər: hər şey, yalnız ad etiketi üslubları və ya heç nə. Gizli, oyun heç vaxt nə geyindiklərini soruşmur.",
"horizon.extras.cosmetics_auras": "Başqalarının auraları və izləri",
"horizon.extras.cosmetics_auras.tooltip": "Digər oyunçuların geydiyi auralar və izlər. Defolt olaraq söndürülür.",
"horizon.extras.cosmetics_hide_fx": "Digər oyunçuların izlərini və auralarını gizlət",
"horizon.extras.cosmetics_hide_fx.tooltip": "Digər oyunçuların izləri və auraları gizli qalır; digər kosmetikaları görünməyə davam edir. Defolt olaraq söndürülüb.",
"horizon.extras.cosmetics.shown": "Göstərildi",
"horizon.extras.cosmetics.hidden": "Gizli",
"horizon.extras.cosmetics.name_tags": "Yalnız ad etiketləri"
@@ -489,8 +489,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Йәшерен: һәр Horizon уйынсы һеҙҙең косметикаһыҙ күрә, һеҙ ҙә индерелгән. Шул уҡ переключатель стартер&#8217;s Гардероб.",
"horizon.extras.cosmetics_others": "Башҡа уйынсыларҙың косметикаһы",
"horizon.extras.cosmetics_others.tooltip": "Башҡа ниндәй Horizon уйынсылар кейә: барыһы ла, тик уларҙы исем биркаһы стилдәре, йәки бер нәмә лә. Йәшерен, уйын бер ҡасан да һорамай, улар нимә кейә.",
"horizon.extras.cosmetics_auras": "Башҡаларҙың ауралары һәм эҙҙәре",
"horizon.extras.cosmetics_auras.tooltip": "Аура һәм эҙҙәр башҡа уйынсылар кейә. Һүндерелгән по умолчанию.",
"horizon.extras.cosmetics_hide_fx": "Башҡа уйынсыларҙың эҙҙәрен һәм ауралары йәшереү",
"horizon.extras.cosmetics_hide_fx.tooltip": "Башҡа уйынсыларҙың эҙҙәре һәм ауралары йәшерен ҡала; уларҙың башҡа косметикаһы күренә. Ғәҙәттә һүндерелгән.",
"horizon.extras.cosmetics.shown": "Күрһәтелгән",
"horizon.extras.cosmetics.hidden": "Йәшерен",
"horizon.extras.cosmetics.name_tags": "Исем билдәләре генә"
@@ -475,8 +475,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Схаваны: кожны гулец Horizon бачыць вас без вашай касметыкі, у тым ліку і вас. The same switch as the launcher's Wardrobe.",
"horizon.extras.cosmetics_others": "Касметыка іншых гульцоў",
"horizon.extras.cosmetics_others.tooltip": "Што носяць іншыя гульцы Horizon: усё, толькі стылі тэгаў з імёнамі або нічога. Hidden, the game never asks what they wear.",
"horizon.extras.cosmetics_auras": "Чужыя аўры і шлейфы",
"horizon.extras.cosmetics_auras.tooltip": "Auras and trails other players wear. Выключана па змаўчанні.",
"horizon.extras.cosmetics_hide_fx": "Схаваць сляды і аўры іншых гульцоў",
"horizon.extras.cosmetics_hide_fx.tooltip": "Сляды і аўры іншых гульцоў схаваныя; іх астатняя касметыка бачная. Па змаўчанні выкл.",
"horizon.extras.cosmetics.shown": "Паказана",
"horizon.extras.cosmetics.hidden": "Схаваны",
"horizon.extras.cosmetics.name_tags": "Толькі біркі з імёнамі"
@@ -470,8 +470,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Скрит: всеки играч на Horizon ви вижда без вашата козметика, включително и вие. Същият превключвател като гардероба на стартера.",
"horizon.extras.cosmetics_others": "Козметика за други играчи",
"horizon.extras.cosmetics_others.tooltip": "Какво носят другите играчи на Horizon: всичко, само техните стилове на имената или нищо. Скрито, играта никога не пита какво носят.",
"horizon.extras.cosmetics_auras": "Аури и следи на други",
"horizon.extras.cosmetics_auras.tooltip": "Аури и пътеки, които другите играчи носят. Изключено по подразбиране.",
"horizon.extras.cosmetics_hide_fx": "Скриване на следите и аурите на другите играчи",
"horizon.extras.cosmetics_hide_fx.tooltip": "Следите и аурите на другите играчи остават скрити; другите им козметики се виждат. Изключено по подразбиране.",
"horizon.extras.cosmetics.shown": "Показано",
"horizon.extras.cosmetics.hidden": "Скрити",
"horizon.extras.cosmetics.name_tags": "Само етикети с имена",
@@ -474,8 +474,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Kuzhet : pep c'hoarier Horizon a wel ac'hanoc'h hep ho kosmetikoù, c'hwi en o zouez. Ar memes treuzfurmadur hag armel al lañser.",
"horizon.extras.cosmetics_others": "Kosmetikoù ar c'hoarierien all",
"horizon.extras.cosmetics_others.tooltip": "Ar pezh a vez gwisket gant ar c'hoarierien Horizon all : pep tra, o doareoù tikedenn anv hepken, pe netra. Kuzhet, ar c'hoari ne c'houlenn ket biskoazh petra a wiskont.",
"horizon.extras.cosmetics_auras": "Auraoù ha roudoù tud all",
"horizon.extras.cosmetics_auras.tooltip": "Auraoù ha roudoù a vez gwisket gant c'hoarierien all. Diweredekaet dre ziouer.",
"horizon.extras.cosmetics_hide_fx": "Kuzhat roudoù hag aouraoù ar c'hoarierien all",
"horizon.extras.cosmetics_hide_fx.tooltip": "Kuzhet e chom roudoù hag aouraoù ar c'hoarierien all; diskouezet e vez o c'hinkladurioù all. Diweredekaet dre ziouer.",
"horizon.extras.cosmetics.shown": "Diskouezet",
"horizon.extras.cosmetics.hidden": "Kuzhet",
"horizon.extras.cosmetics.name_tags": "Tikedennoù anvioù hepken"
@@ -415,8 +415,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skriveno: svaki Horizon igrač vas vidi bez vaše kozmetike, uključujući i vas. Isti prekidač kao Ormar lansera.",
"horizon.extras.cosmetics_others": "Kozmetika drugih igrača",
"horizon.extras.cosmetics_others.tooltip": "Šta drugi Horizon igrači nose: sve, samo stilove oznaka sa imenom ili ništa. Skriveno, igra nikad ne pita šta nose.",
"horizon.extras.cosmetics_auras": "Aure i tragovi drugih",
"horizon.extras.cosmetics_auras.tooltip": "Aure i staze koje drugi igrači nose. Podrazumevano isključeno.",
"horizon.extras.cosmetics_hide_fx": "Sakrij tragove i aure drugih igrača",
"horizon.extras.cosmetics_hide_fx.tooltip": "Tragovi i aure drugih igrača ostaju skriveni; njihova ostala kozmetika se i dalje vidi. Isključeno po zadanom.",
"horizon.extras.cosmetics.shown": "Prikazano",
"horizon.extras.cosmetics.hidden": "Skriveno",
"horizon.extras.cosmetics.name_tags": "Samo oznake sa imenom",
@@ -463,8 +463,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Ocult: tots els jugadors d'Horizon et veuen sense els teus cosmètics, tu inclòs. El mateix interruptor que l'armari del llançador.",
"horizon.extras.cosmetics_others": "Cosmètica d'altres jugadors",
"horizon.extras.cosmetics_others.tooltip": "Què porten altres jugadors d'Horizon: tot, només els seus estils d'etiquetes de nom o res. Amagat, el joc mai pregunta què porten.",
"horizon.extras.cosmetics_auras": "Les aures i els camins dels altres",
"horizon.extras.cosmetics_auras.tooltip": "Aures i rastres que porten altres jugadors. Desactivat per defecte.",
"horizon.extras.cosmetics_hide_fx": "Amaga les esteles i les aures dels altres jugadors",
"horizon.extras.cosmetics_hide_fx.tooltip": "Les esteles i les aures dels altres jugadors queden amagades; els seus altres cosmètics es continuen veient. Desactivat per defecte.",
"horizon.extras.cosmetics.shown": "Es mostra",
"horizon.extras.cosmetics.hidden": "Ocult",
"horizon.extras.cosmetics.name_tags": "Només etiquetes de nom",
@@ -453,8 +453,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skryté: každý hráč Horizon vás vidí bez vaší kosmetiky, včetně vás. Stejný vypínač jako skříň odpalovacího zařízení.",
"horizon.extras.cosmetics_others": "Kosmetika ostatních hráčů",
"horizon.extras.cosmetics_others.tooltip": "Co nosí ostatní hráči Horizon: všechno, jen styly jmenovek nebo nic. Skryto, hra se nikdy neptá, co nosí.",
"horizon.extras.cosmetics_auras": "Aury a stezky ostatních",
"horizon.extras.cosmetics_auras.tooltip": "Aury a stezky, které nosí ostatní hráči. Ve výchozím nastavení vypnuto.",
"horizon.extras.cosmetics_hide_fx": "Skrýt stopy a aury ostatních hráčů",
"horizon.extras.cosmetics_hide_fx.tooltip": "Stopy a aury ostatních hráčů zůstanou skryté; jejich ostatní kosmetika je dál vidět. Ve výchozím stavu vypnuto.",
"horizon.extras.cosmetics.shown": "Zobrazeno",
"horizon.extras.cosmetics.hidden": "Skrytá",
"horizon.extras.cosmetics.name_tags": "Pouze jmenovky"
@@ -485,8 +485,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Пытарнӑ: кашни Horizon вылякан сире косметикӑсӑр курать, эсир те ҫав шутра. Пуҫкаҫӑн гардеробӗнчи пекех переключатель.",
"horizon.extras.cosmetics_others": "Ытти вылякансен косметики",
"horizon.extras.cosmetics_others.tooltip": "Ытти Horizon вылякансем мӗн тӑхӑнаҫҫӗ: пурте, вӗсен ячӗсен стилӗсем ҫеҫ, е нимӗн те мар. Вӑрттӑн, вӑйӑ нихҫан та вӗсем мӗн тӑхӑннине ыйтмасть.",
"horizon.extras.cosmetics_auras": "Ыттисен аурисем тата йӗрӗсем",
"horizon.extras.cosmetics_auras.tooltip": "Ытти вылякансем тӑхӑнакан аурӑсемпе йӗрсем. Выключен по умолчанию.",
"horizon.extras.cosmetics_hide_fx": "Ытти вӑййисен йӗрӗсене тата аурисене пытар",
"horizon.extras.cosmetics_hide_fx.tooltip": "Ытти вӑййисен йӗрӗсем тата аурисем пытарӑнса юлаҫҫӗ; вӗсен ытти косметики курӑнать. Йӑлана кура сӳнтернӗ.",
"horizon.extras.cosmetics.shown": "Кӑтартнӑ",
"horizon.extras.cosmetics.hidden": "Пытарнӑ",
"horizon.extras.cosmetics.name_tags": "Ят паллисем кӑна"
@@ -460,8 +460,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Cudd: mae pob chwaraewr Horizon yn eich gweld heb eich colur, fe wnaethoch chi gynnwys. Yr un switsh â Wardrob y lansiwr.",
"horizon.extras.cosmetics_others": "Colur chwaraewyr eraill",
"horizon.extras.cosmetics_others.tooltip": "Beth mae chwaraewyr Horizon eraill yn ei wisgo: popeth, dim ond eu steil tag enw, neu ddim byd. Yn gudd, nid yw'r gêm byth yn gofyn beth maen nhw'n ei wisgo.",
"horizon.extras.cosmetics_auras": "Auras a llwybrau eraill",
"horizon.extras.cosmetics_auras.tooltip": "Auras a llwybrau mae chwaraewyr eraill yn eu gwisgo. Wedi'i ddiffodd yn ddiofyn.",
"horizon.extras.cosmetics_hide_fx": "Cuddio llwybrau ac awrâu chwaraewyr eraill",
"horizon.extras.cosmetics_hide_fx.tooltip": "Mae llwybrau ac awrâu chwaraewyr eraill yn aros yn gudd; mae eu colur arall yn dal i ddangos. I ffwrdd yn ddiofyn.",
"horizon.extras.cosmetics.shown": "Dangosir",
"horizon.extras.cosmetics.hidden": "Cudd",
"horizon.extras.cosmetics.name_tags": "Tagiau enw yn unig"
@@ -440,8 +440,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skjult: alle Horizon-spillere ser dig uden din kosmetik, inklusive dig. Den samme kontakt som løfterakettens garderobe.",
"horizon.extras.cosmetics_others": "Andre spilleres kosmetik",
"horizon.extras.cosmetics_others.tooltip": "Hvad andre Horizon-spillere bærer: alt, kun deres navnemærke eller intet. Skjult spørger spillet aldrig, hvad de har på.",
"horizon.extras.cosmetics_auras": "Andres auraer og spor",
"horizon.extras.cosmetics_auras.tooltip": "Auraer og spor, som andre spillere bærer. Fra som standard.",
"horizon.extras.cosmetics_hide_fx": "Skjul andre spilleres spor og auraer",
"horizon.extras.cosmetics_hide_fx.tooltip": "Andre spilleres spor og auraer forbliver skjulte; deres andre kosmetikker vises stadig. Slået fra som standard.",
"horizon.extras.cosmetics.shown": "Vist",
"horizon.extras.cosmetics.hidden": "Skjult",
"horizon.extras.cosmetics.name_tags": "Kun navneskilte",
@@ -357,10 +357,14 @@
"horizon.extras.header.cosmetics": "Kosmetik",
"horizon.extras.cosmetics_mine": "Meine Kosmetik",
"horizon.extras.cosmetics_mine.tooltip": "Ausgeblendet: Alle Horizon-Spieler sehen dich ohne deine Kosmetik, du selbst auch. Derselbe Schalter wie in der Garderobe des Launchers.",
"key.emote": "Emote-Rad",
"horizon.emote_wheel.title": "Emotes",
"horizon.emote_wheel.empty": "Noch keine Emotes",
"horizon.emote_wheel.help": "Loslassen oder klicken zum Abspielen · 1–8 · Esc schließt",
"horizon.extras.cosmetics_others": "Kosmetik anderer Spieler",
"horizon.extras.cosmetics_others.tooltip": "Was andere Horizon-Spieler tragen: alles, nur ihre Namensschild-Stile oder nichts. Ausgeblendet fragt das Spiel nie, was sie tragen.",
"horizon.extras.cosmetics_auras": "Auren und Spuren anderer",
"horizon.extras.cosmetics_auras.tooltip": "Auren und Spuren, die andere Spieler tragen. Standardmäßig aus.",
"horizon.extras.cosmetics_hide_fx": "Spuren und Auren anderer Spieler ausblenden",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spuren und Auren anderer Spieler bleiben ausgeblendet; ihre anderen Kosmetika sind weiter sichtbar. Standardmäßig aus.",
"horizon.extras.cosmetics.shown": "Angezeigt",
"horizon.extras.cosmetics.hidden": "Ausgeblendet",
"horizon.extras.cosmetics.name_tags": "Nur Namensschilder",
@@ -462,8 +462,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Κρυφό: κάθε παίκτης του Horizon σας βλέπει χωρίς τα καλλυντικά σας, συμπεριλαμβανομένων εσείς. Ο ίδιος διακόπτης με την ντουλάπα του εκτοξευτή.",
"horizon.extras.cosmetics_others": "Καλλυντικά άλλων παικτών",
"horizon.extras.cosmetics_others.tooltip": "Τι φοράνε οι άλλοι παίκτες του Horizon: τα πάντα, μόνο τα στυλ των ετικετών τους ή τίποτα. Κρυφά, το παιχνίδι δεν ρωτά ποτέ τι φοράνε.",
"horizon.extras.cosmetics_auras": "Οι αύρες και τα μονοπάτια των άλλων",
"horizon.extras.cosmetics_auras.tooltip": "Αύρες και μονοπάτια φορούν άλλοι παίκτες. Απενεργοποίηση από προεπιλογή.",
"horizon.extras.cosmetics_hide_fx": "Απόκρυψη ιχνών και αυρών άλλων παικτών",
"horizon.extras.cosmetics_hide_fx.tooltip": "Τα ίχνη και οι αύρες των άλλων παικτών μένουν κρυφά· τα άλλα διακοσμητικά τους εξακολουθούν να φαίνονται. Ανενεργό από προεπιλογή.",
"horizon.extras.cosmetics.shown": "Εμφανίζεται",
"horizon.extras.cosmetics.hidden": "Κρυφό",
"horizon.extras.cosmetics.name_tags": "Μόνο ετικέτες ονομάτων",
@@ -97,6 +97,25 @@
"horizon.mods.settings": "Settings",
"horizon.mods.in_world": " (leave the world to change)",
"horizon.mods.open_folder": "Open Mod Folder",
"horizon.mods.browse": "Browse Mods...",
"horizon.mods.browse.title": "Browse Mods",
"horizon.mods.browse.search": "Search mods...",
"horizon.mods.browse.project": "Mod",
"horizon.mods.browse.loading": "Reading Horizon's mod registry...",
"horizon.mods.browse.failed": "Couldn't read the mod registry: %s",
"horizon.mods.browse.none": "No mod found",
"horizon.mods.browse.has_update": " (update)",
"horizon.mods.browse.is_installed": " (installed)",
"horizon.mods.browse.by": "by %s",
"horizon.mods.browse.installing": "Installing...",
"horizon.mods.browse.install": "Install",
"horizon.mods.browse.update": "Update",
"horizon.mods.browse.installed": "Installed",
"horizon.mods.browse.open_page": "Open Page",
"horizon.mods.browse.enabled": "Mod",
"horizon.mods.browse.changelog": "Changelog",
"horizon.mods.browse.done": "%s %s is installed and on. Its content loads when the game starts again.",
"horizon.mods.browse.install_failed": "Couldn't install it: %s",
"horizon.shader_packs.empty": "No shader packs: put them in the shaderpacks folder",
"horizon.shader_packs.kind_horizon": " (Horizon)",
"horizon.shader_options.open": "Shader Options...",
@@ -557,10 +576,14 @@
"horizon.extras.header.cosmetics": "Cosmetics",
"horizon.extras.cosmetics_mine": "My cosmetics",
"horizon.extras.cosmetics_mine.tooltip": "Hidden: every Horizon player sees you without your cosmetics, you included. The same switch as the launcher's Wardrobe.",
"key.emote": "Emote Wheel",
"horizon.emote_wheel.title": "Emotes",
"horizon.emote_wheel.empty": "No emotes yet",
"horizon.emote_wheel.help": "Release or click to play · 1–8 · Esc closes",
"horizon.extras.cosmetics_others": "Other players' cosmetics",
"horizon.extras.cosmetics_others.tooltip": "What other Horizon players wear: everything, only their name tag styles, or nothing. Hidden unless you own cosmetics, until you choose. Hidden, the game never asks what they wear.",
"horizon.extras.cosmetics_auras": "Others' auras and trails",
"horizon.extras.cosmetics_auras.tooltip": "Auras and trails other players wear. Off by default.",
"horizon.extras.cosmetics_hide_fx": "Hide other players' trails and auras",
"horizon.extras.cosmetics_hide_fx.tooltip": "Other players' trails and auras stay hidden; their other cosmetics still show. Off by default.",
"horizon.extras.cosmetics.shown": "Shown",
"horizon.extras.cosmetics.hidden": "Hidden",
"horizon.extras.cosmetics.name_tags": "Name tags only",
@@ -676,6 +699,12 @@
"horizon.pvp.hud_held_corner.tooltip": "Where the count shows.",
"horizon.pvp.hud_background": "Widget backgrounds",
"horizon.pvp.hud_background.tooltip": "A dark box behind each widget.",
"horizon.pvp.hud_opacity": "Background opacity",
"horizon.pvp.hud_opacity.tooltip": "How dark the boxes behind the widgets are.",
"horizon.pvp.hud_text_colour": "Text colour",
"horizon.pvp.hud_text_colour.tooltip": "The widgets' text colour. Durability keeps its green to red.",
"horizon.pvp.hud_shadow": "Text shadow",
"horizon.pvp.hud_shadow.tooltip": "A shadow under the widgets' text, as vanilla's HUD text has.",
"horizon.pvp.header.hud": "HUD widgets",
"horizon.pvp.corner.top_left": "Top left",
"horizon.pvp.corner.top_right": "Top right",
@@ -705,6 +734,37 @@
"horizon.pvp.hud.direction.south": "South",
"horizon.pvp.hud.direction.east": "East",
"horizon.pvp.hud.direction.west": "West",
"horizon.pvp.hud_fps": "FPS",
"horizon.pvp.hud_fps.tooltip": "Frames drawn in the last second.",
"horizon.pvp.hud_fps_corner": "FPS corner",
"horizon.pvp.hud_fps_corner.tooltip": "Where the FPS shows.",
"horizon.pvp.hud_cps": "Clicks per second",
"horizon.pvp.hud_cps.tooltip": "Your left and right clicks in the last second.",
"horizon.pvp.hud_cps_corner": "CPS corner",
"horizon.pvp.hud_cps_corner.tooltip": "Where the clicks per second show.",
"horizon.pvp.hud_keys": "Keystrokes",
"horizon.pvp.hud_keys.tooltip": "Your movement keys, mouse buttons and jump, lit while you hold them, with clicks per second.",
"horizon.pvp.hud_keys_corner": "Keystrokes corner",
"horizon.pvp.hud_keys_corner.tooltip": "Where the keystrokes show.",
"horizon.pvp.hud_clock": "Clock",
"horizon.pvp.hud_clock.tooltip": "Your computer's time.",
"horizon.pvp.hud_clock_corner": "Clock corner",
"horizon.pvp.hud_clock_corner.tooltip": "Where the clock shows.",
"horizon.pvp.hud_reach": "Reach",
"horizon.pvp.hud_reach.tooltip": "How far from your eyes your last hit landed, for 3 seconds. It only measures: your reach stays vanilla's.",
"horizon.pvp.hud_reach_corner": "Reach corner",
"horizon.pvp.hud_reach_corner.tooltip": "Where the reach shows.",
"horizon.pvp.hud_speed": "Speed",
"horizon.pvp.hud_speed.tooltip": "How fast you move across the ground, in blocks per second.",
"horizon.pvp.hud_speed_corner": "Speed corner",
"horizon.pvp.hud_speed_corner.tooltip": "Where the speed shows.",
"horizon.pvp.hud.fps": "%s FPS",
"horizon.pvp.hud.cps": "CPS: %s | %s",
"horizon.pvp.hud.reach": "Reach: %s",
"horizon.pvp.hud.speed": "Speed: %s b/s",
"horizon.pvp.hud.keys.attack": "LMB",
"horizon.pvp.hud.keys.use": "RMB",
"horizon.pvp.hud.keys.cps": "%s CPS",
"horizon.pvp.numeric_enchants": "Enchantment levels as numbers",
"horizon.pvp.numeric_enchants.tooltip": "Tooltips and the enchanting table show Sharpness 5 instead of Sharpness V.",
"horizon.pvp.header.items": "Items",
@@ -468,8 +468,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Kaŝita: ĉiu Horizon-ludanto vidas vin sen viaj kosmetikaĵoj, vi inkluzivis. La sama ŝaltilo kiel la Vestoŝranko de la lanĉilo.",
"horizon.extras.cosmetics_others": "Kosmetikaĵoj de aliaj ludantoj",
"horizon.extras.cosmetics_others.tooltip": "Kion aliaj Horizon ludantoj portas: ĉion, nur siajn nometikedstilojn, aŭ nenion. Kaŝita, la ludo neniam demandas kion ili portas.",
"horizon.extras.cosmetics_auras": "Aŭroj kaj spuroj de aliaj",
"horizon.extras.cosmetics_auras.tooltip": "Aŭroj kaj spuroj kiujn aliaj ludantoj portas. Malŝaltita defaŭlte.",
"horizon.extras.cosmetics_hide_fx": "Kaŝi spurojn kaj aŭrojn de aliaj ludantoj",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spuroj kaj aŭroj de aliaj ludantoj restas kaŝitaj; iliaj aliaj kosmetikaĵoj ankoraŭ montriĝas. Defaŭlte malŝaltita.",
"horizon.extras.cosmetics.shown": "Montrita",
"horizon.extras.cosmetics.hidden": "Kaŝita",
"horizon.extras.cosmetics.name_tags": "Nomaj etikedoj nur"
@@ -464,8 +464,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Varjatud: iga Horizoni mängija näeb teid ilma teie kosmeetikata, kaasa arvatud. Sama lüliti, mis käivitaja riidekapil.",
"horizon.extras.cosmetics_others": "Teiste mängijate kosmeetika",
"horizon.extras.cosmetics_others.tooltip": "Mida teised Horizoni mängijad kannavad: kõike, ainult nende nimesiltide stiile või mitte midagi. Varjatud, mäng ei küsi kunagi, mida nad kannavad.",
"horizon.extras.cosmetics_auras": "Teiste aurad ja jäljed",
"horizon.extras.cosmetics_auras.tooltip": "Aurad ja jäljed, mida teised mängijad kannavad. Vaikimisi väljas.",
"horizon.extras.cosmetics_hide_fx": "Peida teiste mängijate jäljed ja aurad",
"horizon.extras.cosmetics_hide_fx.tooltip": "Teiste mängijate jäljed ja aurad jäävad peidetuks; nende muu kosmeetika on endiselt näha. Vaikimisi väljas.",
"horizon.extras.cosmetics.shown": "Näidatud",
"horizon.extras.cosmetics.hidden": "Peidetud",
"horizon.extras.cosmetics.name_tags": "Ainult nimesildid"
@@ -469,8 +469,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Ezkutuan: Horizon jokalari bakoitzak zure kosmetikarik gabe ikusten zaitu, zuk barne. Abiarazlearen armairuaren etengailu bera.",
"horizon.extras.cosmetics_others": "Beste jokalarien kosmetika",
"horizon.extras.cosmetics_others.tooltip": "Beste Horizon jokalariek zer janzten duten: denetarik, izenaren etiketa estiloak bakarrik, edo ezer ez. Ezkutuan, jokoak ez du inoiz galdetzen zer janzten duten.",
"horizon.extras.cosmetics_auras": "Besteen aura eta ibilbideak",
"horizon.extras.cosmetics_auras.tooltip": "Beste jokalariek janzten dituzten aura eta arrastoak. Desaktibatuta lehenespenez.",
"horizon.extras.cosmetics_hide_fx": "Ezkutatu beste jokalarien arrastoak eta aurak",
"horizon.extras.cosmetics_hide_fx.tooltip": "Beste jokalarien arrastoak eta aurak ezkutuan geratzen dira; haien beste kosmetikoak ikusten jarraitzen dute. Desaktibatuta lehenespenez.",
"horizon.extras.cosmetics.shown": "Erakutsita",
"horizon.extras.cosmetics.hidden": "Ezkutuan",
"horizon.extras.cosmetics.name_tags": "Izena etiketak soilik"
@@ -474,8 +474,8 @@
"horizon.extras.cosmetics_mine.tooltip": "پنهان: هر بازیکن Horizon شما را بدون لوازم آرایشی شما، از جمله شما، می بیند. همان سوئیچ کمد لانچر.",
"horizon.extras.cosmetics_others": "لوازم آرایشی دیگر بازیکنان",
"horizon.extras.cosmetics_others.tooltip": "سایر بازیکنان Horizon چه می پوشند: همه چیز، فقط سبک برچسب نام آنها یا هیچ چیز. پنهان، بازی هرگز نمی پرسد آنها چه می پوشند.",
"horizon.extras.cosmetics_auras": "هاله ها و مسیرهای دیگران",
"horizon.extras.cosmetics_auras.tooltip": "هاله ها و دنباله های دیگر بازیکنان می پوشند. به طور پیش فرض خاموش است.",
"horizon.extras.cosmetics_hide_fx": "پنهان کردن ردها و هاله‌های بازیکنان دیگر",
"horizon.extras.cosmetics_hide_fx.tooltip": "ردها و هاله‌های بازیکنان دیگر پنهان می‌مانند؛ دیگر آرایه‌هایشان همچنان دیده می‌شوند. به‌طور پیش‌فرض خاموش.",
"horizon.extras.cosmetics.shown": "نشان داده شده است",
"horizon.extras.cosmetics.hidden": "پنهان شده است",
"horizon.extras.cosmetics.name_tags": "فقط برچسب های نام"
@@ -449,8 +449,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Piilotettu: jokainen Horizon-pelaaja näkee sinut ilman kosmetiikkaasi, sinä mukaan lukien. Sama kytkin kuin kantoraketin vaatekaappi.",
"horizon.extras.cosmetics_others": "Muiden pelaajien kosmetiikkaa",
"horizon.extras.cosmetics_others.tooltip": "Mitä muut Horizon-pelaajat käyttävät: kaikki, vain heidän nimilaputyylinsä tai ei mitään. Piilotettu, peli ei koskaan kysy, mitä he käyttävät.",
"horizon.extras.cosmetics_auras": "Toisten aurat ja polut",
"horizon.extras.cosmetics_auras.tooltip": "Aurat ja jäljet, joita muut pelaajat käyttävät. Oletuksena pois päältä.",
"horizon.extras.cosmetics_hide_fx": "Piilota muiden pelaajien jäljet ja aurat",
"horizon.extras.cosmetics_hide_fx.tooltip": "Muiden pelaajien jäljet ja aurat pysyvät piilossa; heidän muut kosmetiikkansa näkyvät yhä. Oletuksena pois.",
"horizon.extras.cosmetics.shown": "Näytetään",
"horizon.extras.cosmetics.hidden": "Piilotettu",
"horizon.extras.cosmetics.name_tags": "Vain nimilaput",
@@ -421,8 +421,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Nakatago: makikita ka ng bawat Horizon na manlalaro nang wala ang iyong mga pampaganda, kasama mo. Ang parehong switch bilang Wardrobe ng launcher.",
"horizon.extras.cosmetics_others": "Mga pampaganda ng ibang manlalaro",
"horizon.extras.cosmetics_others.tooltip": "Ano ang isinusuot ng iba pang Horizon na manlalaro: lahat, mga istilo lang ng name tag nila, o wala. Nakatago, ang laro ay hindi nagtatanong kung ano ang kanilang isinusuot.",
"horizon.extras.cosmetics_auras": "Mga aura at landas ng iba",
"horizon.extras.cosmetics_auras.tooltip": "Mga aura at trail na isinusuot ng ibang mga manlalaro. Naka-off bilang default.",
"horizon.extras.cosmetics_hide_fx": "Itago ang mga bakas at aura ng ibang manlalaro",
"horizon.extras.cosmetics_hide_fx.tooltip": "Nakatago ang mga bakas at aura ng ibang manlalaro; nakikita pa rin ang iba nilang cosmetics. Naka-off bilang default.",
"horizon.extras.cosmetics.shown": "Ipinakita",
"horizon.extras.cosmetics.hidden": "Nakatago",
"horizon.extras.cosmetics.name_tags": "Mga name tag lang",
@@ -471,8 +471,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Dult: hvør Horizon spælari sær teg uttan títt kosmetikk, tú eisini. Sama rotari sum Klædnaskápið hjá sjósetaranum.",
"horizon.extras.cosmetics_others": "Kosmetikkur hjá øðrum spælarum",
"horizon.extras.cosmetics_others.tooltip": "Hvat aðrir Horizon spælarar eru í: alt, bara teirra navnamerkjastílar, ella einki. Dult spyr spælið ongantíð, hvat tey eru í.",
"horizon.extras.cosmetics_auras": "Aura og slóðir hjá øðrum",
"horizon.extras.cosmetics_auras.tooltip": "Auras og slóðir aðrir spælarar bera. Sløkt sum standard.",
"horizon.extras.cosmetics_hide_fx": "Fjal spor og aurur hjá øðrum leikarum",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spor og aurur hjá øðrum leikarum verða fjald; teirra aðrir prýðislutir síggjast framvegis. Sløkt sum standard.",
"horizon.extras.cosmetics.shown": "Víst",
"horizon.extras.cosmetics.hidden": "Dult",
"horizon.extras.cosmetics.name_tags": "Einans navnamerki"
@@ -46,6 +46,25 @@
"horizon.mods.dev": " (dév.)",
"horizon.mods.settings": "Options",
"horizon.mods.open_folder": "Ouvrir le dossier des mods",
"horizon.mods.browse": "Parcourir les mods...",
"horizon.mods.browse.title": "Parcourir les mods",
"horizon.mods.browse.search": "Rechercher des mods...",
"horizon.mods.browse.project": "Mod",
"horizon.mods.browse.loading": "Lecture du registre des mods Horizon...",
"horizon.mods.browse.failed": "Impossible de lire le registre des mods : %s",
"horizon.mods.browse.none": "Aucun mod trouvé",
"horizon.mods.browse.has_update": " (mise à jour)",
"horizon.mods.browse.is_installed": " (installé)",
"horizon.mods.browse.by": "par %s",
"horizon.mods.browse.installing": "Installation...",
"horizon.mods.browse.install": "Installer",
"horizon.mods.browse.update": "Mettre à jour",
"horizon.mods.browse.installed": "Installé",
"horizon.mods.browse.open_page": "Ouvrir la page",
"horizon.mods.browse.enabled": "Mod",
"horizon.mods.browse.changelog": "Nouveautés",
"horizon.mods.browse.done": "%s %s est installé et activé. Son contenu se charge au prochain démarrage du jeu.",
"horizon.mods.browse.install_failed": "Installation impossible : %s",
"horizon.shader_packs.empty": "Aucun pack de shaders : placez-les dans le dossier shaderpacks",
"horizon.shader_options.open": "Options des shaders...",
"horizon.shader_options.profile": "Profil",
@@ -394,10 +413,14 @@
"horizon.extras.header.cosmetics": "Cosmétiques",
"horizon.extras.cosmetics_mine": "Mes cosmétiques",
"horizon.extras.cosmetics_mine.tooltip": "Masqués : tous les joueurs Horizon vous voient sans vos cosmétiques, vous compris. Le même réglage que la garde-robe du launcher.",
"key.emote": "Roue des emotes",
"horizon.emote_wheel.title": "Emotes",
"horizon.emote_wheel.empty": "Pas encore d'emote",
"horizon.emote_wheel.help": "Relâche ou clique pour jouer · 1–8 · Échap ferme",
"horizon.extras.cosmetics_others": "Cosmétiques des autres",
"horizon.extras.cosmetics_others.tooltip": "Ce que portent les autres joueurs Horizon : tout, seulement leur style d'étiquette de nom, ou rien. Masqués si vous n'avez pas de cosmétiques, tant que vous n'avez pas choisi. Masqués, le jeu ne demande jamais ce qu'ils portent.",
"horizon.extras.cosmetics_auras": "Auras et traînées des autres",
"horizon.extras.cosmetics_auras.tooltip": "Les auras et traînées que portent les autres joueurs. Désactivé par défaut.",
"horizon.extras.cosmetics_hide_fx": "Masquer les traînées et auras des autres joueurs",
"horizon.extras.cosmetics_hide_fx.tooltip": "Les traînées et auras des autres joueurs restent masquées ; leurs autres cosmétiques restent visibles. Désactivé par défaut.",
"horizon.extras.cosmetics.shown": "Affichés",
"horizon.extras.cosmetics.hidden": "Masqués",
"horizon.extras.cosmetics.name_tags": "Étiquettes seulement",
@@ -467,8 +467,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Scuindût: ogni zuiadôr Horizon al viôt cence il to cosmetic, tu ancje. Il stes interrutôr dal Armadi dal lançadôr.",
"horizon.extras.cosmetics_others": "I cosmetics dai altris zuiadôrs",
"horizon.extras.cosmetics_others.tooltip": "Ce che a metin sù altris zuiadôrs Horizon: dut, dome i lôr stîi di etichetis, o nuie. Scuindût, il zûc nol domande mai ce che a metin sù.",
"horizon.extras.cosmetics_auras": "Auris e sentiers di altris",
"horizon.extras.cosmetics_auras.tooltip": "Auris e pistis che a metin sù altris zuiadôrs. Disactivât par automatic.",
"horizon.extras.cosmetics_hide_fx": "Plate lis olmis e lis aureis dai altris zuiadôrs",
"horizon.extras.cosmetics_hide_fx.tooltip": "Lis olmis e lis aureis dai altris zuiadôrs a restin platadis; i lôr altris cosmetics si viodin ancjemò. Distudât di predefinît.",
"horizon.extras.cosmetics.shown": "Mostrât",
"horizon.extras.cosmetics.hidden": "Scuindût",
"horizon.extras.cosmetics.name_tags": "Dome lis etichetis dai nons"
@@ -399,8 +399,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Ferburgen: elke Horizon-spiler sjocht jo sûnder jo kosmetika, jo ynbegrepen. Deselde switch as de Launcher syn Wardrobe.",
"horizon.extras.cosmetics_others": "Oare spilers 'cosmetica",
"horizon.extras.cosmetics_others.tooltip": "Wat oare Horizon-spilers drage: alles, allinich har nammelabelstilen, of neat. Ferburgen, it spultsje freget noait wat se drage.",
"horizon.extras.cosmetics_auras": "Oare aura's en spoaren",
"horizon.extras.cosmetics_auras.tooltip": "Auras en spoaren oare spilers drage. Standert út.",
"horizon.extras.cosmetics_hide_fx": "Spoaren en aura's fan oare spilers ferbergje",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spoaren en aura's fan oare spilers bliuwe ferburgen; harren oare kosmetika bliuwt sichtber. Standert út.",
"horizon.extras.cosmetics.shown": "Oanjûn",
"horizon.extras.cosmetics.hidden": "Ferburgen",
"horizon.extras.cosmetics.name_tags": "Allinnich nammelabels"
@@ -463,8 +463,8 @@
"horizon.extras.cosmetics_mine.tooltip": "I bhfolach: feiceann gach imreoirHorizon tú gan do chosmaidí, tú san áireamh. An lasc céanna le Wardrobe an tosaitheoir.",
"horizon.extras.cosmetics_others": "Cosmaidí imreoirí eile",
"horizon.extras.cosmetics_others.tooltip": "Cad a chaitheann imreoirí Horizon eile: gach rud, gan ach a stíleanna clibeanna ainm, nó rud ar bith. I bhfolach, ní iarrann an cluiche riamh cad a chaitheann siad.",
"horizon.extras.cosmetics_auras": "Auras agus cosáin daoine eile",
"horizon.extras.cosmetics_auras.tooltip": "Auras agus rianta a chaitheamh imreoirí eile. Off de réir réamhshocraithe.",
"horizon.extras.cosmetics_hide_fx": "Folaigh rianta agus aurataí imreoirí eile",
"horizon.extras.cosmetics_hide_fx.tooltip": "Fanann rianta agus aurataí imreoirí eile i bhfolach; feictear a gcuid maisithe eile fós. As de réir réamhshocraithe.",
"horizon.extras.cosmetics.shown": "Taispeántar",
"horizon.extras.cosmetics.hidden": "i bhfolach",
"horizon.extras.cosmetics.name_tags": "Clibeanna ainm amháin"
@@ -464,8 +464,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Falaichte: chì a h-uile cluicheadair Horizon thu às aonais na cungaidhean maise agad, thug thu a-steach. An aon tionndadh ri Wardrobe an lannsair.",
"horizon.extras.cosmetics_others": "Coltas cluicheadairean eile",
"horizon.extras.cosmetics_others.tooltip": "Na bhios cluicheadairean Horizon eile a’ caitheamh: a h-uile càil, dìreach na stoidhlichean tag ainm aca, no dad. Falaichte, cha bhith an geama a-riamh a’ faighneachd dè a bhios orra.",
"horizon.extras.cosmetics_auras": "Auras agus slighean cuid eile",
"horizon.extras.cosmetics_auras.tooltip": "Auras agus slighean bidh cluicheadairean eile a’ caitheamh. Cuir dheth gu bunaiteach.",
"horizon.extras.cosmetics_hide_fx": "Falaich slighean is aurathan chluicheadairean eile",
"horizon.extras.cosmetics_hide_fx.tooltip": "Fanaidh slighean is aurathan chluicheadairean eile falaichte; chithear an cuid maise eile fhathast. Dheth a ghnàth.",
"horizon.extras.cosmetics.shown": "Air a shealltainn",
"horizon.extras.cosmetics.hidden": "Falaichte",
"horizon.extras.cosmetics.name_tags": "Tagaichean ainmean a-mhàin"
@@ -463,8 +463,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Oculto: todos os xogadores de Horizon venche sen os teus cosméticos, ti incluído. O mesmo interruptor que o garda-roupa do lanzador.",
"horizon.extras.cosmetics_others": "Cosmética doutros xogadores",
"horizon.extras.cosmetics_others.tooltip": "Que usan outros Horizon xogadores: todo, só os seus estilos de etiqueta de nome ou nada. Oculto, o xogo nunca pregunta que visten.",
"horizon.extras.cosmetics_auras": "Auras e sendeiros doutros",
"horizon.extras.cosmetics_auras.tooltip": "Auras e rastros que levan outros xogadores. Desactivado por defecto.",
"horizon.extras.cosmetics_hide_fx": "Agochar as estelas e auras doutros xogadores",
"horizon.extras.cosmetics_hide_fx.tooltip": "As estelas e auras doutros xogadores quedan agochadas; os seus outros cosméticos séguense vendo. Desactivado por defecto.",
"horizon.extras.cosmetics.shown": "Amosado",
"horizon.extras.cosmetics.hidden": "Oculto",
"horizon.extras.cosmetics.name_tags": "Só etiquetas de nome"
@@ -458,8 +458,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Huna: ʻike kēlā me kēia Horizon iā ʻoe me ka ʻole o kāu mea hoʻonaninani, ua hoʻokomo ʻoe. ʻO ka hoʻololi like e like me ka mea hoʻolele lole.",
"horizon.extras.cosmetics_others": "ʻO nā mea hoʻonani o nā mea pāʻani ʻē aʻe",
"horizon.extras.cosmetics_others.tooltip": "He aha nā mea pāʻani Horizon ʻē aʻe e ʻaʻahu ai: nā mea āpau, nā ʻano inoa inoa wale nō, a ʻaʻohe mea. Huna, ʻaʻole nīnau ka pāʻani i kā lākou lole.",
"horizon.extras.cosmetics_auras": "ʻO nā aura a me nā alahele o nā poʻe ʻē aʻe",
"horizon.extras.cosmetics_auras.tooltip": "ʻO Auras a me nā alahele e hoʻohana ai nā mea pāʻani. Paʻa ma ka paʻamau.",
"horizon.extras.cosmetics_hide_fx": "Hūnā i nā meheu a me nā aura o nā mea pāʻani ʻē aʻe",
"horizon.extras.cosmetics_hide_fx.tooltip": "Hūnā ʻia nā meheu a me nā aura o nā mea pāʻani ʻē aʻe; ʻike ʻia nō kā lākou mau mea hoʻonani ʻē aʻe. Pio ma ke ʻano maʻamau.",
"horizon.extras.cosmetics.shown": "Hōʻike ʻia",
"horizon.extras.cosmetics.hidden": "Huna",
"horizon.extras.cosmetics.name_tags": "Nā inoa inoa wale nō"
@@ -465,8 +465,8 @@
"horizon.extras.cosmetics_mine": "הקוסמטיקה שלי",
"horizon.extras.cosmetics_others": "מוצרי קוסמטיקה של שחקנים אחרים",
"horizon.extras.cosmetics_others.tooltip": "מה שחקני Horizon אחרים לובשים: הכל, רק סגנונות תג השם שלהם, או כלום. נסתר, המשחק אף פעם לא שואל מה הם לובשים.",
"horizon.extras.cosmetics_auras": "ההילות והשבילים של אחרים",
"horizon.extras.cosmetics_auras.tooltip": "הילות ושבילים ששחקנים אחרים לובשים. כבוי כברירת מחדל.",
"horizon.extras.cosmetics_hide_fx": "הסתרת שבילים והילות של שחקנים אחרים",
"horizon.extras.cosmetics_hide_fx.tooltip": "השבילים וההילות של שחקנים אחרים נשארים מוסתרים; שאר הקוסמטיקה שלהם עדיין מוצגת. כבוי כברירת מחדל.",
"horizon.extras.cosmetics.shown": "מוצג",
"horizon.extras.cosmetics.hidden": "מוסתר",
"horizon.extras.cosmetics.name_tags": "תגי שם בלבד",
@@ -458,8 +458,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Rejtett: minden Horizon játékos lát téged a kozmetikumai nélkül, beleértve Önt is. Ugyanaz a kapcsoló, mint az indító gardróbjában.",
"horizon.extras.cosmetics_others": "Más játékosok kozmetikumai",
"horizon.extras.cosmetics_others.tooltip": "Amit a többi Horizon játékos visel: mindent, csak a névcímkék stílusát, vagy semmit. Rejtett, a játék soha nem kérdezi, mit viselnek.",
"horizon.extras.cosmetics_auras": "Mások aurái és nyomai",
"horizon.extras.cosmetics_auras.tooltip": "Más játékosok által viselt aurák és nyomvonalak. Alapértelmezés szerint ki.",
"horizon.extras.cosmetics_hide_fx": "Más játékosok nyomainak és auráinak elrejtése",
"horizon.extras.cosmetics_hide_fx.tooltip": "Más játékosok nyomai és aurái rejtve maradnak; a többi kozmetikumuk továbbra is látszik. Alapértelmezetten ki.",
"horizon.extras.cosmetics.shown": "Megjelenítve",
"horizon.extras.cosmetics.hidden": "Rejtett",
"horizon.extras.cosmetics.name_tags": "Csak névcímkék"
@@ -464,8 +464,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Թաքնված. յուրաքանչյուր Horizon խաղացող ձեզ տեսնում է առանց ձեր կոսմետիկայի, այդ թվում՝ դուք: Նույն անջատիչը, ինչ գործարկիչի զգեստապահարան:",
"horizon.extras.cosmetics_others": "Այլ խաղացողների կոսմետիկա",
"horizon.extras.cosmetics_others.tooltip": "Ինչ են հագնում մյուս Horizon խաղացողները. ամեն ինչ, միայն նրանց անվան պիտակի ոճերը, կամ ոչինչ: Թաքնված, խաղը երբեք չի հարցնում, թե ինչ են նրանք հագնում:",
"horizon.extras.cosmetics_auras": "Ուրիշների աուրաներն ու արահետները",
"horizon.extras.cosmetics_auras.tooltip": "Աուրաները և արահետները կրում են այլ խաղացողներ: Լռելյայն անջատված է:",
"horizon.extras.cosmetics_hide_fx": "Թաքցնել այլ խաղացողների հետքերն ու աուրաները",
"horizon.extras.cosmetics_hide_fx.tooltip": "Այլ խաղացողների հետքերն ու աուրաները մնում են թաքնված. նրանց մյուս կոսմետիկան դեռ երևում է։ Լռելյայն անջատված է։",
"horizon.extras.cosmetics.shown": "Ցուցադրված է",
"horizon.extras.cosmetics.hidden": "Թաքնված",
"horizon.extras.cosmetics.name_tags": "Միայն անունների պիտակներ"
@@ -460,8 +460,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Zoro ezo: Onye ọkpụkpọ ọ bụla Horizon na-ahụ gị na-enweghị ihe ịchọ mma gị, ị gụnyere. Otu mgbanwe dị ka Wardrobe nke onye mbido.",
"horizon.extras.cosmetics_others": "Ngwa mma ndị egwuregwu ndị ọzọ",
"horizon.extras.cosmetics_others.tooltip": "Ihe ndị ọzọ Horizon Player na-eyi: ihe niile, naanị aha mkpado styles, ma ọ bụ ihe ọ bụla. Na nzuzo, egwuregwu anaghị ajụ ihe ha na-eyi.",
"horizon.extras.cosmetics_auras": "Auras na ụzọ ndị ọzọ",
"horizon.extras.cosmetics_auras.tooltip": "Auras na ụzọ ndị egwuregwu ndị ọzọ na-eyi. Gbanyụọ na ndabara.",
"horizon.extras.cosmetics_hide_fx": "Zoo akara ụkwụ na aura ndị egwuregwu ndị ọzọ",
"horizon.extras.cosmetics_hide_fx.tooltip": "Akara ụkwụ na aura ndị egwuregwu ndị ọzọ na-anọgide zoro ezo; ihe ịchọ mma ha ndị ọzọ ka na-egosi. Gbanyụrụ na ndabara.",
"horizon.extras.cosmetics.shown": "Egosiri",
"horizon.extras.cosmetics.hidden": "Zoro ezo",
"horizon.extras.cosmetics.name_tags": "Naanị mkpado aha"
@@ -465,8 +465,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Falinn: sérhver Horizon leikmaður sér þig án snyrtivörunnar þinnar, þú meðtalin. Sami rofi og fataskápur sjósetjunnar.",
"horizon.extras.cosmetics_others": "Snyrtivörur annarra leikmanna",
"horizon.extras.cosmetics_others.tooltip": "Það sem aðrir Horizon-spilarar klæðast: allt, aðeins nafnmerkisstíllinn eða ekkert. Falinn, leikurinn spyr aldrei hverju þeir klæðist.",
"horizon.extras.cosmetics_auras": "Aurar og slóðir annarra",
"horizon.extras.cosmetics_auras.tooltip": "Auras og slóðir sem aðrir leikmenn klæðast. Slökkt sjálfgefið.",
"horizon.extras.cosmetics_hide_fx": "Fela slóðir og árur annarra leikmanna",
"horizon.extras.cosmetics_hide_fx.tooltip": "Slóðir og árur annarra leikmanna eru faldar; aðrir skrautmunir þeirra sjást áfram. Slökkt sjálfgefið.",
"horizon.extras.cosmetics.shown": "Sýnd",
"horizon.extras.cosmetics.hidden": "Falinn",
"horizon.extras.cosmetics.name_tags": "Eingöngu nafnamerki",
@@ -480,8 +480,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Nascosto: ogni giocatore di Horizon ti vede senza i tuoi cosmetici, incluso te. Lo stesso interruttore dell'armadio del lanciatore.",
"horizon.extras.cosmetics_others": "Cosmetici di altri giocatori",
"horizon.extras.cosmetics_others.tooltip": "Cosa indossano gli altri giocatori di Horizon: tutto, solo lo stile delle etichette con il nome o niente. Nascosto, il gioco non chiede mai cosa indossano.",
"horizon.extras.cosmetics_auras": "Aure e tracce degli altri",
"horizon.extras.cosmetics_auras.tooltip": "Aure e tracce indossate da altri giocatori. Disattivato per impostazione predefinita.",
"horizon.extras.cosmetics_hide_fx": "Nascondi scie e aure degli altri giocatori",
"horizon.extras.cosmetics_hide_fx.tooltip": "Le scie e le aure degli altri giocatori restano nascoste; gli altri loro cosmetici restano visibili. Disattivato per impostazione predefinita.",
"horizon.extras.cosmetics.shown": "Mostrato",
"horizon.extras.cosmetics.hidden": "Nascosto",
"horizon.extras.cosmetics.name_tags": "Solo targhette con nome"
@@ -487,8 +487,8 @@
"horizon.extras.cosmetics_mine.tooltip": "非表示: すべての Horizon プレイヤーは、あなたも含め、化粧品を着用していないあなたを見ます。ランチャーのワードローブと同じスイッチ。",
"horizon.extras.cosmetics_others": "他のプレイヤーの化粧品",
"horizon.extras.cosmetics_others.tooltip": "他の Horizon プレイヤーが着ているもの: すべて、名札のスタイルのみ、または何も着ていません。隠されていますが、ゲームでは彼らが何を着ているかは尋ねられません。",
"horizon.extras.cosmetics_auras": "他人のオーラと軌跡",
"horizon.extras.cosmetics_auras.tooltip": "他のプレイヤーが身に着けているオーラと軌跡。デフォルトではオフです。",
"horizon.extras.cosmetics_hide_fx": "他のプレイヤーの軌跡とオーラを隠す",
"horizon.extras.cosmetics_hide_fx.tooltip": "他のプレイヤーの軌跡とオーラを非表示にします。それ以外のコスメティックは表示されたままです。デフォルトはオフ。",
"horizon.extras.cosmetics.shown": "示されている",
"horizon.extras.cosmetics.hidden": "隠された",
"horizon.extras.cosmetics.name_tags": "ネームタグのみ"
@@ -472,8 +472,8 @@
"horizon.extras.cosmetics_mine.tooltip": "დამალული: ყოველი Horizon მოთამაშე გხედავთ თქვენი კოსმეტიკის გარეშე, თქვენ ჩათვლით. იგივე გადამრთველი, როგორც გამშვების გარდერობი.",
"horizon.extras.cosmetics_others": "სხვა მოთამაშეების კოსმეტიკა",
"horizon.extras.cosmetics_others.tooltip": "რას აცვია სხვა Horizon მოთამაშეები: ყველაფერი, მხოლოდ მათი სახელების სტილები, ან არაფერი. დამალული, თამაში არასდროს ეკითხება, რა აცვიათ.",
"horizon.extras.cosmetics_auras": "სხვების აურა და ბილიკები",
"horizon.extras.cosmetics_auras.tooltip": "აურები და ბილიკები ატარებენ სხვა მოთამაშეებს. ნაგულისხმევად გამორთულია.",
"horizon.extras.cosmetics_hide_fx": "სხვა მოთამაშეების კვალისა და აურების დამალვა",
"horizon.extras.cosmetics_hide_fx.tooltip": "სხვა მოთამაშეების კვალი და აურები დამალული რჩება; მათი სხვა კოსმეტიკა კვლავ ჩანს. ნაგულისხმევად გამორთულია.",
"horizon.extras.cosmetics.shown": "ნაჩვენებია",
"horizon.extras.cosmetics.hidden": "დამალული",
"horizon.extras.cosmetics.name_tags": "მხოლოდ სახელების ტეგები"
@@ -474,8 +474,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Жасырын: әрбір Horizon ойыншы сізді косметикасыз көреді, сіз қосасыз. Іске қосу құрылғысының гардеробымен бірдей қосқыш.",
"horizon.extras.cosmetics_others": "Басқа ойыншылардың косметикасы",
"horizon.extras.cosmetics_others.tooltip": "Басқа Horizon ойыншылары не киеді: барлығы, тек олардың атау тегінің стильдері немесе ештеңе жоқ. Жасырын, ойын ешқашан не киетінін сұрамайды.",
"horizon.extras.cosmetics_auras": "Басқалардың ауралары мен жолдары",
"horizon.extras.cosmetics_auras.tooltip": "Басқа ойыншылар киетін ауралар мен жолдар. Әдепкі бойынша өшірулі.",
"horizon.extras.cosmetics_hide_fx": "Басқа ойыншылардың іздері мен аураларын жасыру",
"horizon.extras.cosmetics_hide_fx.tooltip": "Басқа ойыншылардың іздері мен ауралары жасырын қалады; олардың басқа косметикасы көрінеді. Әдепкі бойынша өшірулі.",
"horizon.extras.cosmetics.shown": "Көрсетілген",
"horizon.extras.cosmetics.hidden": "Жасырын",
"horizon.extras.cosmetics.name_tags": "Тек атау тегтері"
@@ -481,8 +481,8 @@
"horizon.extras.cosmetics_mine.tooltip": "ಮರೆಮಾಡಲಾಗಿದೆ: ಪ್ರತಿ Horizon ಪ್ಲೇಯರ್ ನಿಮ್ಮ ಸೌಂದರ್ಯವರ್ಧಕಗಳಿಲ್ಲದೆ ನಿಮ್ಮನ್ನು ನೋಡುತ್ತಾರೆ, ನೀವು ಸೇರಿಸಿದ್ದೀರಿ. ಲಾಂಚರ್‌ನ ವಾರ್ಡ್‌ರೋಬ್‌ನಂತೆಯೇ ಅದೇ ಸ್ವಿಚ್.",
"horizon.extras.cosmetics_others": "ಇತರ ಆಟಗಾರರ ಸೌಂದರ್ಯವರ್ಧಕಗಳು",
"horizon.extras.cosmetics_others.tooltip": "ಇತರ Horizon ಆಟಗಾರರು ಏನು ಧರಿಸುತ್ತಾರೆ: ಎಲ್ಲವೂ, ಅವರ ಹೆಸರಿನ ಟ್ಯಾಗ್ ಶೈಲಿಗಳು ಅಥವಾ ಏನೂ ಇಲ್ಲ. ಮರೆಮಾಡಲಾಗಿದೆ, ಆಟವು ಅವರು ಏನು ಧರಿಸುತ್ತಾರೆ ಎಂದು ಎಂದಿಗೂ ಕೇಳುವುದಿಲ್ಲ.",
"horizon.extras.cosmetics_auras": "ಇತರರ ಸೆಳವು ಮತ್ತು ಹಾದಿಗಳು",
"horizon.extras.cosmetics_auras.tooltip": "ಔರಾಸ್ ಮತ್ತು ಟ್ರೇಲ್ಸ್ ಇತರ ಆಟಗಾರರು ಧರಿಸುತ್ತಾರೆ. ಡೀಫಾಲ್ಟ್ ಆಗಿ ಆಫ್.",
"horizon.extras.cosmetics_hide_fx": "ಇತರ ಆಟಗಾರರ ಹಾದಿಗಳು ಮತ್ತು ಪ್ರಭಾವಳಿಗಳನ್ನು ಮರೆಮಾಡಿ",
"horizon.extras.cosmetics_hide_fx.tooltip": "ಇತರ ಆಟಗಾರರ ಹಾದಿಗಳು ಮತ್ತು ಪ್ರಭಾವಳಿಗಳು ಮರೆಯಾಗಿರುತ್ತವೆ; ಅವರ ಇತರ ಅಲಂಕಾರಗಳು ಕಾಣುತ್ತವೆ. ಪೂರ್ವನಿಯೋಜಿತವಾಗಿ ಆಫ್.",
"horizon.extras.cosmetics.shown": "ತೋರಿಸಲಾಗಿದೆ",
"horizon.extras.cosmetics.hidden": "ಮರೆಮಾಡಲಾಗಿದೆ",
"horizon.extras.cosmetics.name_tags": "ಹೆಸರು ಟ್ಯಾಗ್‌ಗಳು ಮಾತ್ರ"
@@ -448,8 +448,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Жашырылган: ар бир Horizon оюнчу сизди косметикасыз көрөт. Ишке киргизгичтин гардеробу сыяктуу эле которгуч.",
"horizon.extras.cosmetics_others": "Башка оюнчулардын косметикасы",
"horizon.extras.cosmetics_others.tooltip": "Башка Horizon оюнчулары кандай кийимдерди кийишет: бардыгы, алардын аты тегинин стили гана же эч нерсе. Жашыруун, оюн эч качан алар эмне кийип жүргөнүн сурабайт.",
"horizon.extras.cosmetics_auras": "Башкалардын ауралары жана жолдору",
"horizon.extras.cosmetics_auras.tooltip": "Ауралар жана башка оюнчулар кийген жолдор. Демейки боюнча өчүк.",
"horizon.extras.cosmetics_hide_fx": "Башка оюнчулардын издерин жана ауралары жашыруу",
"horizon.extras.cosmetics_hide_fx.tooltip": "Башка оюнчулардын издери жана ауралары жашыруун калат; алардын башка косметикасы көрүнөт. Демейки боюнча өчүк.",
"horizon.extras.cosmetics.shown": "Көрсөтүлдү",
"horizon.extras.cosmetics.hidden": "Жашырылган",
"horizon.extras.cosmetics.name_tags": "Аталышы гана"
@@ -399,8 +399,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Occultus: omnisHorizonlusor te sine tuis fucis videt, te comprehendit. Idem transitum cum vestiario launcher.",
"horizon.extras.cosmetics_others": "Alii histriones medicamentis",
"horizon.extras.cosmetics_others.tooltip": "Quid aliud?Horizonhistriones gerunt: omnia, solum nomen tag stili, vel nihil. Occultus, ludus numquam quaerit quod gerunt.",
"horizon.extras.cosmetics_auras": "Aliorum auras et calles",
"horizon.extras.cosmetics_auras.tooltip": "Auras et calles alii lusores gerunt. Off per defaltam.",
"horizon.extras.cosmetics_hide_fx": "Vestigia et auras aliorum lusorum celare",
"horizon.extras.cosmetics_hide_fx.tooltip": "Vestigia et aurae aliorum lusorum celata manent; cetera ornamenta eorum adhuc videntur. Ex defalta exstinctum.",
"horizon.extras.cosmetics.shown": "Ostensum",
"horizon.extras.cosmetics.hidden": "Occultus",
"horizon.extras.cosmetics.name_tags": "Nomen tags tantum"
@@ -435,8 +435,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Verstoppt: all Horizon Spiller gesäit Iech ouni Är Kosmetik, Dir abegraff. Deeselwechte Schalter wéi de Launcher Kleederschaf.",
"horizon.extras.cosmetics_others": "Aner Spiller Kosmetik",
"horizon.extras.cosmetics_others.tooltip": "Wat aner Horizon Spiller droen: alles, nëmmen hir Numm Tag Stiler, oder näischt. Verstoppt, d'Spill freet ni wat se droen.",
"horizon.extras.cosmetics_auras": "Anerer hir Auraen an Trëppelweeër",
"horizon.extras.cosmetics_auras.tooltip": "Auras an Trëppelweeër aner Spiller zouzedrécken. Off par défaut.",
"horizon.extras.cosmetics_hide_fx": "Spueren an Auraen vun anere Spiller verstoppen",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spueren an Auraen vun anere Spiller bleiwe verstoppt; hir aner Kosmetik ass ëmmer nach ze gesinn. Standardméisseg aus.",
"horizon.extras.cosmetics.shown": "gewisen",
"horizon.extras.cosmetics.hidden": "Verstoppt",
"horizon.extras.cosmetics.name_tags": "Numm Tags nëmmen"
@@ -434,8 +434,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Verborge: eder Horizon speuler ziet dich zoonder dien cosmetica, inclusief dich. Dezelfde schakelaar es de garderobe vaan de launcher.",
"horizon.extras.cosmetics_others": "Cosmetica vaan aandere speulers",
"horizon.extras.cosmetics_others.tooltip": "Wat aandere Horizon speulers drage: alles, allein hun stijl vaan naamlabel, of niks. Verborge, vraog ‘t spel noets wat ze drage.",
"horizon.extras.cosmetics_auras": "Auras en spore vaan aandere",
"horizon.extras.cosmetics_auras.tooltip": "Auras en spore die aandere speulers drage. Standaard oet.",
"horizon.extras.cosmetics_hide_fx": "Spore en aura's van anger spelers verberge",
"horizon.extras.cosmetics_hide_fx.tooltip": "Spore en aura's van anger spelers blieve verborge; hun anger cosmetica blieve zichbaar. Standaard oet.",
"horizon.extras.cosmetics.shown": "Getoend",
"horizon.extras.cosmetics.hidden": "Verborge",
"horizon.extras.cosmetics.name_tags": "Allein naamtags"
@@ -474,5 +474,5 @@
"horizon.extras.cosmetics_mine.tooltip": "Ascüs: tüt i giucadur Horizon te veden senza i tò cosmetich, anca tì. L’istess interruttur del guardaroba del lanciador.",
"horizon.extras.cosmetics_others": "Cosmetich di olter giucadur",
"horizon.extras.cosmetics_others.tooltip": "Che ròbb che purtan sü i olter giucadur Horizon: tüt, sultant i luur stil de etichett o nient. Ascüs, el giœugh dumanda mai cus’è che g’han sü.",
"horizon.extras.cosmetics_auras.tooltip": "Auras and trails other players wear. Disattiva per predefiniziun."
"horizon.extras.cosmetics_hide_fx.tooltip": "I strasc e i aur di olter giugadur resten scondu; i sò olter cosmetegh se veden anmò. Smorzaa de default."
}
@@ -464,8 +464,8 @@
"horizon.extras.cosmetics_mine.tooltip": "ເຊື່ອງໄວ້: ຜູ້ນ Horizon ທຸກຄົນເຫັນທ່ານໂດຍບໍ່ມີເຄື່ອງສໍາອາງຂອງທ່ານ, ທ່ານລວມ. ສະຫຼັບດຽວກັນກັບຕູ້ເສື້ອຜ້າຂອງຕົວເປີດ.",
"horizon.extras.cosmetics_others": "ເຄື່ອງສໍາອາງຂອງຜູ້ນອື່ນໆ",
"horizon.extras.cosmetics_others.tooltip": "ສິ່ງທີ່ຜູ້ຫຼິ້ນ Horizon ຄົນອື່ນໆໃສ່: ທຸກຢ່າງ, ພຽງແຕ່ຮູບແບບປ້າຍຊື່ຂອງເຂົາເຈົ້າ, ຫຼືບໍ່ມີຫຍັງ. ເຊື່ອງໄວ້, ເກມບໍ່ເຄີຍຖາມວ່າພວກເຂົາໃສ່ຫຍັງ.",
"horizon.extras.cosmetics_auras": "ອໍຣາ ແລະເສັ້ນທາງຂອງຄົນອື່ນ",
"horizon.extras.cosmetics_auras.tooltip": "Aura ແລະ trails ຜູ້ນອື່ນໆໃສ່. ປິດຕາມຄ່າເລີ່ມຕົ້ນ.",
"horizon.extras.cosmetics_hide_fx": "ເຊື່ອງຮອຍ ແລະ ອໍຣາຂອງຜູ້ຫຼິ້ນອື່ນ",
"horizon.extras.cosmetics_hide_fx.tooltip": "ຮອຍ ແລະ ອໍຣາຂອງຜູ້ຫຼິ້ນອື່ນຖືກເຊື່ອງໄວ້; ເຄື່ອງປະດັບອື່ນຂອງເຂົາເຈົ້າຍັງເຫັນຢູ່. ປິດໄວ້ຕາມຄ່າເລີ່ມຕົ້ນ.",
"horizon.extras.cosmetics.shown": "ສະແດງໃຫ້ເຫັນ",
"horizon.extras.cosmetics.hidden": "ເຊື່ອງໄວ້",
"horizon.extras.cosmetics.name_tags": "ປ້າຍຊື່ເທົ່ານັ້ນ",
@@ -467,8 +467,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Paslėpta: kiekvienas „Horizon“ žaidėjas mato jus be jūsų kosmetikos, įskaitant jus. Tas pats jungiklis kaip ir paleidimo priemonės drabužių spinta.",
"horizon.extras.cosmetics_others": "Kitų žaidėjų kosmetika",
"horizon.extras.cosmetics_others.tooltip": "Ką dėvi kiti „Horizon“ žaidėjai: viskas, tik jų vardų etiketės arba nieko. Paslėptas, žaidimas niekada neklausia, ką jie dėvi.",
"horizon.extras.cosmetics_auras": "Kitų auros ir takai",
"horizon.extras.cosmetics_auras.tooltip": "Auros ir takai, kuriuos nešioja kiti žaidėjai. Išjungta pagal numatytuosius nustatymus.",
"horizon.extras.cosmetics_hide_fx": "Slėpti kitų žaidėjų pėdsakus ir auras",
"horizon.extras.cosmetics_hide_fx.tooltip": "Kitų žaidėjų pėdsakai ir auros lieka paslėpti; kita jų kosmetika vis dar matoma. Numatytai išjungta.",
"horizon.extras.cosmetics.shown": "Parodyta",
"horizon.extras.cosmetics.hidden": "Paslėpta",
"horizon.extras.cosmetics.name_tags": "Tik vardų žymos"
@@ -456,8 +456,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Slēpts: katrs Horizon spēlētājs redz jūs bez jūsu kosmētikas, ieskaitot jūs. Tas pats slēdzis kā palaišanas ierīces Garderobe.",
"horizon.extras.cosmetics_others": "Pārējo spēlētāju kosmētika",
"horizon.extras.cosmetics_others.tooltip": "Ko valkā citi Horizon spēlētāji: viss, tikai viņu vārda birku stili vai nekas. Slēpts, spēle nekad nejautā, ko viņi valkā.",
"horizon.extras.cosmetics_auras": "Citu auras un takas",
"horizon.extras.cosmetics_auras.tooltip": "Auras un takas, ko valkā citi spēlētāji. Pēc noklusējuma izslēgts.",
"horizon.extras.cosmetics_hide_fx": "Slēpt citu spēlētāju pēdas un auras",
"horizon.extras.cosmetics_hide_fx.tooltip": "Citu spēlētāju pēdas un auras paliek paslēptas; viņu pārējā kosmētika joprojām redzama. Pēc noklusējuma izslēgts.",
"horizon.extras.cosmetics.shown": "Parādīts",
"horizon.extras.cosmetics.hidden": "Slēpts",
"horizon.extras.cosmetics.name_tags": "Tikai vārdu birkas"
@@ -480,8 +480,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Скриено: секој играч Horizon ве гледа без вашата козметика, вклучително и вие. Истиот прекинувач како и гардеробата на фрлачот.",
"horizon.extras.cosmetics_others": "Козметика за други играчи",
"horizon.extras.cosmetics_others.tooltip": "Што носат другите Horizon играчи: сè, само стилови на нивните ознаки или ништо. Скриено, играта никогаш не прашува што носат.",
"horizon.extras.cosmetics_auras": "Аури и патеки на другите",
"horizon.extras.cosmetics_auras.tooltip": "Аури и патеки што ги носат другите играчи. Исклучено стандардно.",
"horizon.extras.cosmetics_hide_fx": "Скриј ги трагите и аурите на другите играчи",
"horizon.extras.cosmetics_hide_fx.tooltip": "Трагите и аурите на другите играчи остануваат скриени; нивната друга козметика и понатаму се гледа. Стандардно исклучено.",
"horizon.extras.cosmetics.shown": "Прикажани",
"horizon.extras.cosmetics.hidden": "Скриени",
"horizon.extras.cosmetics.name_tags": "Само ознаки со имиња"
@@ -475,8 +475,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Далд: Horizon тоглогч бүр таныг гоо сайхны бүтээгдэхүүнгүйгээр хардаг. Эхлүүлэгчийн хувцасны шүүгээтэй ижил унтраалга.",
"horizon.extras.cosmetics_others": "Бусад тоглогчдын гоо сайхны бүтээгдэхүүн",
"horizon.extras.cosmetics_others.tooltip": "Бусад Horizon тоглогчид юу өмсдөг вэ: бүх зүйл, зөвхөн нэрийн шошго, эсвэл юу ч биш. Нуугдсан, тоглоом хэзээ ч юу өмсдөгийг асуудаггүй.",
"horizon.extras.cosmetics_auras": "Бусдын аура, замууд",
"horizon.extras.cosmetics_auras.tooltip": "Аура болон бусад тоглогчдын өмсдөг замууд. Өгөгдмөлөөр унтраа.",
"horizon.extras.cosmetics_hide_fx": "Бусад тоглогчийн мөр ба аурыг нуух",
"horizon.extras.cosmetics_hide_fx.tooltip": "Бусад тоглогчийн мөр ба аур нуугдсан хэвээр байна; тэдний бусад гоёл харагдсаар байна. Анхдагчаар унтраалттай.",
"horizon.extras.cosmetics.shown": "Үзүүлсэн",
"horizon.extras.cosmetics.hidden": "Нуугдсан",
"horizon.extras.cosmetics.name_tags": "Зөвхөн нэрийн шошго"
@@ -460,8 +460,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Tersembunyi: setiap pemain Horizon melihat anda tanpa kosmetik anda, termasuk anda. Suis yang sama seperti Almari Pakaian pelancar.",
"horizon.extras.cosmetics_others": "Kosmetik pemain lain",
"horizon.extras.cosmetics_others.tooltip": "Perkara yang dipakai oleh pemain Horizon lain: segala-galanya, hanya gaya tanda nama mereka, atau tiada apa-apa. Tersembunyi, permainan tidak pernah bertanya apa yang mereka pakai.",
"horizon.extras.cosmetics_auras": "Aura dan jejak orang lain",
"horizon.extras.cosmetics_auras.tooltip": "Aura dan jejak yang dipakai pemain lain. Mati secara lalai.",
"horizon.extras.cosmetics_hide_fx": "Sembunyikan jejak dan aura pemain lain",
"horizon.extras.cosmetics_hide_fx.tooltip": "Jejak dan aura pemain lain kekal tersembunyi; kosmetik mereka yang lain masih kelihatan. Mati secara lalai.",
"horizon.extras.cosmetics.shown": "Ditunjukkan",
"horizon.extras.cosmetics.hidden": "Tersembunyi",
"horizon.extras.cosmetics.name_tags": "Tanda nama sahaja"
@@ -432,8 +432,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Moħbija: kull plejer Horizon jarak mingħajr il-kożmetiċi tiegħek, int inkluż. L-istess swiċċ bħall-Gwardarobba tal-lanċjar.",
"horizon.extras.cosmetics_others": "Kosmetiċi ta' plejers oħra",
"horizon.extras.cosmetics_others.tooltip": "X'jilbsu plejers oħra ta' Horizon: kollox, l-istili tat-tag tal-isem tagħhom biss, jew xejn. Moħbija, il-logħba qatt ma tistaqsi dak li jilbsu.",
"horizon.extras.cosmetics_auras": "Awra u traċċi ta’ ħaddieħor",
"horizon.extras.cosmetics_auras.tooltip": "Auras u trails plejers oħra jilbsu. Mitfi awtomatikament.",
"horizon.extras.cosmetics_hide_fx": "Aħbi t-traċċi u l-awri ta' plejers oħra",
"horizon.extras.cosmetics_hide_fx.tooltip": "It-traċċi u l-awri ta' plejers oħra jibqgħu moħbija; il-kożmetiċi l-oħra tagħhom jibqgħu jidhru. Mitfi b'mod awtomatiku.",
"horizon.extras.cosmetics.shown": "murija",
"horizon.extras.cosmetics.hidden": "Moħbija",
"horizon.extras.cosmetics.name_tags": "Tikketti tal-isem biss",
@@ -467,8 +467,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Verborgen: elke Horizon-speler ziet je zonder je cosmetica, inclusief jij. Dezelfde schakelaar als de kledingkast van de draagraket.",
"horizon.extras.cosmetics_others": "Cosmetica van andere spelers",
"horizon.extras.cosmetics_others.tooltip": "Wat andere Horizon-spelers dragen: alles, alleen hun naamplaatjestijlen, of niets. Verborgen vraagt het spel nooit wat ze dragen.",
"horizon.extras.cosmetics_auras": "De aura's en sporen van anderen",
"horizon.extras.cosmetics_auras.tooltip": "Aura's en sporen die andere spelers dragen. Standaard uitgeschakeld.",
"horizon.extras.cosmetics_hide_fx": "Sporen en aura's van andere spelers verbergen",
"horizon.extras.cosmetics_hide_fx.tooltip": "Sporen en aura's van andere spelers blijven verborgen; hun andere cosmetica blijven zichtbaar. Standaard uit.",
"horizon.extras.cosmetics.shown": "Getoond",
"horizon.extras.cosmetics.hidden": "Verborgen",
"horizon.extras.cosmetics.name_tags": "Alleen naamplaatjes"
@@ -449,8 +449,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skjult: hver Horizon-spiller ser deg uten kosmetikken din, inkludert du. Samme bryter som bærerakettens garderobe.",
"horizon.extras.cosmetics_others": "Andre spilleres kosmetikk",
"horizon.extras.cosmetics_others.tooltip": "Hva andre Horizon-spillere har på seg: alt, bare navnelappene deres, eller ingenting. Skjult spør spillet aldri hva de har på seg.",
"horizon.extras.cosmetics_auras": "Andres auraer og stier",
"horizon.extras.cosmetics_auras.tooltip": "Auraer og stier andre spillere har på seg. Av som standard.",
"horizon.extras.cosmetics_hide_fx": "Skjul andre spilleres spor og auraer",
"horizon.extras.cosmetics_hide_fx.tooltip": "Andre spilleres spor og auraer forblir skjult; deres andre kosmetikk vises fortsatt. Av som standard.",
"horizon.extras.cosmetics.shown": "Vist",
"horizon.extras.cosmetics.hidden": "Skjult",
"horizon.extras.cosmetics.name_tags": "Kun navnelapper",
@@ -465,8 +465,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Amagat: cada Horizon jogaire vos vei sens vòstres cosmetics, vos tanben. Lo meteis interruptor que l'armari del lançaire.",
"horizon.extras.cosmetics_others": "Los cosmetics dels autres jogaires",
"horizon.extras.cosmetics_others.tooltip": "Çò que pòrtan los autres jogaires Horizon : tot, sonque lors estils de etiqueta de nom, o res. Amagat, lo jòc demanda pas jamai çò que pòrtan.",
"horizon.extras.cosmetics_auras": "Las auras e las pistas dels autres",
"horizon.extras.cosmetics_auras.tooltip": "Auras e pistas que los autres jogaires pòrtan. Desactivat per defaut.",
"horizon.extras.cosmetics_hide_fx": "Amagar las traças e las auras dels autres jogaires",
"horizon.extras.cosmetics_hide_fx.tooltip": "Las traças e las auras dels autres jogaires demòran amagadas; lors autres cosmetics se vesan totjorn. Desactivat per defaut.",
"horizon.extras.cosmetics.shown": "Mostrat",
"horizon.extras.cosmetics.hidden": "Amagat",
"horizon.extras.cosmetics.name_tags": "D'etiquetas de nom solament"
@@ -484,8 +484,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Oculto: todo jogador do Horizon vê você sem seus cosméticos, inclusive você. A mesma opção do guarda-roupa do lançador.",
"horizon.extras.cosmetics_others": "Cosméticos de outros jogadores",
"horizon.extras.cosmetics_others.tooltip": "O que os outros jogadores do Horizon usam: tudo, apenas os estilos dos crachás ou nada. Escondido, o jogo nunca pergunta o que eles vestem.",
"horizon.extras.cosmetics_auras": "Auras e trilhas de outros",
"horizon.extras.cosmetics_auras.tooltip": "Auras e trilhas que outros jogadores usam. Desativado por padrão.",
"horizon.extras.cosmetics_hide_fx": "Ocultar rastros e auras de outros jogadores",
"horizon.extras.cosmetics_hide_fx.tooltip": "Os rastros e auras de outros jogadores ficam ocultos; os demais cosméticos deles continuam visíveis. Desativado por padrão.",
"horizon.extras.cosmetics.shown": "Mostrado",
"horizon.extras.cosmetics.hidden": "Oculto",
"horizon.extras.cosmetics.name_tags": "Somente tags de nome"
@@ -453,8 +453,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Ascuns: fiecare jucător Horizon te vede fără cosmeticele tale, inclusiv tu. Același comutator ca și garderoba lansatorului.",
"horizon.extras.cosmetics_others": "Cosmeticele altor jucători",
"horizon.extras.cosmetics_others.tooltip": "Ce poartă alți jucători de la Horizon: totul, doar stilurile lor de etichete de nume sau nimic. Ascuns, jocul nu le întreabă niciodată ce poartă.",
"horizon.extras.cosmetics_auras": "Aurele și traseele altora",
"horizon.extras.cosmetics_auras.tooltip": "Aurele și traseele pe care le poartă alți jucători. Oprit implicit.",
"horizon.extras.cosmetics_hide_fx": "Ascunde urmele și aurele altor jucători",
"horizon.extras.cosmetics_hide_fx.tooltip": "Urmele și aurele altor jucători rămân ascunse; celelalte cosmetice ale lor se văd în continuare. Dezactivat implicit.",
"horizon.extras.cosmetics.shown": "Afisat",
"horizon.extras.cosmetics.hidden": "Ascuns",
"horizon.extras.cosmetics.name_tags": "Numai etichete de nume",
@@ -491,8 +491,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Кистэлэҥ: хас биирдии Horizon оонньооччу эйигин косметикаҥ суох көрөр, эн эмиэ. Пускатель гардеробун курдук биир переключатель.",
"horizon.extras.cosmetics_others": "Атын оонньооччулар косметикалара",
"horizon.extras.cosmetics_others.tooltip": "Атын Horizon оонньооччулар тугу кэтэллэрий: барытын, ааттарын бэлиэтин стиллэрэ эрэ, эбэтэр туох да суох. Кистэлэҥ, оонньуу хаһан да тугу кэтэллэрин ыйыппат.",
"horizon.extras.cosmetics_auras": "Атыттар ауралара уонна суоллара",
"horizon.extras.cosmetics_auras.tooltip": "Атын оонньооччулар кэтэр ауралара уонна суоллара. По умолчанию выключено.",
"horizon.extras.cosmetics_hide_fx": "Атын оонньооччулар суолларын уонна ааураларын кистээ",
"horizon.extras.cosmetics_hide_fx.tooltip": "Атын оонньооччулар суоллара уонна аауралара кистэлэҥҥэ хаалаллар; кинилэр атын киэргэллэрэ көстөр. Сүрүннээн араарыллыбыт.",
"horizon.extras.cosmetics.shown": "Көрдөрүллүбүт",
"horizon.extras.cosmetics.hidden": "Буккуллубут",
"horizon.extras.cosmetics.name_tags": "Аат бэлиэлэрэ эрэ"
@@ -461,8 +461,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Čuohpaduvvon: juohke Horizon spealli oaidná du kosmetihka haga, maiddái don. Seamma čujuhus go álggaheaddji gárvodanrusttegis.",
"horizon.extras.cosmetics_others": "Eará čiekčiid kosmetihkka",
"horizon.extras.cosmetics_others.tooltip": "Maid eará Horizon-speallit geavahit: visot, dušše sin nammamearkkaid stiillat, dahje ii mihkkege. Čuožžilan, speallu ii goassege jeara maid sii geavahit.",
"horizon.extras.cosmetics_auras": "Earáid aurat ja čuovggat",
"horizon.extras.cosmetics_auras.tooltip": "Aurat ja čuovggat maid eará čiekčit geavahit. Heaittihuvvon standárdan.",
"horizon.extras.cosmetics_hide_fx": "Čiega eará speallariid luottaid ja auraid",
"horizon.extras.cosmetics_hide_fx.tooltip": "Eará speallariid luohtt ja aurat čihkojuvvojit; sin eará čiŋat ain oidnojit. Jáddaduvvon álgoárvun.",
"horizon.extras.cosmetics.shown": "Čájehuvvon",
"horizon.extras.cosmetics.hidden": "Čuohpaduvvon",
"horizon.extras.cosmetics.name_tags": "Dušše nammamearkkat"
@@ -450,8 +450,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skryté: každý hráč Horizon vás vidí bez vašej kozmetiky vrátane vás. Rovnaký vypínač ako šatník odpaľovača.",
"horizon.extras.cosmetics_others": "Kozmetika ostatných hráčov",
"horizon.extras.cosmetics_others.tooltip": "Čo nosia ostatní hráči Horizon: všetko, iba štýly menoviek alebo nič. Skryté, hra sa nikdy nepýta, čo nosia.",
"horizon.extras.cosmetics_auras": "Aury a stopy iných",
"horizon.extras.cosmetics_auras.tooltip": "Aury a chodníky, ktoré nosia ostatní hráči. Predvolene vypnuté.",
"horizon.extras.cosmetics_hide_fx": "Skryť stopy a aury ostatných hráčov",
"horizon.extras.cosmetics_hide_fx.tooltip": "Stopy a aury ostatných hráčov zostanú skryté; ich ostatná kozmetika je stále vidieť. Predvolene vypnuté.",
"horizon.extras.cosmetics.shown": "Zobrazené",
"horizon.extras.cosmetics.hidden": "Skryté",
"horizon.extras.cosmetics.name_tags": "Iba menovky"
@@ -466,8 +466,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skrito: vsak igralec Horizon vas vidi brez vaše kozmetike, vključno z vami. Enako stikalo kot Garderoba zaganjalnika.",
"horizon.extras.cosmetics_others": "Kozmetika drugih igralcev",
"horizon.extras.cosmetics_others.tooltip": "Kaj nosijo drugi igralci Horizon: vse, samo njihove stile imenskih oznak ali nič. Skrita, igra nikoli ne vpraša, kaj nosijo.",
"horizon.extras.cosmetics_auras": "Avre in sledi drugih",
"horizon.extras.cosmetics_auras.tooltip": "Avre in sledi, ki jih nosijo drugi igralci. Privzeto izklopljeno.",
"horizon.extras.cosmetics_hide_fx": "Skrij sledi in avre drugih igralcev",
"horizon.extras.cosmetics_hide_fx.tooltip": "Sledi in avre drugih igralcev ostanejo skrite; njihova druga kozmetika je še vedno vidna. Privzeto izklopljeno.",
"horizon.extras.cosmetics.shown": "Prikazano",
"horizon.extras.cosmetics.hidden": "Skrito",
"horizon.extras.cosmetics.name_tags": "Samo imenske oznake",
@@ -451,8 +451,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Qarsoon: Horizon ciyaaryahan kasta ayaa ku arkaa adiga oo aan la'aanteed waxyaalaha la isku qurxiyo, adiga ayaa ku daray. La mid ah sida Wardrobe-ka furaha.",
"horizon.extras.cosmetics_others": "Isqurxinta ciyaartoyda kale",
"horizon.extras.cosmetics_others.tooltip": "Waxa kale ee Horizon ciyaartoy xidha: wax walba, kaliya magacooda sumadda qaababka, ama waxba. Qarsoon, ciyaartu weligeed ma waydiiso waxay xidhaan.",
"horizon.extras.cosmetics_auras": "Auraska iyo raadadka kuwa kale",
"horizon.extras.cosmetics_auras.tooltip": "Auras iyo raad-raacyo ciyaartoy kale xidhaan. Demin sida caadiga ah.",
"horizon.extras.cosmetics_hide_fx": "Qari raadadka iyo auraha ciyaartoyda kale",
"horizon.extras.cosmetics_hide_fx.tooltip": "Raadadka iyo auraha ciyaartoyda kale way qarsoon yihiin; qurxintooda kale weli way muuqataa. Si caadi ah waa dansan yahay.",
"horizon.extras.cosmetics.shown": "Muujiyay",
"horizon.extras.cosmetics.hidden": "Qarsoon",
"horizon.extras.cosmetics.name_tags": "Magac tags kaliya",
@@ -465,8 +465,8 @@
"horizon.extras.cosmetics_mine.tooltip": "I fshehur: çdo lojtar Horizon ju sheh pa kozmetikën tuaj, përfshirë ju. I njëjti çelës si veshjet e lëshuesit.",
"horizon.extras.cosmetics_others": "Kozmetikë për lojtarë të tjerë",
"horizon.extras.cosmetics_others.tooltip": "Çfarë veshin lojtarët e tjerë Horizon: gjithçka, vetëm stilet e etiketave të emrave të tyre ose asgjë. E fshehur, loja nuk pyet kurrë se çfarë veshin.",
"horizon.extras.cosmetics_auras": "Aurat dhe shtigjet e të tjerëve",
"horizon.extras.cosmetics_auras.tooltip": "Aurat dhe shtigjet që lojtarët e tjerë veshin. Joaktiv si parazgjedhje.",
"horizon.extras.cosmetics_hide_fx": "Fshih gjurmët dhe aurat e lojtarëve të tjerë",
"horizon.extras.cosmetics_hide_fx.tooltip": "Gjurmët dhe aurat e lojtarëve të tjerë mbeten të fshehura; kozmetikat e tjera të tyre shihen ende. Joaktiv si parazgjedhje.",
"horizon.extras.cosmetics.shown": "Treguar",
"horizon.extras.cosmetics.hidden": "I fshehur",
"horizon.extras.cosmetics.name_tags": "Vetëm etiketat e emrave"
@@ -488,8 +488,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skriveno: svaki Horizon igrač vas vidi bez kozmetike, uključujući i vas. Isti prekidač kao Garderoba u pokretaču.",
"horizon.extras.cosmetics_others": "Kozmetika drugih igrača",
"horizon.extras.cosmetics_others.tooltip": "Šta nose drugi Horizon igrači: sve, samo stilove oznaka imena ili ništa. Kada je skriveno, igra nikada ne pita šta nose.",
"horizon.extras.cosmetics_auras": "Aure i tragovi drugih",
"horizon.extras.cosmetics_auras.tooltip": "Aure i staze koje drugi igrači nose. Podrazumevano isključeno.",
"horizon.extras.cosmetics_hide_fx": "Sakrij tragove i aure drugih igrača",
"horizon.extras.cosmetics_hide_fx.tooltip": "Tragovi i aure drugih igrača ostaju skriveni; njihova ostala kozmetika se i dalje vidi. Isključeno po zadanom.",
"horizon.extras.cosmetics.shown": "Pokazano",
"horizon.extras.cosmetics.hidden": "Skriveno",
"horizon.extras.cosmetics.name_tags": "Samo oznake sa imenom"
@@ -488,8 +488,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Скривено: сваки Horizon играч вас види без козметике, укључујући и вас. Исти прекидач као Гардероба у покретачу.",
"horizon.extras.cosmetics_others": "Козметика других играча",
"horizon.extras.cosmetics_others.tooltip": "Шта носе други Horizon играчи: све, само стилове ознака имена или ништа. Када је скривено, игра никада не пита шта носе.",
"horizon.extras.cosmetics_auras": "Ауре и трагови других",
"horizon.extras.cosmetics_auras.tooltip": "Ауре и стазе које други играчи носе. Подразумевано искључено.",
"horizon.extras.cosmetics_hide_fx": "Сакриј трагове и ауре других играча",
"horizon.extras.cosmetics_hide_fx.tooltip": "Трагови и ауре других играча остају сакривени; њихова остала козметика се и даље види. Подразумевано искључено.",
"horizon.extras.cosmetics.shown": "Показано",
"horizon.extras.cosmetics.hidden": "Скривено",
"horizon.extras.cosmetics.name_tags": "Само ознаке са именом"
@@ -450,8 +450,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Dolt: alla Horizon-spelare ser dig utan din kosmetika, inklusive du. Samma switch som bärraketens garderob.",
"horizon.extras.cosmetics_others": "Andra spelares kosmetika",
"horizon.extras.cosmetics_others.tooltip": "Vad andra Horizon-spelare bär: allt, bara deras namnetikettstilar eller ingenting. Dolt, spelet frågar aldrig vad de har på sig.",
"horizon.extras.cosmetics_auras": "Andras auror och spår",
"horizon.extras.cosmetics_auras.tooltip": "Auror och spår som andra spelare bär. Av som standard.",
"horizon.extras.cosmetics_hide_fx": "Dölj andra spelares spår och auror",
"horizon.extras.cosmetics_hide_fx.tooltip": "Andra spelares spår och auror förblir dolda; deras övriga kosmetika syns fortfarande. Av som standard.",
"horizon.extras.cosmetics.shown": "Visas",
"horizon.extras.cosmetics.hidden": "Dold",
"horizon.extras.cosmetics.name_tags": "Endast namnlappar",
@@ -480,8 +480,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Skryte: kożdy grocz Horizon widzi ci bez kosmetyki, w tym ty. Tyn sōm przełōncznik jak Garderoba ôd ôdpalacza.",
"horizon.extras.cosmetics_others": "Kosmetyka ôd inkszych groczy",
"horizon.extras.cosmetics_others.tooltip": "Co inksi grocze Horizon noszōm: wszysko, ino jejich style znakōw, abo nic. Skryte, gra nikej niy pyto, co ôni noszōm.",
"horizon.extras.cosmetics_auras": "Aury i szlaki inkszych",
"horizon.extras.cosmetics_auras.tooltip": "Aury i szlaki noszōm inksi grocze. Wyłōnczōne domyślnie.",
"horizon.extras.cosmetics_hide_fx": "Skryj ślady i aury inszych grŏczy",
"horizon.extras.cosmetics_hide_fx.tooltip": "Ślady i aury inszych grŏczy ôstŏwajōm skryte; jejich inksze kosmetyki sōm dalij widoczne. Wychodnie zastawiōne.",
"horizon.extras.cosmetics.shown": "Pokazano",
"horizon.extras.cosmetics.hidden": "Skryte",
"horizon.extras.cosmetics.name_tags": "Ino znaczniki mian"
@@ -481,8 +481,8 @@
"horizon.extras.cosmetics_mine.tooltip": "மறைக்கப்பட்டவை: ஒவ்வொரு Horizon வீரரும் உங்கள் அழகுசாதனப் பொருட்கள் இல்லாமல் உங்களைப் பார்க்கிறார்கள், நீங்கள் சேர்த்துள்ளீர்கள். லாஞ்சரின் அலமாரியின் அதே சுவிட்ச்.",
"horizon.extras.cosmetics_others": "மற்ற வீரர்களின் அழகுசாதனப் பொருட்கள்",
"horizon.extras.cosmetics_others.tooltip": "மற்ற Horizon வீரர்கள் என்ன அணிவார்கள்: எல்லாம், அவர்களின் பெயர் குறிச்சொல் பாணிகள் அல்லது எதுவும் இல்லை. மறைக்கப்பட்ட, விளையாட்டு அவர்கள் என்ன அணிய வேண்டும் என்று கேட்கவில்லை.",
"horizon.extras.cosmetics_auras": "மற்றவர்களின் ஒளி மற்றும் பாதைகள்",
"horizon.extras.cosmetics_auras.tooltip": "மற்ற வீரர்கள் அணியும் ஆராஸ் மற்றும் டிரெயில்கள். இயல்பாக ஆஃப்.",
"horizon.extras.cosmetics_hide_fx": "மற்ற விளையாட்டாளர்களின் தடங்களையும் ஒளிவட்டங்களையும் மறை",
"horizon.extras.cosmetics_hide_fx.tooltip": "மற்ற விளையாட்டாளர்களின் தடங்களும் ஒளிவட்டங்களும் மறைந்திருக்கும்; அவர்களின் மற்ற அலங்காரங்கள் தெரியும். இயல்பாக அணைக்கப்பட்டுள்ளது.",
"horizon.extras.cosmetics.shown": "காட்டப்பட்டது",
"horizon.extras.cosmetics.hidden": "மறைக்கப்பட்டது",
"horizon.extras.cosmetics.name_tags": "பெயர் குறிச்சொற்கள் மட்டுமே"
@@ -488,8 +488,8 @@
"horizon.extras.cosmetics_mine.tooltip": "ซ่อนเร้น: ผู้เล่น Horizon ทุกคนมองเห็นคุณโดยไม่ได้แต่งหน้า รวมไปถึงคุณด้วย สวิตช์แบบเดียวกับตู้เสื้อผ้าของตัวเรียกใช้งาน",
"horizon.extras.cosmetics_others": "เครื่องสำอางของผู้เล่นคนอื่น",
"horizon.extras.cosmetics_others.tooltip": "ชุดที่ผู้เล่น Horizon คนอื่นๆ ใส่: ทุกอย่าง เฉพาะรูปแบบป้ายชื่อของพวกเขา หรือไม่ใส่เลย ซ่อนเร้นเกมไม่เคยถามว่าพวกเขาสวมอะไร",
"horizon.extras.cosmetics_auras": "ออร่าและเส้นทางของผู้อื่น",
"horizon.extras.cosmetics_auras.tooltip": "ออร่าและเส้นทางที่ผู้เล่นคนอื่นสวมใส่ ปิดโดยค่าเริ่มต้น",
"horizon.extras.cosmetics_hide_fx": "ซ่อนรอยและออร่าของผู้เล่นอื่น",
"horizon.extras.cosmetics_hide_fx.tooltip": "รอยและออร่าของผู้เล่นอื่นจะถูกซ่อน ส่วนไอเทมแต่งตัวอื่นยังมองเห็นได้ ปิดไว้โดยค่าเริ่มต้น",
"horizon.extras.cosmetics.shown": "แสดงแล้ว",
"horizon.extras.cosmetics.hidden": "ซ่อนเร้น",
"horizon.extras.cosmetics.name_tags": "ป้ายชื่อเท่านั้น"
@@ -478,8 +478,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Яшерен: һәр Horizon плейер сезне косметикасыз күрә, сез керттегез. Эшләткечнең гардеробы белән бер үк ачкыч.",
"horizon.extras.cosmetics_others": "Башка уенчыларның косметикасы",
"horizon.extras.cosmetics_others.tooltip": "Башка Horizon уйнаучылар нәрсә киеп йөриләр: барысы да, аларның исеме теге стильләре, яки бернәрсә дә. Яшерен, уен беркайчан да нәрсә кигәннәрен сорамый.",
"horizon.extras.cosmetics_auras": "Башкаларның ауралары һәм юллары",
"horizon.extras.cosmetics_auras.tooltip": "Ауралар һәм башка уенчылар кигән эзләр. Килешү буенча сүндерелгән.",
"horizon.extras.cosmetics_hide_fx": "Башка уенчыларның эзләрен һәм аураларын яшерү",
"horizon.extras.cosmetics_hide_fx.tooltip": "Башка уенчыларның эзләре һәм ауралары яшерен кала; аларның башка косметикасы күренә. Гадәттә сүндерелгән.",
"horizon.extras.cosmetics.shown": "Күрсәтелә",
"horizon.extras.cosmetics.hidden": "Яшерен",
"horizon.extras.cosmetics.name_tags": "Тэгларның исеме генә"
@@ -463,8 +463,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Yashirin: har bir Horizon o'yinchi sizni kosmetikangizsiz ko'radi, shu jumladan. Launcherning shkafi bilan bir xil kalit.",
"horizon.extras.cosmetics_others": "Boshqa o'yinchilarning kosmetikasi",
"horizon.extras.cosmetics_others.tooltip": "Boshqa Horizon o'yinchilar nima kiyishadi: hamma narsa, faqat ism yorlig'i uslublari yoki hech narsa. Yashirin, o'yin hech qachon ular nima kiyishlarini so'ramaydi.",
"horizon.extras.cosmetics_auras": "Boshqalarning auralari va izlari",
"horizon.extras.cosmetics_auras.tooltip": "Boshqa o'yinchilar kiygan auralar va izlar. Sukut boʻyicha oʻchirilgan.",
"horizon.extras.cosmetics_hide_fx": "Boshqa o‘yinchilarning izlari va auralarini yashirish",
"horizon.extras.cosmetics_hide_fx.tooltip": "Boshqa o‘yinchilarning izlari va auralari yashirin qoladi; ularning boshqa kosmetikasi ko‘rinib turadi. Standart bo‘yicha o‘chiq.",
"horizon.extras.cosmetics.shown": "Ko'rsatilgan",
"horizon.extras.cosmetics.hidden": "Yashirin",
"horizon.extras.cosmetics.name_tags": "Faqat nom teglari"
@@ -464,8 +464,8 @@
"horizon.extras.cosmetics_mine.tooltip": "Nascosto: ogni Horizon giocatore ti vede senza i tuoi cosmetici, tu compreso. Lo stesso interruttore del Armadio del lanciatore.",
"horizon.extras.cosmetics_others": "Cosmetici dei altri zogadori",
"horizon.extras.cosmetics_others.tooltip": "Cossa che i altri zugadori de Horizon i ga indosso: tuto, soło i so stiłi de name tag, o gnente. Nascosto, el zogo no ghe dimanda mai cossa che i porta.",
"horizon.extras.cosmetics_auras": "Aure e sentieri dei altri",
"horizon.extras.cosmetics_auras.tooltip": "Aure e sentieri che altri zugadori i ga. Spento par indebołimento.",
"horizon.extras.cosmetics_hide_fx": "Scondi i trasi e łe aure de i altri zugadori",
"horizon.extras.cosmetics_hide_fx.tooltip": "I trasi e łe aure de i altri zugadori i resta sconti; i so altri cosmetici i se vede ancora. Destudà par defolt.",
"horizon.extras.cosmetics.shown": "Mostrà",
"horizon.extras.cosmetics.hidden": "Sconto",
"horizon.extras.cosmetics.name_tags": "Solo etichete de nome",
Loaded 100 of 359 files, more files were not shown because too many files have changed in this diff. Show more