mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge origin/main into fix/7067-minecart-world-border
This commit is contained in:
commit
a5cdf9fd53
40 files changed
+794
-320
No files matched your search
@@ -51,6 +51,7 @@ pub struct SkinJob {
|
||||
pub overlay: u32,
|
||||
/// 1 when the overlay is the armour glint: the model UV rides in `glint_uv`.
|
||||
pub glint: u32,
|
||||
/// Always 0: the shader reads the last as a zero it cannot fold away.
|
||||
pub spare: [u32; 3],
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@ const MODEL_WORDS: u32 = 7u;
|
||||
const PART_WORDS: u32 = 25u;
|
||||
// A job (16 words): first model vertex, vertex count, first part, first output
|
||||
// vertex, the texture rect (4 floats), scroll, colour, light, overlay,
|
||||
// whether the overlay is the armour glint (its model UV in `glint_uv`), 3 spare.
|
||||
// whether the overlay is the armour glint (its model UV in `glint_uv`), 3 spare
|
||||
// (0: the last one is `keep`'s).
|
||||
const JOB_WORDS: u32 = 16u;
|
||||
// `mesher::Vertex` (11 words): pos (3), uv (2), layer, color, light, normal
|
||||
// (4 x i8), glint_uv (2).
|
||||
@@ -30,6 +31,20 @@ fn f(words: u32) -> f32 {
|
||||
return bitcast<f32>(words);
|
||||
}
|
||||
|
||||
// A zero the compiler cannot see (the job's last word). Metal compiles shaders
|
||||
// with fast math: it would fuse `a * b + c` into one rounding and reorder sums,
|
||||
// a bit off the CPU's separate operations. A value xored with `keep` is opaque
|
||||
// to it, so each operation below rounds on its own, in the CPU's order.
|
||||
var<private> keep: u32;
|
||||
|
||||
fn r(v: f32) -> f32 {
|
||||
return bitcast<f32>(bitcast<u32>(v) ^ keep);
|
||||
}
|
||||
|
||||
fn r3(v: vec3<f32>) -> vec3<f32> {
|
||||
return bitcast<vec3<f32>>(bitcast<vec3<u32>>(v) ^ vec3(keep));
|
||||
}
|
||||
|
||||
fn part_f(part: u32, i: u32) -> f32 {
|
||||
return f(parts[part * PART_WORDS + i]);
|
||||
}
|
||||
@@ -40,8 +55,8 @@ fn scroll_u(u: f32, scroll: f32) -> f32 {
|
||||
return u;
|
||||
}
|
||||
// Rust's `%` on floats: the remainder with the dividend's sign.
|
||||
let s = u + scroll;
|
||||
return s - trunc(s);
|
||||
let s = r(u + scroll);
|
||||
return r(s - r(trunc(s)));
|
||||
}
|
||||
|
||||
// `Polygon::vertex_normal`'s packing: clamped, times 127, cut toward zero.
|
||||
@@ -72,17 +87,18 @@ fn skin(
|
||||
let light = jobs[j + 10u];
|
||||
let overlay = jobs[j + 11u];
|
||||
let glint = jobs[j + 12u] != 0u;
|
||||
keep = jobs[j + 15u];
|
||||
for (var k = lane; k < count; k += 64u) {
|
||||
let v = (first + k) * MODEL_WORDS;
|
||||
let p = vec3(f(model[v]), f(model[v + 1u]), f(model[v + 2u]));
|
||||
let uv = vec2(f(model[v + 3u]), f(model[v + 4u]));
|
||||
let axis = model[v + 5u];
|
||||
let part = first_part + model[v + 6u];
|
||||
// glam's Mat4::transform_point3, in its order.
|
||||
var pos = vec3(part_f(part, 0u), part_f(part, 1u), part_f(part, 2u)) * p.x;
|
||||
pos = vec3(part_f(part, 4u), part_f(part, 5u), part_f(part, 6u)) * p.y + pos;
|
||||
pos = vec3(part_f(part, 8u), part_f(part, 9u), part_f(part, 10u)) * p.z + pos;
|
||||
pos = vec3(part_f(part, 12u), part_f(part, 13u), part_f(part, 14u)) + pos;
|
||||
// glam's Mat4::transform_point3, in its order, each operation rounded.
|
||||
var pos = r3(vec3(part_f(part, 0u), part_f(part, 1u), part_f(part, 2u)) * p.x);
|
||||
pos = r3(r3(vec3(part_f(part, 4u), part_f(part, 5u), part_f(part, 6u)) * p.y) + pos);
|
||||
pos = r3(r3(vec3(part_f(part, 8u), part_f(part, 9u), part_f(part, 10u)) * p.z) + pos);
|
||||
pos = r3(vec3(part_f(part, 12u), part_f(part, 13u), part_f(part, 14u)) + pos);
|
||||
// An axis normal times the normal matrix is that column, exactly.
|
||||
let c = 16u + (axis % 3u) * 3u;
|
||||
var n = vec3(part_f(part, c), part_f(part, c + 1u), part_f(part, c + 2u));
|
||||
@@ -93,8 +109,8 @@ fn skin(
|
||||
out[o] = bitcast<u32>(pos.x);
|
||||
out[o + 1u] = bitcast<u32>(pos.y);
|
||||
out[o + 2u] = bitcast<u32>(pos.z);
|
||||
out[o + 3u] = bitcast<u32>(rect.x + (rect.z - rect.x) * scroll_u(uv.x, scroll));
|
||||
out[o + 4u] = bitcast<u32>(rect.y + (rect.w - rect.y) * uv.y);
|
||||
out[o + 3u] = bitcast<u32>(rect.x + r(r(rect.z - rect.x) * scroll_u(uv.x, scroll)));
|
||||
out[o + 4u] = bitcast<u32>(rect.y + r(r(rect.w - rect.y) * uv.y));
|
||||
out[o + 5u] = overlay;
|
||||
out[o + 6u] = color;
|
||||
out[o + 7u] = light;
|
||||
|
||||
@@ -533,7 +533,62 @@ fn galactic_widths(
|
||||
}
|
||||
widths
|
||||
}
|
||||
/// `TextureAtlas.dumpContents` (`F3 + S`, vanilla's "dynamic textures"): the atlas
|
||||
/// written as `name.png` beside `name.txt`, every sprite in name order with its
|
||||
/// rect in texels (`dumpSpriteNames`). Vanilla names each file after its atlas
|
||||
/// with `/` and `:` as `_` (`Identifier.toDebugFileName`); Horizon packs the GUI,
|
||||
/// font, particle, map and skin sprites into one atlas, so one file stands in for
|
||||
/// the atlases vanilla dumps apart.
|
||||
pub fn dump_atlas(
|
||||
dir: &Path,
|
||||
name: &str,
|
||||
width: u32,
|
||||
height: u32,
|
||||
pixels: &[u8],
|
||||
sprites: &HashMap<String, Rect>,
|
||||
) -> std::io::Result<PathBuf> {
|
||||
// A build whose pixels were freed (`fonts`) has the size and no texels:
|
||||
// write nothing rather than a file every reader would reject.
|
||||
if pixels.len() != (width as usize) * (height as usize) * 4 {
|
||||
return Err(std::io::Error::other(format!(
|
||||
"wrong data size, expected {} got {}",
|
||||
(width as usize) * (height as usize) * 4,
|
||||
pixels.len()
|
||||
)));
|
||||
}
|
||||
fs::create_dir_all(dir)?;
|
||||
let png_path = dir.join(format!("{name}.png"));
|
||||
let mut encoder = png::Encoder::new(fs::File::create(&png_path)?, width, height);
|
||||
encoder.set_color(png::ColorType::Rgba);
|
||||
encoder.set_depth(png::BitDepth::Eight);
|
||||
let mut writer = encoder.write_header().map_err(std::io::Error::other)?;
|
||||
writer
|
||||
.write_image_data(pixels)
|
||||
.map_err(std::io::Error::other)?;
|
||||
drop(writer);
|
||||
let mut names = sprites.iter().collect::<Vec<_>>();
|
||||
names.sort_by(|a, b| a.0.cmp(b.0));
|
||||
let mut list = String::new();
|
||||
for (sprite, rect) in names {
|
||||
let (w, h) = rect.texels((width, height));
|
||||
let x = (rect.u0 * width as f32).round() as u32;
|
||||
let y = (rect.v0 * height as f32).round() as u32;
|
||||
list.push_str(&format!("{sprite}\tx={x}\ty={y}\tw={w}\th={h}\n"));
|
||||
}
|
||||
fs::write(dir.join(format!("{name}.txt")), list)?;
|
||||
Ok(png_path)
|
||||
}
|
||||
|
||||
impl HudAtlas {
|
||||
/// `TextureAtlas.dumpContents` for this atlas: `dir` is `screenshots/debug`,
|
||||
/// the folder `TextureUtil.getDebugTexturePath` names.
|
||||
pub fn dump_contents(&self, dir: &Path, name: &str) -> std::io::Result<PathBuf> {
|
||||
// `pixels()`: the copy `pack_pixels` compressed once the GPU had the
|
||||
// atlas, decompressed; vanilla reads the texture back from the GPU.
|
||||
let pixels = self.pixels();
|
||||
dump_atlas(dir, name, self.width, self.height, &pixels, &self.sprites)
|
||||
}
|
||||
|
||||
fn next_revision() -> u64 {
|
||||
static NEXT: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
|
||||
NEXT.fetch_add(1, std::sync::atomic::Ordering::Relaxed)
|
||||
@@ -2567,6 +2622,51 @@ impl HudRenderer {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn dumping_the_atlas_writes_its_pixels_and_sprite_rects() {
|
||||
let root = std::env::temp_dir().join("horizon-atlas-dump-test");
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
let pixels: Vec<u8> = (0..4u8).flat_map(|i| [i, 0, 0, 255]).collect();
|
||||
let rect = |u0: f32, v0: f32| Rect {
|
||||
u0,
|
||||
v0,
|
||||
u1: u0 + 0.5,
|
||||
v1: v0 + 0.5,
|
||||
w: 8,
|
||||
h: 8,
|
||||
};
|
||||
let sprites = HashMap::from([
|
||||
("particle/smoke".to_string(), rect(0.5, 0.0)),
|
||||
("gui/sprites/bars/experience".to_string(), rect(0.0, 0.5)),
|
||||
]);
|
||||
let path = dump_atlas(
|
||||
&root,
|
||||
"minecraft_textures_atlas_gui",
|
||||
2,
|
||||
2,
|
||||
&pixels,
|
||||
&sprites,
|
||||
)
|
||||
.expect("the dump writes");
|
||||
assert_eq!(path, root.join("minecraft_textures_atlas_gui.png"));
|
||||
let written = fs::read(&path).expect("the PNG is there");
|
||||
let (width, height, rgba) = decode_bytes(&written).expect("the PNG decodes");
|
||||
assert_eq!((width, height), (2, 2));
|
||||
assert_eq!(rgba, pixels);
|
||||
// Sorted by sprite name, rects in texels, as `dumpSpriteNames` writes them.
|
||||
let mut expected = String::from("gui/sprites/bars/experience\tx=0\ty=1\tw=1\th=1\n");
|
||||
expected.push_str("particle/smoke\tx=1\ty=0\tw=1\th=1\n");
|
||||
assert_eq!(
|
||||
fs::read_to_string(root.join("minecraft_textures_atlas_gui.txt")).unwrap(),
|
||||
expected
|
||||
);
|
||||
// A build with no texels in hand writes no file at all.
|
||||
let empty = dump_atlas(&root, "empty", 2, 2, &[], &sprites);
|
||||
assert!(empty.is_err());
|
||||
assert!(!root.join("empty.png").exists());
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decode_bytes_ignores_crc_checksum_error() {
|
||||
let mut encoded = Vec::new();
|
||||
|
||||
@@ -6915,7 +6915,7 @@ impl Game<'_> {
|
||||
let canceled = !hand_changed && !self.use_item_stopped(stack, ticks);
|
||||
let (release, spyglass) = item_use::release_parts(canceled, hand_changed);
|
||||
match &*stack.item {
|
||||
"minecraft:bow" if release => self.release_bow(self.ticks_held(stack, ticks)),
|
||||
"minecraft:bow" if release => self.release_bow(stack, self.ticks_held(stack, ticks)),
|
||||
"minecraft:trident" if release => self.release_trident(self.ticks_held(stack, ticks)),
|
||||
"minecraft:spyglass" if spyglass => self.stop_spyglass(),
|
||||
_ => {}
|
||||
@@ -12133,6 +12133,16 @@ impl Game<'_> {
|
||||
}
|
||||
}
|
||||
}
|
||||
// IntegratedServer.initServer's line, which other launchers read in `latest.log` to
|
||||
// offer the world again; single player starts here with or without a server thread.
|
||||
horizon_client::logging::write_as(
|
||||
"Server thread",
|
||||
log::Level::Info,
|
||||
&format!(
|
||||
"Starting integrated minecraft server version {}",
|
||||
horizon_core::VANILLA_VERSION
|
||||
),
|
||||
);
|
||||
if self
|
||||
.options
|
||||
.execution_role
|
||||
@@ -13895,16 +13905,15 @@ impl Game<'_> {
|
||||
}
|
||||
}
|
||||
/// BowItem.releaseUsing: power from charge time, arrows at power * 3.
|
||||
fn release_bow(&mut self, ticks: u32) {
|
||||
let f = ticks as f32 / 20.0;
|
||||
let power = ((f * f + f * 2.0) / 3.0).min(1.0);
|
||||
if power < 0.1 {
|
||||
return;
|
||||
}
|
||||
fn release_bow(&mut self, stack: &ItemStack, ticks: u32) {
|
||||
let arrow_slot = self.projectile_slot("minecraft:bow");
|
||||
if arrow_slot.is_none() && !self.creative {
|
||||
let has_ammo = arrow_slot.is_some() || self.creative;
|
||||
let mut charge = i32::try_from(ticks).unwrap_or(i32::MAX);
|
||||
let mut canceled = false;
|
||||
self.native_arrow_loose(stack, has_ammo, &mut charge, &mut canceled);
|
||||
let Some(power) = item_use::bow_release_power(has_ammo, charge, canceled) else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
let Some(eye) = self.eye_position() else {
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -197,20 +197,105 @@ struct ResourceIds {
|
||||
damage_types: Vec<String>,
|
||||
loot_tables: Vec<String>,
|
||||
templates: Vec<String>,
|
||||
/// `entity-types.json`'s keys, sorted (empty when the file is missing).
|
||||
entity_types: Vec<String>,
|
||||
enchantments: Vec<String>,
|
||||
structures: Vec<String>,
|
||||
biomes: Vec<String>,
|
||||
clocks: Vec<String>,
|
||||
/// The overworld clock's timelines, their periods and time markers.
|
||||
timelines: Vec<(String, Option<i64>)>,
|
||||
markers: Vec<(String, TimeMarker)>,
|
||||
}
|
||||
static RESOURCE_IDS: Mutex<Vec<(PathBuf, Arc<ResourceIds>)>> = Mutex::new(Vec::new());
|
||||
|
||||
/// The `minecraft:` ids of the `.json` files directly in `dir`, sorted.
|
||||
fn json_ids_in(dir: &Path) -> Vec<String> {
|
||||
let mut out: Vec<String> = std::fs::read_dir(dir)
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.filter_map(|e| {
|
||||
e.file_name()
|
||||
.to_str()?
|
||||
.strip_suffix(".json")
|
||||
.map(|n| format!("minecraft:{n}"))
|
||||
})
|
||||
.collect();
|
||||
out.sort();
|
||||
out
|
||||
}
|
||||
|
||||
/// The overworld clock's timelines (with their periods) and their time
|
||||
/// markers, read from `data/minecraft/timeline`.
|
||||
fn overworld_timelines(root: &Path) -> (Vec<(String, Option<i64>)>, Vec<(String, TimeMarker)>) {
|
||||
let dir = root.join("data/minecraft/timeline");
|
||||
let (mut timelines, mut markers) = (Vec::new(), Vec::new());
|
||||
for name in json_ids_in(&dir) {
|
||||
let path = dir.join(format!("{}.json", name.trim_start_matches("minecraft:")));
|
||||
let Ok(v) =
|
||||
serde_json::from_slice::<serde_json::Value>(&std::fs::read(path).unwrap_or_default())
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if v["clock"].as_str() != Some("minecraft:overworld") {
|
||||
continue;
|
||||
}
|
||||
let period = v["period_ticks"].as_i64();
|
||||
timelines.push((name.clone(), period));
|
||||
for (marker, def) in v["time_markers"].as_object().into_iter().flatten() {
|
||||
let (ticks, show) = match def {
|
||||
serde_json::Value::Number(n) => (n.as_i64().unwrap_or(0), false),
|
||||
other => (
|
||||
other["ticks"].as_i64().unwrap_or(0),
|
||||
other["show_in_commands"].as_bool().unwrap_or(false),
|
||||
),
|
||||
};
|
||||
markers.push((
|
||||
marker.clone(),
|
||||
TimeMarker {
|
||||
ticks,
|
||||
period,
|
||||
show,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
(timelines, markers)
|
||||
}
|
||||
|
||||
fn resource_ids(root: &Path) -> Arc<ResourceIds> {
|
||||
let mut cache = RESOURCE_IDS.lock().unwrap_or_else(|e| e.into_inner());
|
||||
if let Some((_, ids)) = cache.iter().find(|(cached, _)| cached == root) {
|
||||
return ids.clone();
|
||||
}
|
||||
let data = root.join("data/minecraft");
|
||||
let mut entity_types: Vec<String> = serde_json::from_slice::<serde_json::Value>(
|
||||
&std::fs::read(root.join("entity-types.json")).unwrap_or_default(),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|v| {
|
||||
v.as_object().map(|o| {
|
||||
o.keys()
|
||||
.map(|k| horizon_client::command::args::normalize(k))
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
entity_types.sort();
|
||||
let (timelines, markers) = overworld_timelines(root);
|
||||
let ids = Arc::new(ResourceIds {
|
||||
recipes: ids_under(&data.join("recipe"), "json"),
|
||||
damage_types: ids_under(&data.join("damage_type"), "json"),
|
||||
loot_tables: ids_under(&data.join("loot_table"), "json"),
|
||||
templates: templates_under(&root.join("worldgen/structure")),
|
||||
entity_types,
|
||||
enchantments: json_ids_in(&data.join("enchantment")),
|
||||
structures: json_ids_in(&data.join("worldgen/structure")),
|
||||
biomes: json_ids_in(&data.join("worldgen/biome")),
|
||||
clocks: json_ids_in(&data.join("world_clock")),
|
||||
timelines,
|
||||
markers,
|
||||
});
|
||||
cache.push((root.to_owned(), ids.clone()));
|
||||
ids
|
||||
@@ -326,10 +411,11 @@ fn ids_in(root: &Path, extension: &str, namespace: &str) -> Vec<String> {
|
||||
}
|
||||
|
||||
impl Game<'_> {
|
||||
/// The caches `build_registries` reads (`resource_ids`, `block_properties`,
|
||||
/// `command_export`), filled on a helper thread while the title screen is up: the
|
||||
/// first world opened or server joined built them in its frame (20 ms of the Join
|
||||
/// click on an M4 Pro). Whoever needs one before it is done waits for it, as before.
|
||||
/// The caches `build_registries` and `join_server` read (`resource_ids`,
|
||||
/// `block_properties`, `command_export`, `builtin_registries`), filled on a helper
|
||||
/// thread while the title screen is up: the first world opened or server joined
|
||||
/// built them in its frame (20 ms of the Join click on an M4 Pro). Whoever needs one
|
||||
/// before it is done waits for it, as before.
|
||||
pub(super) fn preload_registries(&self) {
|
||||
if self.options.dedicated.is_some() {
|
||||
return;
|
||||
@@ -340,6 +426,7 @@ impl Game<'_> {
|
||||
.name("Registries preload".into())
|
||||
.spawn(move || {
|
||||
horizon_threads::behind_server();
|
||||
super::remote::builtin_registries(&dirs[0]);
|
||||
resource_ids(&dirs[0]);
|
||||
block_properties(registry);
|
||||
for dir in &dirs {
|
||||
@@ -472,50 +559,23 @@ impl Game<'_> {
|
||||
summonable.sort();
|
||||
summonable.dedup();
|
||||
reg.summonable = summonable;
|
||||
let root = self.options.resources.clone();
|
||||
let mut types: Vec<String> = serde_json::from_slice::<serde_json::Value>(
|
||||
&std::fs::read(root.join("entity-types.json")).unwrap_or_default(),
|
||||
)
|
||||
.ok()
|
||||
.and_then(|v| {
|
||||
v.as_object().map(|o| {
|
||||
o.keys()
|
||||
.map(|k| horizon_client::command::args::normalize(k))
|
||||
.collect()
|
||||
})
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let mut types = ids.entity_types.clone();
|
||||
if types.is_empty() {
|
||||
types = reg.summonable.clone();
|
||||
types.push("minecraft:player".into());
|
||||
types.sort();
|
||||
}
|
||||
types.sort();
|
||||
reg.entity_types = types;
|
||||
let list = |dir: &str| -> Vec<String> {
|
||||
let mut out: Vec<String> = std::fs::read_dir(root.join(dir))
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.filter_map(|e| {
|
||||
e.file_name()
|
||||
.to_str()?
|
||||
.strip_suffix(".json")
|
||||
.map(|n| format!("minecraft:{n}"))
|
||||
})
|
||||
.collect();
|
||||
out.sort();
|
||||
out
|
||||
};
|
||||
// The mob effect registry: every effect `/effect` and the
|
||||
// `mob_effect` resource arguments accept.
|
||||
reg.effects = horizon_client::brewing::all_effects()
|
||||
.map(|e| horizon_client::brewing::namespaced(e.id).to_owned())
|
||||
.collect();
|
||||
reg.effects.sort();
|
||||
reg.enchantments = list("data/minecraft/enchantment");
|
||||
reg.structures = list("data/minecraft/worldgen/structure");
|
||||
reg.biomes = list("data/minecraft/worldgen/biome");
|
||||
reg.clocks = list("data/minecraft/world_clock");
|
||||
reg.enchantments = ids.enchantments.clone();
|
||||
reg.structures = ids.structures.clone();
|
||||
reg.biomes = ids.biomes.clone();
|
||||
reg.clocks = ids.clocks.clone();
|
||||
reg.dimensions = vec![
|
||||
"minecraft:overworld".into(),
|
||||
"minecraft:the_nether".into(),
|
||||
@@ -523,41 +583,8 @@ impl Game<'_> {
|
||||
];
|
||||
reg.players = vec![PLAYER_NAME.into()];
|
||||
// Timelines of the overworld clock and their time markers.
|
||||
self.ui.markers.clear();
|
||||
self.ui.timelines.clear();
|
||||
for name in list("data/minecraft/timeline") {
|
||||
let path = root.join(format!(
|
||||
"data/minecraft/timeline/{}.json",
|
||||
name.trim_start_matches("minecraft:")
|
||||
));
|
||||
let Ok(v) = serde_json::from_slice::<serde_json::Value>(
|
||||
&std::fs::read(path).unwrap_or_default(),
|
||||
) else {
|
||||
continue;
|
||||
};
|
||||
if v["clock"].as_str() != Some("minecraft:overworld") {
|
||||
continue;
|
||||
}
|
||||
let period = v["period_ticks"].as_i64();
|
||||
self.ui.timelines.insert(name.clone(), period);
|
||||
for (marker, def) in v["time_markers"].as_object().into_iter().flatten() {
|
||||
let (ticks, show) = match def {
|
||||
serde_json::Value::Number(n) => (n.as_i64().unwrap_or(0), false),
|
||||
other => (
|
||||
other["ticks"].as_i64().unwrap_or(0),
|
||||
other["show_in_commands"].as_bool().unwrap_or(false),
|
||||
),
|
||||
};
|
||||
self.ui.markers.insert(
|
||||
marker.clone(),
|
||||
TimeMarker {
|
||||
ticks,
|
||||
period,
|
||||
show,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
self.ui.timelines = ids.timelines.iter().cloned().collect();
|
||||
self.ui.markers = ids.markers.iter().cloned().collect();
|
||||
// Vanilla's built-in registries (mob effects, components, dialogs...).
|
||||
for dir in [&self.options.resources, &self.ui.vanilla_root] {
|
||||
if let Some(export) = command_export(dir, self.options.dedicated.is_none()) {
|
||||
@@ -1580,6 +1607,43 @@ mod tests {
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
/// Only the overworld clock's timelines count; a marker is a bare tick
|
||||
/// count (hidden from commands) or an object that may show itself.
|
||||
#[test]
|
||||
fn overworld_timelines_and_markers() {
|
||||
let root = std::env::temp_dir().join(format!("horizon-timelines-{}", std::process::id()));
|
||||
let dir = root.join("data/minecraft/timeline");
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
std::fs::write(
|
||||
dir.join("day.json"),
|
||||
r#"{"clock":"minecraft:overworld","period_ticks":24000,
|
||||
"time_markers":{"minecraft:noon":6000,
|
||||
"minecraft:night":{"ticks":13000,"show_in_commands":true}}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(
|
||||
dir.join("other.json"),
|
||||
r#"{"clock":"minecraft:the_end","time_markers":{"minecraft:x":1}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::write(dir.join("broken.json"), "{").unwrap();
|
||||
let (timelines, markers) = overworld_timelines(&root);
|
||||
assert_eq!(timelines, [("minecraft:day".to_owned(), Some(24000))]);
|
||||
let mut markers: Vec<_> = markers
|
||||
.iter()
|
||||
.map(|(name, m)| (name.as_str(), m.ticks, m.period, m.show))
|
||||
.collect();
|
||||
markers.sort();
|
||||
assert_eq!(
|
||||
markers,
|
||||
[
|
||||
("minecraft:night", 13000, Some(24000), true),
|
||||
("minecraft:noon", 6000, Some(24000), false),
|
||||
]
|
||||
);
|
||||
let _ = std::fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
/// The export is read once per folder; a folder without one stays without.
|
||||
#[test]
|
||||
fn command_exports_are_read_once_per_folder() {
|
||||
|
||||
@@ -10,7 +10,7 @@ use horizon_client::{
|
||||
gizmos::Gizmos,
|
||||
hud::HudBatch,
|
||||
hud_layout, keybinds,
|
||||
text::Text,
|
||||
text::{ClickEvent, Style, Text},
|
||||
};
|
||||
use horizon_core::geometry::{Axis, Vec3};
|
||||
use horizon_protocol::packets::play::{BlockEntityTagQuery, EntityTagQuery, Serverbound};
|
||||
@@ -722,11 +722,42 @@ impl Game<'_> {
|
||||
self.export_repro_key();
|
||||
true
|
||||
}
|
||||
DebugAction::DumpDynamicTextures => {
|
||||
// `KeyboardHandler`: `TextureUtil.getDebugTexturePath` is the game
|
||||
// folder's `screenshots/debug`; `TextureManager.dumpAllSheets` then
|
||||
// writes every dumpable texture there and the chat names the folder.
|
||||
let dir = horizon_client::logging::player_dir()
|
||||
.join("screenshots")
|
||||
.join("debug");
|
||||
match self
|
||||
.gui
|
||||
.atlas
|
||||
.dump_contents(&dir, "minecraft_textures_atlas_gui")
|
||||
{
|
||||
Ok(_) => {
|
||||
log::info!("Dumped dynamic textures to {}", dir.display());
|
||||
let link = Text::styled(
|
||||
"screenshots/debug",
|
||||
Style {
|
||||
underlined: Some(true),
|
||||
click: Some(ClickEvent::OpenFile(
|
||||
dir.to_string_lossy().into_owned(),
|
||||
)),
|
||||
..Style::default()
|
||||
},
|
||||
);
|
||||
self.debug_feedback(Text::translate(
|
||||
"debug.dump_dynamic_textures",
|
||||
&[link],
|
||||
));
|
||||
}
|
||||
Err(e) => log::error!("Failed to dump dynamic textures: {e}"),
|
||||
}
|
||||
true
|
||||
}
|
||||
// Screens and overlays Horizon does not draw yet (the profiler and
|
||||
// its chart, the texture dump): the keys are used up as in vanilla.
|
||||
DebugAction::DumpDynamicTextures
|
||||
| DebugAction::Profiling
|
||||
| DebugAction::ProfilingChart => true,
|
||||
// its chart): the keys are used up as in vanilla.
|
||||
DebugAction::Profiling | DebugAction::ProfilingChart => true,
|
||||
DebugAction::ShowHitboxes
|
||||
| DebugAction::ShowChunkBorders
|
||||
| DebugAction::SwitchGameMode
|
||||
|
||||
@@ -204,6 +204,15 @@ pub(super) fn release_parts(canceled: bool, hand_changed: bool) -> (bool, bool)
|
||||
(!canceled && !hand_changed, !canceled)
|
||||
}
|
||||
|
||||
pub(super) fn bow_release_power(has_ammo: bool, charge: i32, canceled: bool) -> Option<f32> {
|
||||
if canceled || charge < 0 || !has_ammo {
|
||||
return None;
|
||||
}
|
||||
let f = charge as f32 / 20.0;
|
||||
let power = ((f * f + f * 2.0) / 3.0).min(1.0);
|
||||
(power >= 0.1).then_some(power)
|
||||
}
|
||||
|
||||
/// `useItemRemaining` of a use of `duration` ticks, `ticks` old.
|
||||
fn ticks_left(duration: i32, ticks: u32) -> i32 {
|
||||
duration.saturating_sub_unsigned(ticks)
|
||||
@@ -272,8 +281,8 @@ pub(super) fn use_pose(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{
|
||||
consumes_at_once, count_down, duration_leaving, held, release_parts, start_of, tick_left,
|
||||
ticks_left, use_pose,
|
||||
bow_release_power, consumes_at_once, count_down, duration_leaving, held, release_parts,
|
||||
start_of, tick_left, ticks_left, use_pose,
|
||||
};
|
||||
use horizon_client::first_person::ItemPose;
|
||||
use horizon_world::consumable::UseAnimation;
|
||||
@@ -367,6 +376,16 @@ mod tests {
|
||||
assert_eq!(release_parts(false, true), (false, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bow_release_respects_charge_cancel_and_ammo() {
|
||||
assert_eq!(bow_release_power(true, 20, false), Some(1.0));
|
||||
assert_eq!(bow_release_power(true, 10, false), Some(5.0 / 12.0));
|
||||
assert_eq!(bow_release_power(true, 0, false), None);
|
||||
assert_eq!(bow_release_power(true, -1, false), None);
|
||||
assert_eq!(bow_release_power(true, 20, true), None);
|
||||
assert_eq!(bow_release_power(false, 20, false), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_moved_end_moves_the_charge() {
|
||||
// a bow held 10 ticks of 72000: 10, as vanilla's.
|
||||
|
||||
@@ -5065,6 +5065,23 @@ impl Game<'_> {
|
||||
canceled,
|
||||
);
|
||||
}
|
||||
/// NeoForge's `ArrowLooseEvent`: the player releases a bow `stack` with
|
||||
/// `has_ammo` and `charge` ticks held. Change `charge` or set `canceled`
|
||||
/// to prevent the shot; negative charge also prevents it. Unlike
|
||||
/// `native_living_entity_use_item_stop`, this does not skip the whole item
|
||||
/// release; `native_entity_shoot_bow` reports a spawned arrow afterward
|
||||
/// with read-only force. Fires on the Game running the bow release, including
|
||||
/// LAN guests; a remote client's own release path is not covered. Crossbows
|
||||
/// and `ArrowNockEvent` are not covered. @API:arrow_loose@.
|
||||
pub(super) fn native_arrow_loose(
|
||||
&mut self,
|
||||
stack: &ItemStack,
|
||||
has_ammo: bool,
|
||||
charge: &mut i32,
|
||||
canceled: &mut bool,
|
||||
) {
|
||||
mod_api::dispatch_arrow_loose(self, mod_api::mods(), stack, has_ammo, charge, canceled);
|
||||
}
|
||||
/// NeoForge's `CriticalHitEvent`: a player's melee hit on a living
|
||||
/// `target_kind` (`minecraft:zombie`, `minecraft:armor_stand`) that deals
|
||||
/// damage, where `Player.attack` decides whether it is critical.
|
||||
|
||||
@@ -54,6 +54,24 @@ use std::{
|
||||
};
|
||||
use winit::{event::MouseButton, keyboard::KeyCode};
|
||||
|
||||
type BuiltinCache = Vec<(std::path::PathBuf, Arc<Builtin>)>;
|
||||
static BUILTIN: std::sync::Mutex<BuiltinCache> = std::sync::Mutex::new(Vec::new());
|
||||
|
||||
/// The prepared resources' `registries.json`, parsed once per root: the
|
||||
/// file never changes while the game runs, and parsing it took about 3 ms
|
||||
/// of the frame that joins a server (or opens a single-player world).
|
||||
/// `None` when it is missing or invalid (not cached: a fixed install can
|
||||
/// join again).
|
||||
pub(super) fn builtin_registries(root: &std::path::Path) -> Option<Arc<Builtin>> {
|
||||
let mut cache = BUILTIN.lock().unwrap_or_else(|e| e.into_inner());
|
||||
if let Some((_, builtin)) = cache.iter().find(|(cached, _)| cached == root) {
|
||||
return Some(builtin.clone());
|
||||
}
|
||||
let builtin = Arc::new(Builtin::find(root).and_then(|p| Builtin::load(&p).ok())?);
|
||||
cache.push((root.to_owned(), builtin.clone()));
|
||||
Some(builtin)
|
||||
}
|
||||
|
||||
/// `ChatType`'s two decorations: how a message shows in the chat, and what
|
||||
/// the narrator says of it.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
@@ -814,9 +832,7 @@ impl Game<'_> {
|
||||
// world's packed table must not name its ids.
|
||||
self.world_biomes = None;
|
||||
let root = self.options.resources.clone();
|
||||
let builtin = Builtin::find(&root)
|
||||
.and_then(|p| Builtin::load(&p).ok())
|
||||
.ok_or("Resources are incomplete: registries.json is missing or invalid. Click \"Prepare again\" in the launcher (or run horizon-prepare), then try again.")?;
|
||||
let builtin = builtin_registries(&root).ok_or("Resources are incomplete: registries.json is missing or invalid. Click \"Prepare again\" in the launcher (or run horizon-prepare), then try again.")?;
|
||||
let lang = Arc::new(horizon_client::net::load_language(&root));
|
||||
// Options.createInformation: what the server learns about this player,
|
||||
// sent again when one of those options changes.
|
||||
@@ -967,7 +983,7 @@ impl Game<'_> {
|
||||
quiet_commands: false,
|
||||
mod_net: false,
|
||||
far_terrain: None,
|
||||
builtin: Arc::new(builtin),
|
||||
builtin,
|
||||
status: lang
|
||||
.get("connect.connecting")
|
||||
.cloned()
|
||||
|
||||
+46
@@ -2461,6 +2461,21 @@ pub trait Hooks: Send + Sync {
|
||||
let _ = host;
|
||||
let _ = event;
|
||||
}
|
||||
/// NeoForge's `ArrowLooseEvent`: the player releases a bow `stack` with
|
||||
/// `has_ammo` and `charge` ticks held. Change `charge` or set `canceled`
|
||||
/// to prevent the shot; negative charge also prevents it. Unlike
|
||||
/// `native_living_entity_use_item_stop`, this does not skip the whole item
|
||||
/// release; `native_entity_shoot_bow` reports a spawned arrow afterward
|
||||
/// with read-only force. Fires on the Game running the bow release, including
|
||||
/// LAN guests; a remote client's own release path is not covered. Crossbows
|
||||
/// and `ArrowNockEvent` are not covered. @API:arrow_loose@.
|
||||
///
|
||||
/// Return `Flow::Cancel` to take it: this sets `canceled`, and later mods are skipped.
|
||||
fn arrow_loose(&self, host: &mut dyn Host, event: &mut ArrowLooseEvent<'_>) -> Flow {
|
||||
let _ = host;
|
||||
let _ = event;
|
||||
Flow::Continue
|
||||
}
|
||||
/// A beacon at `pos` activated or deactivated after its beam was checked.
|
||||
/// `active` says whether it now has a complete pyramid. Server-side.
|
||||
/// @API:beacon_state_change@.
|
||||
@@ -8508,6 +8523,37 @@ pub fn dispatch_anvil_damaged(
|
||||
mod_hook.anvil_damaged(host, &mut event);
|
||||
}
|
||||
}
|
||||
/// What [`Hooks::arrow_loose`] is told. Fields may be added: the struct is `#[non_exhaustive]`.
|
||||
#[non_exhaustive]
|
||||
pub struct ArrowLooseEvent<'a> {
|
||||
pub stack: &'a ItemStack,
|
||||
pub has_ammo: bool,
|
||||
pub charge: i32,
|
||||
}
|
||||
pub fn dispatch_arrow_loose(
|
||||
host: &mut dyn Host,
|
||||
mods: &[Box<dyn Hooks>],
|
||||
stack: &ItemStack,
|
||||
has_ammo: bool,
|
||||
charge: &mut i32,
|
||||
canceled: &mut bool,
|
||||
) {
|
||||
if *canceled {
|
||||
return;
|
||||
}
|
||||
let mut event = ArrowLooseEvent {
|
||||
stack,
|
||||
has_ammo,
|
||||
charge: *charge,
|
||||
};
|
||||
for mod_hook in mods {
|
||||
if matches!(mod_hook.arrow_loose(host, &mut event), Flow::Cancel) {
|
||||
*canceled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*charge = event.charge;
|
||||
}
|
||||
/// What [`Hooks::beacon_state_change`] is told. Fields may be added: the struct is `#[non_exhaustive]`.
|
||||
#[non_exhaustive]
|
||||
pub struct BeaconStateChangeEvent<'a> {
|
||||
|
||||
@@ -23,7 +23,7 @@ use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
Arc, Mutex,
|
||||
atomic::{AtomicBool, Ordering},
|
||||
atomic::{AtomicBool, AtomicU32, Ordering},
|
||||
mpsc::{Receiver, Sender, channel},
|
||||
},
|
||||
thread::JoinHandle,
|
||||
@@ -515,6 +515,23 @@ impl Reason {
|
||||
}
|
||||
}
|
||||
|
||||
/// `ConnectScreen.connect`'s log line, as vanilla writes it from its "Server Connector #N" thread:
|
||||
/// the address as the player gave it, and the port (25565 when none was given), before any SRV
|
||||
/// lookup. Other launchers read the last one from `latest.log` to offer the server again.
|
||||
fn connecting_line(host: &str, port: u16) -> String {
|
||||
format!("Connecting to {host}, {port}")
|
||||
}
|
||||
fn log_connecting(host: &str, port: u16) {
|
||||
// ConnectScreen.UNIQUE_THREAD_ID: the first connector is #1.
|
||||
static CONNECTORS: AtomicU32 = AtomicU32::new(0);
|
||||
let n = CONNECTORS.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
crate::logging::write_as(
|
||||
&format!("Server Connector #{n}"),
|
||||
log::Level::Info,
|
||||
&connecting_line(host, port),
|
||||
);
|
||||
}
|
||||
|
||||
/// `Connection$1.initChannel`: a client socket's pipeline starts with
|
||||
/// `ReadTimeoutHandler(30)`. A server sends a keep-alive every 15 s, so one
|
||||
/// that sends nothing for 30 s has frozen or dropped off the network.
|
||||
@@ -598,6 +615,7 @@ fn run(
|
||||
));
|
||||
};
|
||||
status(send, &tr(lang, "connect.connecting"));
|
||||
log_connecting(&target.0, target.1);
|
||||
target
|
||||
}
|
||||
};
|
||||
@@ -1164,6 +1182,24 @@ fn continues_after_failed_join(lan: bool, signed_in: bool) -> bool {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
/// Launchers find the last server joined in `latest.log` by vanilla's line.
|
||||
#[test]
|
||||
fn the_connecting_line_is_vanillas() {
|
||||
let line = |address: &str| {
|
||||
let (host, port) = parse_address(address).unwrap();
|
||||
connecting_line(&host, port)
|
||||
};
|
||||
assert_eq!(
|
||||
line("play.example.net"),
|
||||
"Connecting to play.example.net, 25565"
|
||||
);
|
||||
assert_eq!(
|
||||
line("play.example.net:25577"),
|
||||
"Connecting to play.example.net, 25577"
|
||||
);
|
||||
assert_eq!(line("[::1]:25566"), "Connecting to ::1, 25566");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn direct_login_keeps_the_hostname_in_the_handshake() {
|
||||
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
|
||||
|
||||
@@ -95,6 +95,7 @@ Optional Windows allocator build features are documented in
|
||||
| E | Inventory and 2x2 crafting (shift-click to quick-move or craft all) |
|
||||
| Q / Ctrl+Q | Drop one / drop stack |
|
||||
| F3 | Debug overlay (position, chunk, light, biome, FPS) |
|
||||
| F3 + S | Dump the texture atlas to `screenshots/debug/`: `minecraft_textures_atlas_gui.png` with `minecraft_textures_atlas_gui.txt` beside it, every sprite's rect in texels (vanilla's `TextureManager.dumpAllSheets`) |
|
||||
| Esc | Pause menu (Save and Quit) |
|
||||
|
||||
Worlds autosave every 6000 ticks (5 minutes), when chunks unload and on quit.
|
||||
|
||||
Generated
+1
@@ -2714,6 +2714,7 @@ dependencies = [
|
||||
"toml 1.1.8+spec-1.1.0",
|
||||
"trash",
|
||||
"ureq",
|
||||
"windows 0.62.2",
|
||||
"windows-sys 0.61.2",
|
||||
"winreg",
|
||||
"winresource",
|
||||
|
||||
@@ -86,6 +86,9 @@ raw-window-handle = "0.6"
|
||||
keyring = { version = "3", features = ["windows-native"] }
|
||||
# The computer's memory, the end of the Launch panel's memory slider; already in the lockfile.
|
||||
windows-sys = { version = "0.61", features = ["Win32_System_SystemInformation"] }
|
||||
# Shortcuts written by the shell itself (shortcut::write_windows_link): the hand-laid Shell Link has
|
||||
# no target ID list, so Explorer shows an empty target and starts nothing.
|
||||
windows = { version = "0.62", features = ["Win32_Foundation", "Win32_Storage_FileSystem", "Win32_System_Com", "Win32_UI_Shell"] }
|
||||
# Per-user setup: the Uninstall entry and the launcher's own key under HKCU (installer.rs).
|
||||
winreg = "0.56"
|
||||
|
||||
|
||||
+36
-13
@@ -165,13 +165,7 @@ fn desktop_link() -> Option<PathBuf> {
|
||||
}
|
||||
|
||||
fn write_link(path: &Path, exe: &Path) -> io::Result<()> {
|
||||
if let Some(dir) = path.parent() {
|
||||
fs::create_dir_all(dir)?;
|
||||
}
|
||||
let bytes = shortcut::lnk(&exe.to_string_lossy(), "", APP_NAME);
|
||||
let temp = path.with_extension("horizon-tmp");
|
||||
fs::write(&temp, bytes)?;
|
||||
fs::rename(&temp, path)
|
||||
shortcut::write_windows_link(path, exe, "", APP_NAME).map_err(io::Error::other)
|
||||
}
|
||||
|
||||
/// Whether the shortcut file names `exe` (its path, as the Shell Link keeps it, in UTF-16).
|
||||
@@ -505,16 +499,45 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
/// What the shell itself reads as the shortcut's target: the field Explorer starts from.
|
||||
fn target_of(link: &Path) -> String {
|
||||
use windows::core::{Interface, HSTRING};
|
||||
use windows::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, IPersistFile, CLSCTX_INPROC_SERVER,
|
||||
COINIT_APARTMENTTHREADED, STGM_READ,
|
||||
};
|
||||
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
|
||||
// SAFETY: COM calls on interfaces made and dropped here, on this test's own thread.
|
||||
unsafe {
|
||||
let _ = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
|
||||
let shell: IShellLinkW =
|
||||
CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER).unwrap();
|
||||
let file: IPersistFile = shell.cast().unwrap();
|
||||
file.Load(&HSTRING::from(link.as_os_str()), STGM_READ)
|
||||
.unwrap();
|
||||
let mut buf = [0u16; 520];
|
||||
shell.GetPath(&mut buf, std::ptr::null_mut(), 0).unwrap();
|
||||
let end = buf.iter().position(|&c| c == 0).unwrap_or(buf.len());
|
||||
String::from_utf16_lossy(&buf[..end])
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_shortcut_points_at_the_launcher_it_was_made_for() {
|
||||
fn the_shell_reads_the_target_of_the_shortcut_it_gets() {
|
||||
let dir = std::env::temp_dir().join(format!("horizon-link-{}", std::process::id()));
|
||||
let _ = fs::create_dir_all(&dir);
|
||||
let _ = fs::remove_dir_all(&dir);
|
||||
let exe = dir.join("Horizon Launcher").join("horizon-launcher.exe");
|
||||
fs::create_dir_all(exe.parent().unwrap()).unwrap();
|
||||
fs::write(&exe, b"x").unwrap();
|
||||
let link = dir.join("Horizon Launcher.lnk");
|
||||
let exe = Path::new(
|
||||
r"C:\Users\player\AppData\Local\Programs\Horizon Launcher\horizon-launcher.exe",
|
||||
write_link(&link, &exe).unwrap();
|
||||
// The bug this guards: a link whose target the shell read as empty, so a double click did nothing.
|
||||
assert_eq!(
|
||||
target_of(&link).to_lowercase(),
|
||||
exe.to_string_lossy().to_lowercase()
|
||||
);
|
||||
fs::write(&link, shortcut::lnk(&exe.to_string_lossy(), "", APP_NAME)).unwrap();
|
||||
assert!(points_to(&link, exe));
|
||||
// The uninstaller finds its shortcuts by the program's path inside them.
|
||||
assert!(points_to(&link, &exe));
|
||||
assert!(!points_to(
|
||||
&link,
|
||||
Path::new(r"C:\Other\horizon-launcher.exe")
|
||||
|
||||
@@ -246,6 +246,51 @@ pub fn lnk(exe: &str, args: &str, comment: &str) -> Vec<u8> {
|
||||
out
|
||||
}
|
||||
|
||||
/// A Windows shortcut written by the shell itself (`IShellLinkW`), as Explorer and every installer
|
||||
/// make one. `lnk` above lays the bytes out from the format's specification, which tests can check
|
||||
/// anywhere, but it has no target ID list, and the shell reads the target from that list: Explorer
|
||||
/// shows an empty target and starts nothing. So on Windows this writes the shortcuts that are used.
|
||||
/// The icon is the program's own, which is also how an uninstall finds shortcuts made for it.
|
||||
#[cfg(windows)]
|
||||
pub fn write_windows_link(
|
||||
path: &Path,
|
||||
exe: &Path,
|
||||
args: &str,
|
||||
comment: &str,
|
||||
) -> Result<(), String> {
|
||||
use windows::core::{Interface, HSTRING};
|
||||
use windows::Win32::System::Com::{
|
||||
CoCreateInstance, CoInitializeEx, CoUninitialize, IPersistFile, CLSCTX_INPROC_SERVER,
|
||||
COINIT_APARTMENTTHREADED,
|
||||
};
|
||||
use windows::Win32::UI::Shell::{IShellLinkW, ShellLink};
|
||||
|
||||
if let Some(dir) = path.parent() {
|
||||
fs::create_dir_all(dir).map_err(|e| format!("{}: {e}", dir.display()))?;
|
||||
}
|
||||
// SAFETY: plain COM calls on interfaces created and dropped here; COM is initialised for this
|
||||
// thread first and released after, when this call is the one that initialised it.
|
||||
unsafe {
|
||||
let init = CoInitializeEx(None, COINIT_APARTMENTTHREADED);
|
||||
let made = (|| -> windows::core::Result<()> {
|
||||
let link: IShellLinkW = CoCreateInstance(&ShellLink, None, CLSCTX_INPROC_SERVER)?;
|
||||
link.SetPath(&HSTRING::from(exe.as_os_str()))?;
|
||||
link.SetArguments(&HSTRING::from(args))?;
|
||||
if let Some(dir) = exe.parent() {
|
||||
link.SetWorkingDirectory(&HSTRING::from(dir.as_os_str()))?;
|
||||
}
|
||||
link.SetIconLocation(&HSTRING::from(exe.as_os_str()), 0)?;
|
||||
link.SetDescription(&HSTRING::from(comment))?;
|
||||
let file: IPersistFile = link.cast()?;
|
||||
file.Save(&HSTRING::from(path.as_os_str()), true)
|
||||
})();
|
||||
if init.is_ok() {
|
||||
CoUninitialize();
|
||||
}
|
||||
made.map_err(|e| format!("{}: {e}", path.display()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the shortcut at `path` plays the instance `id`.
|
||||
fn plays(path: &Path, id: &str) -> bool {
|
||||
let ext = path.extension().and_then(|e| e.to_str()).unwrap_or("");
|
||||
@@ -323,15 +368,16 @@ pub fn make_in(
|
||||
write(&path.join(inside), &bytes, program)?;
|
||||
}
|
||||
}
|
||||
System::Windows => write(
|
||||
&path,
|
||||
&lnk(
|
||||
&exe.to_string_lossy(),
|
||||
&windows_args(id),
|
||||
&format!("Play {name} in Horizon"),
|
||||
),
|
||||
false,
|
||||
)?,
|
||||
System::Windows => {
|
||||
let args = windows_args(id);
|
||||
let comment = format!("Play {name} in Horizon");
|
||||
// On Windows the shell writes the shortcut (`write_windows_link`); elsewhere, and in
|
||||
// tests for the other systems, it is laid out from the format.
|
||||
#[cfg(windows)]
|
||||
write_windows_link(&path, exe, &args, &comment)?;
|
||||
#[cfg(not(windows))]
|
||||
write(&path, &lnk(&exe.to_string_lossy(), &args, &comment), false)?;
|
||||
}
|
||||
}
|
||||
Ok(made)
|
||||
}
|
||||
|
||||
@@ -128,6 +128,28 @@ fn a_windows_shortcut_is_a_shell_link_to_the_launcher() {
|
||||
);
|
||||
}
|
||||
|
||||
/// The shell-written shortcut keeps the instance's arguments, so an uninstall finds it: `plays`
|
||||
/// reads them from the file's Unicode strings.
|
||||
#[cfg(windows)]
|
||||
#[test]
|
||||
fn the_shell_written_link_keeps_the_instance_it_plays() {
|
||||
let root = scratch("plays");
|
||||
let exe = root.join("Horizon Launcher").join("horizon-launcher.exe");
|
||||
fs::create_dir_all(exe.parent().unwrap()).unwrap();
|
||||
fs::write(&exe, b"x").unwrap();
|
||||
let link = root.join("Hardcore (Horizon).lnk");
|
||||
write_windows_link(
|
||||
&link,
|
||||
&exe,
|
||||
&windows_args("hardcore"),
|
||||
"Play Hardcore in Horizon",
|
||||
)
|
||||
.unwrap();
|
||||
assert!(plays(&link, "hardcore"));
|
||||
assert!(!plays(&link, "another"));
|
||||
let _ = fs::remove_dir_all(&root);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shortcuts_are_made_found_renamed_and_removed() {
|
||||
let root = scratch("make");
|
||||
@@ -139,7 +161,13 @@ fn shortcuts_are_made_found_renamed_and_removed() {
|
||||
let bin = trash.clone();
|
||||
let trash_fn = move |p: &Path| desktop_seams::to_folder(p, &bin);
|
||||
let t: Trash = &trash_fn;
|
||||
let exe = Path::new("/opt/horizon-launcher");
|
||||
// A path the shell accepts on the system running the test: Windows writes its shortcuts through
|
||||
// IShellLinkW, which refuses a Unix path.
|
||||
let exe = if cfg!(windows) {
|
||||
Path::new(r"C:\Horizon\horizon-launcher.exe")
|
||||
} else {
|
||||
Path::new("/opt/horizon-launcher")
|
||||
};
|
||||
for system in [System::Linux, System::Mac, System::Windows] {
|
||||
let made = make_in(
|
||||
system,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"name": "arrow_loose",
|
||||
"target": "horizon_client::game::native_hooks::Game<'_>::native_arrow_loose",
|
||||
"neoforge": "ArrowLooseEvent",
|
||||
"side": "server",
|
||||
"cancellable": true,
|
||||
"mod_api": {
|
||||
"contract": "cancel",
|
||||
"out": "canceled"
|
||||
}
|
||||
}
|
||||
],
|
||||
"rust_summary": "A player releases a bow with adjustable charge or cancellation (`native_arrow_loose`).",
|
||||
"doc_summary": "A player releases a bow: `native_arrow_loose(stack, has_ammo, charge, canceled)` may change held-tick `charge` or cancel the shot; negative charge also prevents it. Unlike `native_living_entity_use_item_stop`, it does not skip the whole item release; `native_entity_shoot_bow` reports the spawned arrow afterward with read-only force. Fires on the Game running the bow release, including LAN guests; a remote client's own release path, crossbows, and ArrowNockEvent are not covered. Bundles need \"hooks\": @API:arrow_loose@."
|
||||
}
|
||||
@@ -11,7 +11,7 @@ Allay.isLikedPlayer inline crates/horizon-client/src/mobs/ai.rs::accepts_damage
|
||||
Allay.setJukeboxPlaying inline crates/horizon-client/src/game/allays.rs::Game::tick_allays polls playing jukeboxes within 10 blocks every tick instead of listening for jukebox events; no remembered jukebox
|
||||
Allay.wantsToPickUp inline crates/horizon-client/src/game/allays.rs::Game::tick_allays same item within 32 blocks, mob_griefing on
|
||||
Allay.allayConsidersItemEqual inline crates/horizon-client/src/game/allays.rs::Game::tick_allays gap: compares item ids only, the held item keeps no potion contents
|
||||
Allay.hasNonMatchingPotion missing an allay holding a potion also fetches other potion types; the held item is only an id
|
||||
Allay.hasNonMatchingPotion inline crates/horizon-client/src/mobs/allay.rs::considers_item_equal the potion half of considers_item_equal (held.potion() == candidate.potion()); gap: the potion id only, not custom effects or colour
|
||||
Allay.updateDynamicGameEventListener inline crates/horizon-client/src/game/allays.rs::Game::tick_allays no listener registry: the vibration half is mobs/allay.rs::listen (game/sculk.rs dispatches each event) and the jukebox half is polled here; vanilla's re-registration on a chunk-section change has no counterpart
|
||||
Allay.setDancing inline crates/horizon-client/src/game/allays.rs::Game::tick_allays dancing set while a jukebox plays and not panicking
|
||||
Allay.shouldStopDancing inline crates/horizon-client/src/game/allays.rs::Game::tick_allays no jukebox within 10 blocks stops the dance
|
||||
@@ -47,11 +47,11 @@ Axolotl.soloAnimation inline crates/horizon-client/src/mobs/axolotl.rs::Animatio
|
||||
Axolotl.tickAdultAnimations inline crates/horizon-client/src/mobs/axolotl.rs::Animation::tick the binary animators
|
||||
Axolotl.rehydrate port crates/horizon-client/src/game/splash_water.rs::Game::affect_entities_around water potion on #rehydrates_axolotls: 1800 more air up to MAX_AIR (6000)
|
||||
Axolotl.get port crates/horizon-client/src/entity_nbt.rs::bucket_components axolotl/variant component written to the bucket
|
||||
Axolotl.applyImplicitComponent port crates/horizon-client/src/entity_nbt.rs::load_bucket_data axolotl/variant read from the bucket
|
||||
Axolotl.applyImplicitComponent port crates/horizon-client/src/entity_nbt.rs::apply_item_components axolotl/variant read from the bucket or spawn egg
|
||||
Axolotl.getBreedOffspring port crates/horizon-client/src/game/creatures.rs::Game::breed gap: baby takes the first parent's colour; no random parent, no 1-in-1200 blue, not set persistent
|
||||
Axolotl.createAttributes skip:data attributes come from entity-types.json
|
||||
Axolotl.mobInteract port crates/horizon-client/src/game/creatures.rs::Game::interact_mob a water bucket scoops it up (bucketable)
|
||||
Axolotl.loadFromBucketTag port crates/horizon-client/src/entity_nbt.rs::load_bucket_data age, age lock and hunting cooldown
|
||||
Axolotl.loadFromBucketTag port crates/horizon-client/src/entity_nbt.rs::apply_item_components age, age lock and hunting cooldown from the bucket_entity_data component
|
||||
Axolotl.applySupportingEffects inline crates/horizon-client/src/game/creatures.rs::Game::handle_mob_events the AxolotlSupportPlayer event: regeneration and no mining fatigue, host player only
|
||||
Axolotl.usePlayerItem port crates/horizon-client/src/game/creatures.rs::Game::interact_mob a fed tropical fish bucket leaves a water bucket in its place (creative keeps the fish bucket and adds the bucket)
|
||||
Axolotl.Variant.getSpawnVariant port crates/horizon-client/src/mobs/finalize.rs::Ctx::finalize the common pick for a spawn group; the 1-in-1200 blue draw is the breeding path's (crates/horizon-client/src/game/creatures.rs::Game::breed)
|
||||
@@ -117,8 +117,8 @@ Chicken.defineSynchedData port crates/horizon-client/src/game/lan.rs::mob_meta g
|
||||
Chicken.readAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::mob_from_nbt EggLayTime, variant, sound_variant; jockey in riders.rs
|
||||
Chicken.addAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::mob_to_nbt
|
||||
Chicken.get port crates/horizon-client/src/mobs/finalize.rs::variant_component gap: chicken/variant only, no chicken/sound_variant
|
||||
Chicken.applyImplicitComponents missing variant components on a spawn egg or item are ignored; the mob gets its biome variant
|
||||
Chicken.applyImplicitComponent missing see applyImplicitComponents
|
||||
Chicken.applyImplicitComponents port crates/horizon-client/src/entity_nbt.rs::apply_item_components chicken/variant and chicken/sound_variant from the stack that spawns or buckets it
|
||||
Chicken.applyImplicitComponent port crates/horizon-client/src/entity_nbt.rs::apply_item_components the same fn reads both components
|
||||
Chicken.positionRider inline crates/horizon-client/src/game/passengers.rs::Game::position_riders every mob rider copies its vehicle's body yaw, not only chicken riders
|
||||
ChickenVariants skip:data chicken variants come from the registry data files
|
||||
AbstractCow.registerGoals port crates/horizon-client/src/mobs/farm.rs::register
|
||||
|
||||
|
@@ -65,8 +65,8 @@ PiglinBruteAi.playActivitySound port crates/horizon-client/src/mobs/piglin.rs::p
|
||||
PiglinBruteAi.setAngerTarget missing minor: no 600-tick anger memory; the target goals keep the target instead
|
||||
PiglinBruteAi.updateActivity inline crates/horizon-client/src/mobs/piglin.rs::register_brute gap: minor: no fight and idle activity switch; the melee goal sets the aggressive flag
|
||||
StartAdmiringItemIfSeen.create inline crates/horizon-client/src/game/piglins.rs::Game::piglin_pickups gap: player: a piglin takes a wanted item and admires it in hand; it does not stop to admire one it only sees on the ground
|
||||
StopAdmiringIfItemTooFarAway.create missing minor: no admire-on-the-ground phase, so no stop when the wanted item moves away
|
||||
StopAdmiringIfTiredOfTryingToReachItem.create missing minor: no time limit on walking to an admired item; the piglin walks to the item as GoToWantedItem does
|
||||
StopAdmiringIfItemTooFarAway.create inline crates/horizon-client/src/mobs/piglin.rs::Memories::admire_seen the 9 block test on NEAREST_VISIBLE_WANTED_ITEM (squared 81) while the off hand holds what is admired, folded into the admire memory tick
|
||||
StopAdmiringIfTiredOfTryingToReachItem.create inline crates/horizon-client/src/mobs/piglin.rs::Memories::admire_seen the 200 tick TIME_TRYING_TO_REACH_ADMIRE_ITEM countdown that ends the admire, then DISABLE_WALK_TO_ADMIRE_ITEM for 200
|
||||
Parched.getArrow inline crates/horizon-client/src/mobs/undead.rs::perform_ranged_attack Parched arrows carry weakness for 600 ticks
|
||||
Stray.checkStraySpawnRules port crates/horizon-client/src/mobs/spawn_rules.rs::check_spawn_rules S::Stray arm: powder snow skipped, sky must be visible
|
||||
Stray.getArrow inline crates/horizon-client/src/mobs/undead.rs::perform_ranged_attack Stray arrows carry slowness for 600 ticks
|
||||
@@ -79,20 +79,20 @@ PlayerSkin.Patch.create skip:java record factory for the patch; the patch itsel
|
||||
SpectralArrow.doPostHurtEffects port crates/horizon-client/src/game/potions.rs::Game::arrow_post_hurt_effects 200-tick Glowing on any target a spectral arrow lands on (creatures.rs:3589); a bow, a crossbow and a dispenser also store the effect on the arrow
|
||||
SpectralArrow.tick port crates/horizon-client/src/game/remote_projectiles.rs::Game::arrow_effect_particles client tick: an effect sparkle at the arrow's position while it is not stuck; the tipped arrow's colour swirls share the fn
|
||||
Fireball.getSlot missing minor: the fireball's item slot (its displayed fire charge) is not modelled
|
||||
Fireball.readAdditionalSaveData missing unsure: fireball_from_nbt reads no Item key, so the displayed item is not restored
|
||||
Fireball.readAdditionalSaveData missing `fireball_from_nbt` reads no `Item` key, so a saved fireball is drawn as the default fire charge
|
||||
Fireball.setItem missing minor: the displayed item of a fireball is not set
|
||||
Fireball.shouldRenderAtSqrDistance skip:ui render distance rule for the first two ticks; Horizon draws the projectile as its own pass
|
||||
LargeFireball.onHit port crates/horizon-client/src/game/creatures.rs::Game::projectile_hit LargeFireball arm: explosion of the given power, then the projectile is gone
|
||||
LargeFireball.onHitEntity port crates/horizon-client/src/game/creatures.rs::Game::projectile_hit LargeFireball arm: 6 damage to the entity
|
||||
SmallFireball.onHitEntity port crates/horizon-client/src/game/creatures.rs::Game::projectile_hit SmallFireball arm: ignites for 5 seconds and deals 5 damage
|
||||
AbstractThrownPotion.affectEntitiesAround port crates/horizon-client/src/game/splash_water.rs::Game::affect_entities_around water potion in the potion's (4, 2, 4) box: 1 indirect-magic damage to water-sensitive mobs, put out burning mobs, players and armor stands, then Axolotl.rehydrate
|
||||
AbstractThrownPotion.calculateHorizontalHurtKnockbackDirection missing minor: the splash hurt pushes nothing away from the potion's position
|
||||
AbstractThrownPotion.calculateHorizontalHurtKnockbackDirection inline crates/horizon-client/src/mobs.rs::Mob::damage_with the splash hurt is `Damage::indirect_magic` from the potion position and the hurt pushes away from the source position
|
||||
AbstractThrownPotion.douseFire port crates/horizon-client/src/game/splash_water.rs::Game::douse_fire fire blocks break without drops, lit candles and campfires go out (campfire with level event 1009 and the block-change game event); gap: minor: that game event carries no source entity
|
||||
AbstractThrownPotion.onHitBlock port crates/horizon-client/src/game/splash_water.rs::Game::potion_hit_block a potion in #douses_fire puts out the cell in front of the face it hit, the block it hit and the four horizontal neighbours of the cell in front
|
||||
Snowball.getParticle port crates/horizon-client/src/game/creatures.rs::Game::item_burst snowball item burst on break
|
||||
Snowball.handleEntityEvent port crates/horizon-client/src/game/creatures.rs::Game::thrown_break_event break event 3 for thrown items
|
||||
Snowball.onHit inline crates/horizon-client/src/game/creatures.rs::Game::projectile_hit Snowball arm: 3 damage to blazes, then the break burst
|
||||
ThrowableItemProjectile.readAdditionalSaveData missing minor: the thrown item is not read back from the save
|
||||
ThrowableItemProjectile.readAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::throwable_from_nbt the `Item` it flies as is read back with the rest (a potion keeps its effects); a tag without one keeps `getItem`'s default
|
||||
Activity.equals skip:java value equality of a named activity; no Horizon counterpart needed
|
||||
ModelAndTexture.codec skip:data codec for the variant model and texture asset; Horizon reads variant data from files
|
||||
MoonBrightnessCheck.test inline crates/horizon-client/src/mobs/finalize.rs::VariantRegistry::select Condition::Moon arm: moon brightness of the phase against the range
|
||||
@@ -105,12 +105,12 @@ AbstractMinecartContainer.createMenu inline crates/horizon-client/src/game/minec
|
||||
AbstractMinecartContainer.remove inline crates/horizon-client/src/game/minecarts.rs::Game::hurt_cart contents spill when the cart breaks, if entity_drops is on
|
||||
MinecartChest.interact inline crates/horizon-client/src/game/minecarts.rs::Game::interact_cart chest arm: opens the cart's items and plays the chest sound
|
||||
MinecartCommandBlock.activateMinecart inline crates/horizon-client/src/game/minecarts.rs::Game::activate_cart gap: minor: no command ever runs; the cart holds no command since its editor is missing
|
||||
MinecartCommandBlock.defineSynchedData port crates/horizon-client/src/game/minecarts.rs::command_due the cart's command is held on the cart and runs when an activator rail sets it due
|
||||
MinecartCommandBlock.defineSynchedData port crates/horizon-client/src/game/minecarts.rs::Minecart::new the cart's `synced_command` and `synced_output` start empty on the cart itself, as `DATA_ID_COMMAND_NAME` and `DATA_ID_LAST_OUTPUT` do
|
||||
MinecartCommandBlock.interact port crates/horizon-client/src/game/remote.rs::Game::remote_use_entity the client opens the command editor of the cart it right-clicked
|
||||
MinecartCommandBlock.onSyncedDataUpdated inline crates/horizon-client/src/game/minecarts.rs the command is the cart's own field rather than synched entity data
|
||||
MinecartCommandBlock.onSyncedDataUpdated inline crates/horizon-client/src/game/command_minecarts.rs::Game::cart_command_updated the command is the cart's own field rather than synched entity data, which `onUpdated` copies out
|
||||
MinecartCommandBlock.readAdditionalSaveData inline crates/horizon-client/src/game/minecarts.rs::Minecart::from_nbt gap: minor: the saved Command text is not read
|
||||
MinecartCommandBlock.MinecartCommandBase.createCommandSourceStack port crates/horizon-client/src/game/minecarts.rs:1350 the due command runs with the cart as its source
|
||||
MinecartCommandBlock.MinecartCommandBase.onUpdated inline crates/horizon-client/src/game/minecarts.rs::command_due set by the activator rail at minecarts.rs:1051
|
||||
MinecartCommandBlock.MinecartCommandBase.createCommandSourceStack port crates/horizon-client/src/game/command_minecarts.rs::Game::perform_cart_command the due command runs with the cart as its source: its position, rotation and game master level
|
||||
MinecartCommandBlock.MinecartCommandBase.onUpdated inline crates/horizon-client/src/game/command_minecarts.rs::Game::cart_command_updated copies the command and the last output into the cart's synched fields
|
||||
MinecartFurnace.addAdditionalSaveData port crates/horizon-client/src/game/minecarts.rs::Minecart::to_nbt
|
||||
MinecartFurnace.addFuel inline crates/horizon-client/src/game/minecarts.rs::Game::interact_cart furnace arm: coal or charcoal adds 3600 ticks of fuel up to 32000
|
||||
MinecartFurnace.applyNaturalSlowdown port crates/horizon-client/src/game/minecarts.rs::Game::natural_slowdown
|
||||
@@ -158,7 +158,7 @@ TransientCraftingContainer.getItem skip:java slot read of a menu-owned grid; Ho
|
||||
TransientCraftingContainer.isEmpty skip:java emptiness of a menu-owned grid; Horizon reads menu slots directly
|
||||
TransientCraftingContainer.removeItem skip:java slot removal of a menu-owned grid; Horizon takes from menu slots directly
|
||||
TransientCraftingContainer.setItem skip:java slot write of a menu-owned grid; Horizon writes menu slots directly
|
||||
AdventureModePredicate port crates/horizon-client/src/game.rs::can_place_on_in_adventure the can_place_on / can_break lists are checked before a placement in adventure mode
|
||||
AdventureModePredicate home crates/horizon-client/src/game.rs the can_place_on / can_break lists are checked before a placement in adventure mode (`can_place_on_in_adventure`)
|
||||
ArrayItemProvider.findNext inline crates/horizon-client/src/game/recipe_book.rs::Game::draw_ghost ghost slot item list
|
||||
ArrayItemProvider.next inline crates/horizon-client/src/game/recipe_book.rs::Game::draw_ghost ghost slot item list
|
||||
ArrayItemProvider.peek inline crates/horizon-client/src/game/recipe_book.rs::Game::draw_ghost ghost slot item list
|
||||
@@ -187,8 +187,8 @@ CreativeModeTabs.generateSuspiciousStews skip:data creative contents come from
|
||||
CreativeModeTabs.registerColoredItems skip:data creative contents come from the data file
|
||||
CreativeModeTabs.tryRebuildTabContents port crates/horizon-client/src/creative.rs::Creative::items contents rebuilt on demand
|
||||
DebugStickItem home crates/horizon-client/src/game/debug_stick.rs
|
||||
DoubleHighBlockItem.placeBlock missing unsure: no code found that places the upper half of a tall block
|
||||
DyeItem.interactLivingEntity missing unsure: no dye use on mobs (sheep, collars) found in the client
|
||||
DoubleHighBlockItem.placeBlock port crates/horizon-world/src/level/place.rs::Sim::place the block above is cleared to air (or water when it was water) before the placed half, as `BlockItem.place` does for a double-high item
|
||||
DyeItem.interactLivingEntity port crates/horizon-client/src/game/creatures.rs::Game::interact_mob a dye recolours an unsheared sheep's wool and a tamed wolf's or cat's collar, consumed with `item.dye.use`
|
||||
DyeItem.tryApplyToSign inline crates/horizon-client/src/game/sign_edit.rs::Game::use_sign_applicator dye colours the sign text
|
||||
EggItem.asProjectile port crates/horizon-client/src/game/creatures.rs::Game::throw_item egg kinds in throw_item
|
||||
EggItem.use inline crates/horizon-client/src/game/creatures.rs::Game::throw_item egg throw
|
||||
@@ -198,16 +198,16 @@ ExperienceBottleItem.createDispenseConfig port crates/horizon-client/src/game/di
|
||||
ExperienceBottleItem.use inline crates/horizon-client/src/game/potions.rs::Game::use_potion_item thrown bottle path
|
||||
FireChargeItem.asProjectile port crates/horizon-client/src/game/dispenser.rs::Game::shoot_projectile_item fire charge becomes a small fireball
|
||||
FireChargeItem.createDispenseConfig port crates/horizon-client/src/game/dispenser.rs::Game::dispense_projectile dispensed fire charge flight
|
||||
FireChargeItem.useOn missing unsure: no fire charge use on blocks found in the client
|
||||
FireChargeItem.useOn inline crates/horizon-client/src/game.rs::Game::use_tool lights a campfire or candle, else sets fire above the clicked block, with the fire charge's own pitch and one charge used
|
||||
GameMasterBlockItem.getPlacementState port crates/horizon-client/src/game/block_items.rs::Game::apply_item_block_state default state for the placed block
|
||||
GlowInkSacItem.tryApplyToSign inline crates/horizon-client/src/game/sign_edit.rs::Game::use_sign_applicator glow ink on a sign
|
||||
HangingSignItem.canPlace missing unsure: no hanging sign placement check found
|
||||
HangingSignItem.canPlace inline crates/horizon-world/src/level/place.rs::Sim::placement a wall hanging sign also needs `wall_hanging_sign_can_place` (the same-axis wall sign or a sturdy face), and either kind must survive where it goes
|
||||
InkSacItem.tryApplyToSign inline crates/horizon-client/src/game/sign_edit.rs::Game::use_sign_applicator ink on a sign
|
||||
InstrumentItem.create skip:java builds the horn stack
|
||||
InstrumentItem.getInstrument skip:data instrument read from the item data
|
||||
InstrumentItem.getUseDuration port crates/horizon-client/src/game/item_draw.rs::use_duration goat horn use duration 72000
|
||||
InstrumentItem.play missing player: using a goat horn plays no sound; Horizon has no horn playback
|
||||
InstrumentItem.use missing player: using a goat horn plays no sound and does not start the horn cooldown
|
||||
InstrumentItem.play inline crates/horizon-client/src/game.rs::Game::use_instrument the instrument's sound at the player (SoundSource.RECORDS, volume `range / 16`), `INSTRUMENT_PLAY` and the use-duration cooldown
|
||||
InstrumentItem.use port crates/horizon-client/src/game.rs::Game::use_instrument holds the horn up for the instrument's use duration, plays it, counts the used statistic; an unknown instrument fails
|
||||
Instruments.bootstrap skip:data registry bootstrap of the instrument list
|
||||
Instruments.register skip:data registry bootstrap of the instrument list
|
||||
ItemFrameItem.mayPlace port crates/horizon-client/src/game/frames.rs::Game::place_item_frame
|
||||
@@ -217,8 +217,8 @@ ItemProvider.FallbackItemProvider.findNext inline crates/horizon-client/src/game
|
||||
ItemProvider.FallbackItemProvider.next inline crates/horizon-client/src/game/recipe_book.rs::Game::draw_ghost ghost slot item list
|
||||
ItemProvider.FallbackItemProvider.peek inline crates/horizon-client/src/game/recipe_book.rs::Game::draw_ghost ghost slot item list
|
||||
JukeboxSongs skip:data registry of jukebox songs; song data is read from files
|
||||
KnowledgeBookItem.use missing minor: using a knowledge book (recipe unlock) does nothing in Horizon
|
||||
KnowledgeBookItem.use port crates/horizon-client/src/game/advancements.rs::Game::use_knowledge_book the recipes the book names become known and the book is used up; an invalid recipe knows nothing
|
||||
LingeringPotionItem.createPotion port crates/horizon-client/src/game/potions.rs::thrown_kind lingering entity type
|
||||
LingeringPotionItem.use inline crates/horizon-client/src/game/potions.rs::Game::use_potion_item lingering potion throw
|
||||
NameTagItem.interactLivingEntity missing unsure: name tag use on a mob is only forwarded on remote games (remote_mob_use.rs); no local rename found
|
||||
NameTagItem.interactLivingEntity port crates/horizon-client/src/game/names.rs::Game::name_mob a tag with a custom name names the mob under the crosshair, makes it persistent and is used up, in creative too
|
||||
PlaceOnWaterBlockItem.use inline crates/horizon-client/src/game/block_items.rs::Game::apply_placed_item placed by generic block placement; the water rule is not checked here
|
||||
|
@@ -149,7 +149,7 @@ StraightTrunkPlacer.placeTrunk port crates/horizon-world/src/worldgen/tree/trunk
|
||||
UpwardsBranchingTrunkPlacer.placeBranch port crates/horizon-world/src/worldgen/tree/trunk.rs::TrunkPlacer::upwards_branch
|
||||
UpwardsBranchingTrunkPlacer.placeTrunk port crates/horizon-world/src/worldgen/tree/trunk.rs::TrunkPlacer::place_trunk UpwardsBranching arm
|
||||
UpwardsBranchingTrunkPlacer.validTreePos port crates/horizon-world/src/worldgen/tree/trunk.rs::TrunkPlacer::valid_tree_pos
|
||||
FlatLayerInfo.heightLimited missing minor: no per-layer clamp to the max height; flat settings only cap the total at the build height
|
||||
FlatLayerInfo.heightLimited inline crates/horizon-client/src/title/flat.rs::FlatSettings::from_tag each layer is read with its height clamped to 0..Y_SIZE (DimensionType.Y_SIZE, the most a flat generator takes), and FlatSettings::parse caps it again at the height left below Y_SIZE
|
||||
FlatLayerInfo.toString skip:debug debug text
|
||||
FlatLevelGeneratorPresets.Bootstrap skip:data registry bootstrap of the preset list
|
||||
BiasedToBottomHeight.sample port crates/horizon-world/src/worldgen/height_provider.rs::HeightProvider::sample BiasedToBottom arm
|
||||
|
||||
|
@@ -3,7 +3,7 @@ SetWritableBookPagesFunction missing minor: no vanilla loot table uses set_writ
|
||||
SetWrittenBookPagesFunction missing minor: no vanilla loot table uses set_written_book_pages; Horizon's loot run has no arm for it
|
||||
SmeltItemFunction.run port crates/horizon-world/src/loot.rs::Context::run furnace_smelt arm: smelting recipe, use_input_count and stack cap
|
||||
SmeltItemFunction.smelted skip:java static builder factory
|
||||
ToggleTooltips missing minor: no vanilla loot table uses toggle_tooltips; Horizon's loot run has no arm for it
|
||||
ToggleTooltips home crates/horizon-client/src/game/commands/items.rs the `/item modify` arm toggle_tooltips writes the tooltip_display component's hide_tooltip and hidden_components as run does; the loot run has no arm, and no vanilla loot table uses it
|
||||
LootContextParamSets skip:data loot parameter set registry and validation; Horizon reads its loot tables
|
||||
AllOfCondition.allOf skip:java static builder
|
||||
AllOfCondition.combine inline crates/horizon-items/src/items.rs::LootContext::condition all_of arm: every term must hold
|
||||
@@ -121,14 +121,14 @@ PathAllowList.ConfigEntry.parse skip:server server file allow-list
|
||||
BlockHitResult.hitBorder missing minor: BlockHit has no world-border flag; vanilla projectiles check it on a border hit
|
||||
BlockHitResult.withDirection skip:java copy helper (Rust struct update)
|
||||
BlockHitResult.withPosition skip:java copy helper (Rust struct update)
|
||||
HitResult.distanceTo missing minor: only the fishing bobber's block-hit bounce uses it; Horizon's bobber does not bounce back on a block hit
|
||||
HitResult.distanceTo port crates/horizon-client/src/game/fishing.rs::rebound the bobber's block-hit bounce: the squared distance to the hook scales the normalised velocity (`FishingHook.onHitBlock`)
|
||||
Vec2.add skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.distanceToSqr skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.dot skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.length skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.lengthSquared skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.normalized skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.rotate skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.rotate port crates/horizon-client/src/mobs/sulfur_cube.rs::rotate x cos - y sin, x sin + y cos in floats, for the sulfur cube's 2D maths; the other Vec2 rows stay arithmetic in their callers
|
||||
Vec2.scale skip:other 2D vector maths; Horizon has no Vec2 type and keeps 2D maths in its callers
|
||||
Vec2.equals skip:java Object equality; Rust derives it
|
||||
Vec2.hashCode skip:java Object hashing; Rust derives it
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
VillagerRenderer.getShadowRadius missing minor: baby villagers keep the full shadow radius; shadows.rs shadow_params takes no baby flag
|
||||
VillagerRenderer.getShadowRadius port crates/horizon-client/src/shadows.rs::mob_shadow_radius a baby villager's radius is halved, as the strider's is
|
||||
VillagerRenderer.extractRenderState port crates/horizon-client/src/mobs/villager.rs::anim unhappy head shake read here; gap: player: no held item is read (Horizon villagers carry none)
|
||||
WanderingTraderRenderer.extractRenderState port crates/horizon-client/src/mobs/render.rs::render_with the trader's unhappy counter is never ticked in vanilla (only Villager ticks it), so nothing is read
|
||||
WardenRenderer.<init> port crates/horizon-client/src/mobs/warden.rs::emissive_layers the four emissive layers: bioluminescent, pulsating spots, tendrils, heart
|
||||
@@ -18,33 +18,33 @@ ZombieNautilusRenderer.getTextureLocation port crates/horizon-client/src/mobs/re
|
||||
ZombieNautilusRenderer.extractRenderState port crates/horizon-client/src/mobs/render.rs::layers saddle and armour layers
|
||||
ZombieVillagerRenderer.extractRenderState port crates/horizon-client/src/mobs/render.rs::shaking converting shake; type and profession are in layers, aggressive arms in anim
|
||||
ZombieVillagerRenderer.isShaking port crates/horizon-client/src/mobs/render.rs::shaking converting zombie villagers shake
|
||||
BlockDecorationLayer.submit missing player: a block placed on a copper golem's antenna is not drawn; Horizon reads the antenna slot only as the flower
|
||||
BlockDecorationLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::antenna_block_geometry the antenna slot's block item with its block_state component applied, under applyBlockOnAntennaTransform
|
||||
BreezeEyesLayer.submit port crates/horizon-client/src/mobs/render.rs::layers breeze eyes layer, full bright
|
||||
BreezeWindLayer.submit port crates/horizon-client/src/mobs/render.rs::layers gap: player: the wind layer does not scroll (no texture offset, as noted in layers)
|
||||
CapeLayer.hasLayer missing player: capes are never drawn; skin cape textures are downloaded (skins.rs) but no draw reads them
|
||||
CapeLayer.submit missing player: capes are never drawn (see CapeLayer.hasLayer)
|
||||
CapeLayer.hasLayer inline crates/horizon-client/src/game/perspective.rs::Game::player_cape_geometry only a skin with a cape sprite draws one, and never an invisible player
|
||||
CapeLayer.submit port crates/horizon-client/src/mobs/render.rs::cape the body posed as the player's, the cape turned by the flap and leans
|
||||
CarriedBlockLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::mob_block_geometry the enderman's carried block
|
||||
CatCollarLayer.submit port crates/horizon-client/src/mobs/render.rs::layers dyed collar
|
||||
CrossedArmsItemLayer.submit missing player: a villager or wandering trader never shows an item in its folded arms (Horizon villagers carry nothing and the villager model has no right_arm for the hand lookup)
|
||||
CrossedArmsItemLayer.applyTranslation missing player: no crossed-arms item placement (see CrossedArmsItemLayer.submit)
|
||||
CrossedArmsItemLayer.submit inline crates/horizon-client/src/mobs/render.rs::held_item_transform the villager and wandering trader branch: the main hand's item over the folded arms
|
||||
CrossedArmsItemLayer.applyTranslation port crates/horizon-client/src/mobs/render.rs::crossed_arms_matrix translateToArms, then the item's placement over the folded arms
|
||||
CustomHeadLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::head_item_geometry non-armour head items (carved pumpkins, mob heads, skulls) on players and mobs
|
||||
CustomHeadLayer.resolveSkullRenderType missing player: player-head skins on worn heads are never resolved (no worn heads are drawn, see CustomHeadLayer.submit)
|
||||
Deadmau5EarsLayer.submit missing minor: only a player named deadmau5 gets ears; the name tag lift for them is missing too
|
||||
DolphinCarryingItemLayer.submit missing player: a dolphin carrying an item shows nothing (the dolphin model has no arm bones for the hand lookup)
|
||||
CustomHeadLayer.resolveSkullRenderType port crates/horizon-client/src/game/mob_blocks.rs::Game::head_item_geometry a worn player head takes its profile's skin (entityTranslucent), else the skull model's texture
|
||||
Deadmau5EarsLayer.submit port crates/horizon-client/src/mobs/render.rs::ears two ears in the player's own skin, for a player named deadmau5
|
||||
DolphinCarryingItemLayer.submit inline crates/horizon-client/src/mobs/render.rs::held_item_transform the dolphin branch: the main hand's item at the snout, lifted and pulled in as it pitches
|
||||
DrownedOuterLayer.submit port crates/horizon-client/src/mobs/render.rs::layers drowned outer layer, adult and baby
|
||||
EnergySwirlLayer.submit port crates/horizon-client/src/mobs/render.rs::energy_swirl charged creeper and powered wither swirl, drawn in render_visible
|
||||
EquipmentLayerRenderer.renderLayers port crates/horizon-client/src/game/armor_stands.rs::Game::armor_layers draws all humanoid layers of the equipment asset, including leather overlay
|
||||
EquipmentLayerRenderer.getColorForLayer port crates/horizon-client/src/game/armor_stands.rs::Game::armor_layers gap: player: a dyed leather piece is drawn in the undyed brown; the stack's dyed colour is not read
|
||||
EquipmentLayerRenderer.TrimTextureKey.createTextureWithNoPalette port crates/horizon-client-render/src/trims.rs::TrimTexture::generate a trim with no palette is used as its own texture
|
||||
EyesLayer.submit port crates/horizon-client/src/mobs/render.rs::layers spider, enderman and phantom eyes
|
||||
FoxHeldItemLayer.submit missing player: a fox's food in its mouth (berries, fish) is not drawn; the fox model has no arm bones for the hand lookup
|
||||
FoxHeldItemLayer.submit inline crates/horizon-client/src/mobs/render.rs::held_item_transform the fox branch: the main hand's item in its mouth, at fox_item_transform
|
||||
HorseMarkingLayer.submit port crates/horizon-client/src/mobs/render.rs::layers horse markings layer
|
||||
HumanoidArmorLayer.shouldRender port crates/horizon-client/src/mobs/render.rs::humanoid_armor slot read from the item id suffix (_helmet and so on); players use Game::armor_layers
|
||||
HumanoidArmorLayer.submit port crates/horizon-client/src/mobs/render.rs::humanoid_armor armour for mobs; players use Game::armor_layers
|
||||
HumanoidArmorLayer.renderArmorPiece port crates/horizon-client/src/mobs/render.rs::humanoid_armor one armour piece per slot with its layer model
|
||||
HumanoidArmorLayer.getArmorModel port crates/horizon-client/src/mobs/render.rs::humanoid_armor armour model is the body's #helmet, #chestplate, #leggings or #boots part
|
||||
IronGolemCrackinessLayer.submit port crates/horizon-client/src/mobs/render.rs::layers crack levels via golem::crackiness
|
||||
IronGolemFlowerLayer.submit missing player: an iron golem offering a poppy raises its arm (golem anim) but no poppy is drawn in it
|
||||
IronGolemFlowerLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::golem_flower_geometry the poppy in the right arm while the offer tick runs
|
||||
ItemInHandLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::held_item_geometry both hands through the item pipeline
|
||||
ItemInHandLayer.useBabyOffset port crates/horizon-client/src/mobs/render.rs::hand_base baby hand offset
|
||||
LivingEntityEmissiveLayer.submit port crates/horizon-client/src/mobs/render.rs::layers emissive layers drawn full bright; warden alpha is in warden::emissive_layers
|
||||
@@ -53,12 +53,12 @@ LlamaDecorLayer.renderEquipment port crates/horizon-client/src/mobs/llama.rs::de
|
||||
MushroomCowMushroomLayer.submitMushroomBlock port crates/horizon-client/src/game/mob_blocks.rs::Game::worn_block_geometry mushrooms on an adult mooshroom
|
||||
PandaHoldsItemLayer.submit port crates/horizon-client/src/mobs/panda.rs::item_offset item in the mouth of a sitting panda, with the eating bob
|
||||
ParrotOnShoulderLayer.submit port crates/horizon-client/src/mobs/render.rs::shoulder_parrot
|
||||
ParrotOnShoulderLayer.submitOnShoulder missing player: a parrot on a player's shoulder is not drawn (see ParrotOnShoulderLayer.submit)
|
||||
ParrotOnShoulderLayer.submitOnShoulder port crates/horizon-client/src/mobs/render.rs::shoulder_parrot the shoulder's parrot in the ON_SHOULDER pose with the avatar's walk animation, age and head turn
|
||||
PlayerItemInHandLayer.submitArmWithItem port crates/horizon-client/src/game/mob_blocks.rs::Game::held_item_geometry gap: player: the spyglass raised to the eye is not drawn (see renderItemHeldToEye)
|
||||
PlayerItemInHandLayer.renderItemHeldToEye missing player: another player using a spyglass does not hold it at the eye in third person; Horizon has no held-on-head state
|
||||
PlayerItemInHandLayer.renderItemHeldToEye port crates/horizon-client/src/mobs/render.rs::held_to_eye_matrix a spyglass in use, with no swing in progress, held at the eye
|
||||
RenderLayer.coloredCutoutModelCopyLayerRender port crates/horizon-client/src/mobs/render.rs::render_visible coloured cutout layers drawn in render_visible
|
||||
RenderLayer.renderColoredCutoutModel port crates/horizon-client/src/mobs/render.rs::render_visible coloured cutout layers drawn in render_visible
|
||||
RopesLayer.submit missing player: a harnessed happy ghast that holds a leash shows no rope model on its body
|
||||
RopesLayer.submit inline crates/horizon-client/src/mobs/render.rs::layers the ropes layer over a harnessed happy ghast that holds a leash
|
||||
SheepWoolLayer.submit port crates/horizon-client/src/mobs/render.rs::layers gap: minor: the outline-only pass for an invisible glowing sheep is not drawn
|
||||
SheepWoolUndercoatLayer.submit port crates/horizon-client/src/mobs/render.rs::layers gap: player: a sheep named jeb_ gets no undercoat while its wool is white (vanilla always draws it for jeb_)
|
||||
SimpleEquipmentLayer.submit port crates/horizon-client/src/mobs/render.rs::layers pig, strider and nautilus saddles and the happy ghast harness
|
||||
@@ -66,8 +66,8 @@ SkeletonClothingLayer.submit port crates/horizon-client/src/mobs/render.rs::laye
|
||||
SlimeOuterLayer.submit port crates/horizon-client/src/mobs/render.rs::layers translucent outer slime cube
|
||||
SnowGolemHeadLayer.submit port crates/horizon-client/src/game/mob_blocks.rs::Game::worn_block_geometry carved pumpkin on the snow golem
|
||||
SpinAttackEffectLayer.submit port crates/horizon-client/src/game/perspective.rs::Game::spin_attack_geometry riptide spin model
|
||||
StuckInBodyLayer.submitStuckItem missing player: arrows stuck in a player's body are not drawn (Horizon keeps no stuck-arrow count)
|
||||
StuckInBodyLayer.submit missing player: arrows stuck in a player's body are not drawn (see submitStuckItem)
|
||||
StuckInBodyLayer.submitStuckItem port crates/horizon-client/src/mobs/render.rs::stuck_in_body each arrow or stinger in a random cube of the posed body, ON_SURFACE snapping to a face
|
||||
StuckInBodyLayer.submit inline crates/horizon-client/src/game/perspective.rs::Game::stuck_in_body_geometry the arrow and stinger counts, for another player and for the local player
|
||||
SulfurCubeInnerLayer.submit port crates/horizon-client/src/mobs/render.rs::layers gap: player: a block swallowed by a sulfur cube is not drawn inside the shell (sulfur_cube::inner returns nothing when the cube has a body)
|
||||
TropicalFishPatternLayer.submit port crates/horizon-client/src/mobs/render.rs::layers pattern on the small or large model, tinted
|
||||
VillagerProfessionLayer.submit port crates/horizon-client/src/mobs/render.rs::layers type, profession and level layers; hat masks applied in render_visible
|
||||
@@ -85,7 +85,7 @@ AvatarRenderer.submitNameDisplay port crates/horizon-client/src/game/names.rs::G
|
||||
AvatarRenderer.extractRenderState port crates/horizon-client/src/mobs.rs::Mob::tick_avatar_pose glide count, wings and swim read here; gap: player: arrow and stinger counts, parrots, cape, ears and the spyglass use are not read
|
||||
AvatarRenderer.shouldShowName port crates/horizon-client/src/game/names.rs::Game::name_tags name tags for players and named mobs
|
||||
AvatarRenderer.extractFlightData port crates/horizon-client/src/mobs/render.rs::base_transform_at glide time drives the tilt; gap: player: the body does not turn toward the flight direction (no flying yaw)
|
||||
AvatarRenderer.extractCapeState missing player: capes are never drawn, so the cape flap and lean are never used
|
||||
AvatarRenderer.extractCapeState port crates/horizon-client-render/src/camera.rs::AvatarBob::cape the cape flap, lean and lean2 from the cloak lagging behind the body
|
||||
AvatarRenderer.renderRightHand port crates/horizon-client/src/game.rs::Game::hand_geometry first-person arm; gap: minor: no 0.1 radian arm tilt or sleeve toggle in hand_geometry
|
||||
AvatarRenderer.renderLeftHand port crates/horizon-client/src/game.rs::Game::hand_geometry first-person arm; gap: minor: no 0.1 radian arm tilt or sleeve toggle in hand_geometry
|
||||
AvatarRenderer.renderHand port crates/horizon-client/src/game.rs::Game::hand_geometry first-person arm; gap: minor: no 0.1 radian arm tilt or sleeve toggle in hand_geometry
|
||||
|
||||
|
@@ -6,7 +6,7 @@ SectionRenderDispatcher.uploadTerrainBuffersToGpu port crates/horizon-client-ren
|
||||
SectionRenderDispatcher.schedule port crates/horizon-client-render/src/streaming.rs::Streaming::submit the mesh job goes into the priority queue by distance
|
||||
SectionRenderDispatcher.dispose port crates/horizon-client-render/src/gfx.rs::Renderer::clear_sections frees every section's GPU buffers
|
||||
SectionRenderDispatcher.getStats skip:debug F3 text: compile queue size and free buffers
|
||||
SectionRenderDispatcher.RenderSection.getVisibility missing player: newly meshed terrain appears at full strength; vanilla fades each section in over the chunkSectionFadeInTime option, and block entities wait for 0.3
|
||||
SectionRenderDispatcher.RenderSection.getVisibility port crates/horizon-client-render/src/gfx.rs::chunk_visibility a section's visibility runs 0 to 1 over Options.chunkSectionFadeInTime from the upload; the instance data carries 1 - it to the terrain shader
|
||||
SectionRenderDispatcher.RenderSection.setSectionNode port crates/horizon-client-render/src/gfx.rs::section_instance the section's render origin; its 16-block bounds are derived from the origin
|
||||
SectionRenderDispatcher.RenderSection.reset port crates/horizon-client-render/src/gfx.rs::Renderer::release_section drops the section's mesh and GPU slices
|
||||
SectionRenderDispatcher.RenderSection.resortTransparency port crates/horizon-client-render/src/gfx/translucency.rs::SortState::update translucent quads re-sorted for the camera; gap: minor: the new order goes to the next draw, not a newly uploaded index buffer
|
||||
@@ -51,7 +51,7 @@ BreezeDebugRenderer missing minor: F3 breeze jump target view; breeze_jump_targ
|
||||
ChunkCullingDebugRenderer missing minor: F3 chunk culling frustum view; the occlusion graph has no draw
|
||||
ChunkDebugRenderer missing minor: F3 chunk info view fed by the integrated server; not drawn
|
||||
ChunkDebugRenderer.ChunkData missing minor: data for the F3 chunk info view; not built
|
||||
CollisionBoxRenderer missing minor: F3 block collision box view; not drawn
|
||||
CollisionBoxRenderer home crates/horizon-client/src/game/debug_renderers.rs Game::debug_renderer_gizmos outlines the block shapes within 6 of the camera entity's box, white (visualize_collision_boxes)
|
||||
DebugRenderer.refreshRendererList inline crates/horizon-client/src/game/debug_keys.rs::Game::debug_gizmos the enabled views; Horizon has only chunk borders (show_chunk_borders) and hitboxes (show_hitboxes), the rest are missing
|
||||
DebugRenderer.getTargetedEntity skip:debug entity under the crosshair for debug views only
|
||||
DebugRenderer.mixColor skip:debug colour helper for debug paths
|
||||
@@ -62,8 +62,8 @@ EntityHitboxDebugRenderer.getServerEntity skip:debug the integrated server's en
|
||||
GameEventListenerRenderer missing minor: F3 game event listener view; not drawn
|
||||
GameTestBlockHighlightRenderer skip:debug game test block markers; Horizon does not run game tests
|
||||
GoalSelectorDebugRenderer missing minor: F3 mob goal view; not drawn
|
||||
HeightMapRenderer missing minor: F3 heightmap view; not drawn
|
||||
LightDebugRenderer missing minor: F3 light level view; not drawn
|
||||
HeightMapRenderer home crates/horizon-client/src/game/debug_renderers.rs Game::heightmap_shapes fills a small box per column of the 5x5 chunks around the camera, stacked by kind, coloured as getColor (visualize_heightmap)
|
||||
LightDebugRenderer home crates/horizon-client/src/game/debug_renderers.rs light_level_texts prints the block and sky light within 10 of the camera (visualize_block_light_levels and visualize_sky_light_levels)
|
||||
LightSectionDebugRenderer missing minor: F3 light section view; not drawn
|
||||
LightSectionDebugRenderer.SectionData missing minor: data for the F3 light section view; not built
|
||||
NeighborsUpdateRenderer missing minor: F3 neighbour update view; not drawn
|
||||
@@ -73,13 +73,13 @@ PathfindingRenderer missing minor: F3 mob path view; not drawn
|
||||
PoiDebugRenderer missing minor: F3 point of interest view; not drawn
|
||||
RaidDebugRenderer missing minor: F3 raid centre view; not drawn
|
||||
RedstoneWireOrientationsRenderer missing minor: F3 redstone wire orientation view; not drawn
|
||||
SolidFaceRenderer missing minor: F3 solid face view; not drawn
|
||||
SolidFaceRenderer home crates/horizon-client/src/game/debug_renderers.rs Game::solid_face_shapes fills the sturdy sides of the outline boxes of the blocks within 6, grown by 0.002 (visualize_solid_faces)
|
||||
StructureRenderer missing minor: F3 structure bounding box view fed by debug subscriptions; Horizon sends none
|
||||
SupportBlockRenderer missing minor: F3 support block view; not drawn
|
||||
VillageSectionsDebugRenderer missing minor: F3 village section view; not drawn
|
||||
WaterDebugRenderer missing minor: F3 water level view; not drawn
|
||||
WaterDebugRenderer home crates/horizon-client/src/game/debug_renderers.rs Game::water_level_shapes fills each water block within 10 of the feet to its height and prints its amount over it (visualize_water_levels)
|
||||
LevelExtractor.extract port crates/horizon-client/src/game.rs::Game::render the frame's extraction and draw; gap: minor: no separate render state, the frame is built and drawn in one fn
|
||||
LevelExtractor.drainTransientBlockQueue missing player: temporary blocks the server shows (ClientboundAddTransientBlockPacket) never appear; the packet has an id in horizon-protocol but no handler
|
||||
LevelExtractor.drainTransientBlockQueue port crates/horizon-client/src/game/transient_blocks.rs::Game::drain_transient_block_queue ClientboundAddTransientBlock's blocks are drawn as moving blocks until a section mesh compiled after them is uploaded
|
||||
LevelExtractor.extractVisibleBlockEntities inline crates/horizon-client/src/game.rs::Game::render block entities of the visible sections; gap: minor: no 0.3 visibility gate, see RenderSection.getVisibility
|
||||
LevelExtractor.extractBlockDestroyAnimation port crates/horizon-client/src/game.rs::Game::destroy_block_progress keeps the crumbling progress per breaker for 400 ticks; gap: minor: no 32-block distance cut here
|
||||
LevelExtractor.extractGizmos port crates/horizon-client/src/game/debug_keys.rs::Game::debug_gizmos the frame's debug gizmos
|
||||
|
||||
|
@@ -25,7 +25,7 @@ Font.PreparedTextBuilder.visit skip:other visitor over prepared glyphs for draw
|
||||
Font.PreparedTextBuilder.getTextColor inline crates/horizon-client-render/src/hud.rs::HudBatch::text_styled style colour with the base colour's alpha
|
||||
Font.PreparedTextBuilder.getShadowColor inline crates/horizon-client-render/src/hud.rs::HudBatch::text_styled gap: minor: style shadow colour is ignored; shadow is always 0.25 of the text colour
|
||||
Font.PreparedTextBuilder.bounds skip:other bounds of prepared text for vanilla hit tests; Horizon hit-tests by advance
|
||||
Gui.update skip:other narrator-only update (handleDelayedNarration); Horizon has no narrator
|
||||
Gui.update inline crates/horizon-client/src/game/narrator.rs::Game::narrate_screen once a turn after the frame's widgets were read: ScreenNarrator::frame runs the narration handleDelayedNarration makes due and a new screen's
|
||||
Gui.isPausing port crates/horizon-client/src/game.rs::Game::pauses_game gap: minor: checks the open screen only, not the overlay part
|
||||
Gui.addSocialInteractionsToast skip:service social interactions are not offered by Horizon
|
||||
Gui.handleKeybinds port crates/horizon-client/src/game.rs::Game::key_pressed gap: minor: the social interactions key has no port (see addSocialInteractionsToast)
|
||||
@@ -113,8 +113,8 @@ AbstractSelectionList.nextEntry port crates/horizon-client/src/game/key_focus.rs
|
||||
AbstractSelectionList.extractListItems port crates/horizon-client-render/src/pack_screen.rs::PackScreen::draw_list rows culled to the visible band
|
||||
AbstractSelectionList.extractItem port crates/horizon-client-render/src/pack_screen.rs::PackScreen::draw_list selection outline and row content
|
||||
AbstractSelectionList.extractSelection port crates/horizon-client-render/src/pack_screen.rs::PackScreen::draw_list two fills: outline colour and black inner
|
||||
AbstractSelectionList.getRowBottom skip:other only the LAN-found narration uses it; Horizon has no narrator
|
||||
AbstractSelectionList.narrationPriority skip:other screen-reader priority; Horizon has no narrator
|
||||
AbstractSelectionList.getRowBottom inline crates/horizon-client/src/multiplayer.rs::Multiplayer::lan_found_narrations ServerSelectionList.updateNetworkServers is its only caller, testing whether a LAN world found since the last call has its row in view; that test computes the row's top and bottom here (row_top + ROW_HEIGHT)
|
||||
AbstractSelectionList.narrationPriority inline crates/horizon-client/src/screen_narrator.rs::Ctx::priority focused, else hovered (a list's is a row under the mouse), else none; a container list is focused with one of its widgets
|
||||
AbstractSelectionList.removeEntry skip:other rows are rebuilt from the model when they change (update_list, server list), so there is no single-row removal
|
||||
AbstractSelectionList.narrateListElementPosition skip:other narration only
|
||||
AbstractSelectionList.TrackedList.set skip:java delegate list wrapper
|
||||
|
||||
|
@@ -30,13 +30,13 @@ ChatComponent.DrawingFocusedGraphicsAccess.showTooltip port crates/horizon-clien
|
||||
Checkbox.adjustWidth missing minor: the checkbox width is never capped or its label wrapped; dialog_screen.rs:137 sets the width to the full label
|
||||
Checkbox.overflowsRowLimit missing minor: no tooltip for a label that wraps past two rows; Horizon dialog labels never wrap
|
||||
Checkbox.onPress port crates/horizon-client/src/game/dialogs.rs::Game::dialog_click toggles the boolean input value (dialogs.rs:448)
|
||||
Checkbox.updateWidgetNarration skip:other narration text; Horizon has no narrator (the Narrator option is stored only)
|
||||
Checkbox.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's checkbox arm: gui.narrate.button(message), then narration.checkbox.usage.{focused,hovered}.{check,uncheck} while the widget is active
|
||||
Checkbox.extractContents port crates/horizon-client/src/game/dialogs.rs::Game::draw_dialog box sprite for checked and focused states, then the label (Part::Check)
|
||||
Checkbox.Builder.selected skip:java builder setter
|
||||
Checkbox.Builder.build skip:java builder: makes the checkbox and its tooltip
|
||||
CommandSuggestions.mouseScrolled port crates/horizon-client-render/src/chat.rs::ChatScreen::scroll wheel over the suggestion list, clamped to the list
|
||||
CommandSuggestions.mouseClicked port crates/horizon-client-render/src/chat.rs::ChatScreen::click click on a suggestion row uses it, else the input box
|
||||
CommandSuggestions.getUsageNarration skip:other narration text; no narrator in Horizon
|
||||
CommandSuggestions.getUsageNarration port crates/horizon-client-render/src/chat.rs::ChatScreen::suggestions_usage narration.suggestion.usage.{cycle,fill}.{hidable,fixed} while the list shows; Game::draw_command_block passes it as the screen's usage
|
||||
CommandSuggestions.sortSuggestions port crates/horizon-client-render/src/chat.rs::ChatScreen::show_suggestions suggestions starting with the typed word first, including the minecraft: prefix
|
||||
CommandSuggestions.hasMessageArguments missing minor: a /say or /msg style command with a message argument counts as a command here; Horizon's parse keeps no argument kinds (see update_usage_info comment)
|
||||
CommandSuggestions.getExceptionMessage port crates/horizon-client-render/src/chat.rs::ChatScreen::update_usage_info parse errors shown with their context (e.with_context)
|
||||
@@ -46,29 +46,29 @@ CommandSuggestions.formatChat port crates/horizon-client-render/src/chat.rs::Cha
|
||||
CommandSuggestions.calculateSuggestionSuffix port crates/horizon-client-render/src/chat.rs::ChatScreen::select the grey suffix for the highlighted suggestion (strip the typed prefix)
|
||||
CommandSuggestions.extractSuggestions port crates/horizon-client-render/src/chat.rs::ChatScreen::draw the suggestion list drawn when it is open
|
||||
CommandSuggestions.extractUsage port crates/horizon-client-render/src/chat.rs::ChatScreen::draw usage lines drawn upward from the bottom, as vanilla's bottom anchor
|
||||
CommandSuggestions.getNarrationMessage skip:other narration text; no narrator in Horizon
|
||||
CommandSuggestions.getNarrationMessage inline crates/horizon-client-render/src/chat.rs::SuggestionList::narration_message the selected suggestion, said when the selection moves (ChatScreen::select); gap: minor: the chat screen's own narration does not add it (screen_info::chat reads the usage and the typed message)
|
||||
CommandSuggestions.hasAllowedInput port crates/horizon-client-render/src/chat.rs::ChatAbilities::allows gap: minor: a /say style command is judged as a command, not a message (see hasMessageArguments)
|
||||
CommandSuggestions.SuggestionsList.extractRenderState port crates/horizon-client-render/src/chat.rs::ChatScreen::draw_list rows, scroll marks, highlight and tooltip; gap: minor: no pointing-hand cursor over the rows
|
||||
CommandSuggestions.SuggestionsList.mouseClicked port crates/horizon-client-render/src/chat.rs::ChatScreen::click row click selects and uses the suggestion
|
||||
CommandSuggestions.SuggestionsList.keyPressed port crates/horizon-client-render/src/chat.rs::ChatScreen::key up, down and tab cycle and use the suggestion
|
||||
CommandSuggestions.SuggestionsList.cycle port crates/horizon-client-render/src/chat.rs::ChatScreen::cycle moves the selection and the scroll offset
|
||||
CommandSuggestions.SuggestionsList.getNarrationMessage skip:other narration text; no narrator in Horizon
|
||||
CommandSuggestions.SuggestionsList.getNarrationMessage port crates/horizon-client-render/src/chat.rs::suggestion_narration narration.suggestion, or narration.suggestion.tooltip when the entry has one, over the position, the count and the text; SuggestionList::narration_message marks lastNarratedEntry
|
||||
ComponentRenderUtils.stripColor port crates/horizon-client-render/src/chat.rs::Chat::displayed with Chat Colors off the section codes are stripped before wrapping
|
||||
ContainerObjectSelectionList.nextFocusPath port crates/horizon-client-input/src/gamepad.rs::focus_step gap: minor: picks the nearest target by geometry, not row by row with a wrap to the next entry
|
||||
ContainerObjectSelectionList.setFocused missing minor: unsure: no list focus model beyond gamepad focus_step; losing focus does not clear a selection here
|
||||
ContainerObjectSelectionList.updateWidgetNarration skip:other narration text; no narrator in Horizon
|
||||
ContainerObjectSelectionList.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's container-list arm: the row under the mouse for the mouse and the system, else the focused one, then narrator.position.list; the row's own widgets one level deeper (narrate_row)
|
||||
ContainerObjectSelectionList.Entry.setFocused missing minor: unsure: focus inside a row is not tracked; focus_step works on target rectangles
|
||||
ContainerObjectSelectionList.Entry.focusPathAtIndex missing minor: unsure: no per-row focus path; see focus_step
|
||||
ContainerObjectSelectionList.Entry.nextFocusPath port crates/horizon-client-input/src/gamepad.rs::focus_step gap: minor: moves by nearest target rectangle, not by child index within the row
|
||||
ContainerObjectSelectionList.Entry.updateNarration skip:other narration text; no narrator in Horizon
|
||||
ContainerObjectSelectionList.Entry.updateNarration port crates/horizon-client/src/screen_narrator.rs::narrate_row the row widget findNarratableWidget picks (inactive ones too), with narrator.position.object_list when the row has more than one
|
||||
CycleButton.extractContents port crates/horizon-client-render/src/options_ui.rs::OptionsUi::draw option button sprite and its label
|
||||
CycleButton.onPress port crates/horizon-client-render/src/options_ui.rs::Opt::cycle click cycles forward; the back flag comes from the caller
|
||||
CycleButton.getCycledValue skip:other only feeds the narration of the next value
|
||||
CycleButton.mouseScrolled port crates/horizon-client-render/src/options_ui.rs::OptionsUi::wheel the wheel over a cycle button takes its step (up goes back) and the list stays put; a blocked row falls through to the page
|
||||
CycleButton.updateValue inline crates/horizon-client-render/src/options_ui.rs::Opt::cycle labels are read live from Settings (Opt::label), so no cached message needs updating
|
||||
CycleButton.createLabelForValue port crates/horizon-client-render/src/options_ui.rs::Opt::label value label or full name, from the setting
|
||||
CycleButton.updateWidgetNarration skip:other narration text; no narrator in Horizon
|
||||
CycleButton.createDefaultNarrationMessage skip:other narration text; no narrator in Horizon
|
||||
CycleButton.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's cycle arm: gui.narrate.button(name: value), then narration.cycle_button.usage.{focused,hovered} with the value a click moves to
|
||||
CycleButton.createDefaultNarrationMessage inline crates/horizon-client/src/screen_narrator.rs::narrate the gui.narrate.button wrap of narrate's cycle arm; the name and value it wraps are built where the widget is recorded (options.generic_value in the screen's label)
|
||||
CycleButton.builder skip:java builder
|
||||
CycleButton.booleanBuilder skip:java builder
|
||||
CycleButton.onOffBuilder skip:java builder
|
||||
@@ -92,7 +92,7 @@ DebugScreenOverlay.toggleFpsCharts port crates/horizon-client/src/debug_chart.rs
|
||||
DebugScreenOverlay.toggleLightmapTexture port crates/horizon-client/src/debug_chart.rs::DebugCharts::toggle_lightmap toggles the lightmap and clears the others
|
||||
DebugScreenOverlay.toggleProfilerChart missing minor: no profiler chart (see showProfilerChart)
|
||||
DebugScreenOverlay.logRemoteSample missing minor: unsure: the debug_sample packet is only named in horizon-protocol/src/ids.rs, so a server's samples are not logged
|
||||
EditBox.createNarrationMessage skip:other narration text; no narrator in Horizon
|
||||
EditBox.createNarrationMessage inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's edit-box arm: gui.narrate.editBox(message, value); Narratable::edit_box is recorded by ui::EditBox::draw and screen_draw's field
|
||||
EditBox.getHighlighted port crates/horizon-client-render/src/ui.rs::EditBox::selected_text the text between cursor and highlight
|
||||
EditBox.moveCursorTo port crates/horizon-client-render/src/ui.rs::EditBox::set_cursor sets the cursor and keeps the highlight unless extending
|
||||
EditBox.setCursorPosition port crates/horizon-client-render/src/ui.rs::EditBox::set_cursor clamps and scrolls to the cursor
|
||||
@@ -109,7 +109,7 @@ EditBox.setHint inline crates/horizon-client/src/title/create_world.rs::Title::c
|
||||
FittingMultiLineTextWidget.setWidth skip:ui layout: wrap width
|
||||
FittingMultiLineTextWidget.minimizeHeight skip:ui layout: height to content
|
||||
FittingMultiLineTextWidget.extractContents port crates/horizon-client/src/game/dialogs.rs::Game::draw_dialog message lines drawn as text parts
|
||||
FocusableTextWidget.updateWidgetNarration skip:other narration text; no narrator in Horizon
|
||||
FocusableTextWidget.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's text arm reads the widget's message; gap: minor: the focusedUsageNarration and hoveredUsageNarration a FocusableTextWidget can carry are not modelled
|
||||
FocusableTextWidget.extractWidgetRenderState port crates/horizon-client/src/game/lan_screen.rs::Game::draw_restrictions gap: minor: text only; no focus outline or background fill
|
||||
FocusableTextWidget.updateWidth skip:ui layout: width from the message
|
||||
FocusableTextWidget.updateHeight skip:ui layout: height from the wrapped lines
|
||||
@@ -124,12 +124,12 @@ ImageWidget.texture skip:java factory
|
||||
ImageWidget.Sprite.extractWidgetRenderState skip:other picture of a popup or social tab; Horizon's lock popup has no picture
|
||||
ImageWidget.Texture.extractWidgetRenderState skip:other picture of a popup or social tab; Horizon's lock popup has no picture
|
||||
ItemDisplayWidget.extractWidgetRenderState port crates/horizon-client/src/game/dialogs.rs::Game::draw_dialog a dialog's item body draws the item at its corner, then its decorations, and its tooltip under the cursor
|
||||
ItemDisplayWidget.updateWidgetNarration skip:other narration text; no narrator in Horizon
|
||||
ItemDisplayWidget.updateWidgetNarration inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats narration.item(hover name) recorded as the stats screen's item row text, the ItemRowWidget that is an ItemDisplayWidget
|
||||
LoadingDotsWidget.extractWidgetRenderState port crates/horizon-client/src/multiplayer.rs::Screen::draw the scanning label and the animated dots under it on the LAN row
|
||||
LockIconButton.createNarrationMessage skip:other narration text; no narrator in Horizon
|
||||
LockIconButton.createNarrationMessage inline crates/horizon-client/src/game/lan_screen.rs::WorldOptions::narration gui.narrate.button(narrator.button.difficulty_lock) joined for narration with narrator.button.difficulty_lock.locked or .unlocked (Button::Lock)
|
||||
LockIconButton.extractContents port crates/horizon-client/src/game/lan_screen.rs::Game::draw_options_view lock or unlock sprite by state
|
||||
LogoRenderer.extractRenderState port crates/horizon-client/src/title.rs::Title::draw logo top 44 rows and edition banner; gap: minor: no easter-egg logo variant
|
||||
MultiLineEditBox.updateWidgetNarration skip:other narration text; no narrator in Horizon
|
||||
MultiLineEditBox.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's edit-box arm: gui.narrate.editBox(message, value), the two things MultiLineEditBox adds; books and dialogs record their multi-line boxes as Narratable::edit_box
|
||||
MultiLineEditBox.onClick port crates/horizon-client-render/src/screen_draw.rs::TextField::click click places the cursor; gap: minor: no double-click word select
|
||||
MultiLineEditBox.onDrag port crates/horizon-client-render/src/multiline_edit.rs::MultiLineEdit::drag the selection follows the pointer, or the held scroll bar does
|
||||
MultiLineEditBox.charTyped port crates/horizon-client-render/src/screen_draw.rs::TextField::insert_text typed text replaces the selection or goes at the cursor
|
||||
|
||||
|
@@ -94,7 +94,7 @@ OversizedItemRenderer.textureIsReadyToBlit skip:other cache check for the pictu
|
||||
PictureInPictureRenderer.blitTexture skip:other picture-in-picture texture blit; Horizon draws each preview into the batch directly (draw_player_preview, draw_banner_result)
|
||||
PictureInPictureRenderer.prepareTexturesAndProjection skip:other GPU texture allocation for a picture-in-picture
|
||||
PictureInPictureRenderer.close skip:other GPU texture release
|
||||
AccessibilityOnboardingScreen.init port crates/horizon-client/src/title/onboarding.rs::Title::onboarding_buttons gap: minor: the Narrator button stays inactive and reads Not Available (no narrator output)
|
||||
AccessibilityOnboardingScreen.init port crates/horizon-client/src/title/onboarding.rs::Title::onboarding_buttons gap: minor: the Narrator button is drawn disabled and labelled Narrator: Not Available where vanilla builds it from Options.narrator's own button and enables it while the narrator can speak, so the narrator cannot be turned on here; handleInitialNarrationDelay's accessibility.onboarding.screen.narrator line is not said
|
||||
AccessibilityOnboardingScreen.setInitialFocus missing minor: the onboarding screen itself is ported (title/onboarding.rs); the focus starting on the Narrator button is not
|
||||
AccessibilityOnboardingScreen.closeAndSetScreen port crates/horizon-client/src/title.rs::Title::click_action
|
||||
AccessibilityOnboardingScreen.extractRenderState port crates/horizon-client/src/title/onboarding.rs::Title::draw_onboarding
|
||||
|
||||
|
@@ -17,8 +17,8 @@ WorldOptionsScreen.extractMenuBackground port crates/horizon-client/src/game/lan
|
||||
WorldOptionsScreen.extractRenderState port crates/horizon-client/src/game/lan_screen.rs::Game::draw_options_view header and footer separators and the widgets
|
||||
WorldOptionsScreen.onGamemasterPermissionChanged port crates/horizon-client/src/game/lan_screen.rs::Game::remote_world_options_permission losing permission on a server closes the screen; gap: minor: the default and personal modes are not reset as updatePermissionDependentButtons does
|
||||
WorldOptionsScreen.updatePermissionDependentButtons inline crates/horizon-client/src/game/lan_screen.rs::Game::world_options_click the Cheats arm resets default and personal mode to the saved default when commands turn off; gap: minor: the remote permission path does not do this
|
||||
WorldOptionsScreen.updatePersonalGameModeButton missing minor: a personal mode changed while the options are open is not shown; Horizon reads the modes once when the screen opens
|
||||
WorldOptionsScreen.onDefaultGameModeChanged missing minor: a default mode changed while the options are open is not shown; Horizon reads the modes once when the screen opens
|
||||
WorldOptionsScreen.updatePersonalGameModeButton inline crates/horizon-client/src/game/lan_screen.rs::WorldOptions::buttons the personal mode button is rebuilt from the live personal mode every frame and labelled in WorldOptions::label, so a mode changed while the screen is open shows without a callback
|
||||
WorldOptionsScreen.onDefaultGameModeChanged inline crates/horizon-client/src/game/lan_screen.rs::WorldOptions::buttons the default mode button is rebuilt from the live default mode every frame and labelled in WorldOptions::label, so a default changed while the screen is open shows without a callback
|
||||
WorldOptionsScreen.hasSettingsChanges inline crates/horizon-client/src/game/lan_screen.rs::WorldOptions::changed compares every setting against the values read at open
|
||||
WorldOptionsScreen.lanPortChanged inline crates/horizon-client/src/game/lan_screen.rs::WorldOptions::snapshot the port is part of the snapshot only while LAN is on
|
||||
WorldOptionsScreen.changeMultiplayerScope inline crates/horizon-client/src/game/lan_screen.rs::Game::apply_world_options closes LAN and reopens it on the new port when the scope or port changed
|
||||
@@ -30,14 +30,14 @@ WorldOptionsScreen.DifficultyButtons.create inline crates/horizon-client/src/gam
|
||||
WorldOptionsScreen.DifficultyButtons.refresh port crates/horizon-client/src/game/lan_screen.rs::WorldOptions::server_difficulty a server's difficulty and lock update the screen; gap: minor: it also resets the baseline, so Apply no longer sees the change
|
||||
WorldOptionsScreen.DifficultyButtons.isDifficultyLocked inline crates/horizon-client/src/game/lan_screen.rs::Game::open_world_options locked when the level is locked or hardcore; the lock button's enabled state is in WorldOptions::active
|
||||
StatsScreen.onStatsUpdated inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats the lists are rebuilt from the stored values on every draw; the AwardStats arm in remote.rs only stores them
|
||||
StatsScreen.setTabActiveStateAndTooltip missing player: an empty Items or Mobs tab stays selectable with no 'No statistics found' tooltip
|
||||
StatsScreen.setTabActiveStateAndTooltip port crates/horizon-client/src/game/stats_screen.rs::stats_tab_active the Items and Mobs tabs are selectable only with rows; hovering an empty tab draws its gui.stats.none_found tooltip (split at 170) in Game::draw_stats
|
||||
StatsScreen.repositionElements skip:ui layout only: tab bar placement and header height
|
||||
StatsScreen.keyPressed missing minor: no keyboard tab switching on the statistics screen; Escape still closes it
|
||||
StatsScreen.extractRenderState inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats footer separator is drawn with the tab bar in draw_stats
|
||||
StatsScreen.extractMenuBackground inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats background drawn at the start of draw_stats
|
||||
StatsScreen.GeneralStatisticsList.Entry.getValueText port crates/horizon-client/src/game/stats_screen.rs::format value text by the stat's format (time, distance, tenths, plain)
|
||||
StatsScreen.GeneralStatisticsList.Entry.extractContent port crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats General rows: name left, value right
|
||||
StatsScreen.GeneralStatisticsList.Entry.getNarration skip:other narration text for screen readers; Horizon has no narrator output
|
||||
StatsScreen.GeneralStatisticsList.Entry.getNarration inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats narrator.select(<label> <value>) built as the general list's hovered row text
|
||||
StatsScreen.ItemStatisticsList.<init> port crates/horizon-client/src/game/stats_screen.rs::Game::stat_items items with a non-zero count in any column, block items included
|
||||
StatsScreen.ItemStatisticsList.getColumn inline crates/horizon-client/src/game/stats_screen.rs::Game::stat_items the column index selects COLUMNS directly
|
||||
StatsScreen.ItemStatisticsList.getColumnIndex inline crates/horizon-client/src/game/stats_screen.rs::Game::stats_click the sort state keeps the column index, so no reverse lookup is needed
|
||||
@@ -49,10 +49,10 @@ StatsScreen.ItemStatisticsList.HeaderEntry.StatSortButton.extractContents inline
|
||||
StatsScreen.ItemStatisticsList.ItemRow.extractContent port crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats item slot and the block and item stat cells per row
|
||||
StatsScreen.ItemStatisticsList.ItemRow.extractStat inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats cell value right-aligned in its column
|
||||
StatsScreen.ItemStatisticsList.ItemRow.ItemRowWidget.extractWidgetRenderState inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats slot background and item icon
|
||||
StatsScreen.ItemStatisticsList.ItemRow.ItemRowWidget.extractTooltip missing player: hovering an item in the Items tab shows no item tooltip
|
||||
StatsScreen.ItemStatisticsList.ItemRow.ItemRowWidget.extractTooltip port crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats the hovered item row draws its stack tooltip at the slot's corner (draw_stack_tooltip)
|
||||
StatsScreen.ItemStatisticsList.ItemRowComparator.compare inline crates/horizon-client/src/game/stats_screen.rs::Game::stat_items orders by the sorted column; gap: minor: non-block items count as 0 in block columns (vanilla -1), and ties are not broken by item id
|
||||
StatsScreen.MobsStatisticsList.MobRow.extractContent port crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats mob name, kills and killed-by lines
|
||||
StatsScreen.MobsStatisticsList.MobRow.getNarration skip:other narration text for screen readers; Horizon has no narrator output
|
||||
StatsScreen.MobsStatisticsList.MobRow.getNarration inline crates/horizon-client/src/game/stats_screen.rs::Game::draw_stats narrator.select(joinForNarration(kills, killed by)) built as the mobs list's hovered row text
|
||||
StatsScreen.StatisticsTab.doLayout skip:ui layout only: list size and position
|
||||
AdvancementTab.copyPosition inline crates/horizon-client/src/game/advancements_screen.rs::Game::adv_cache a rebuilt tree keeps adv_ui.scroll; tab bounds are recomputed in adv_view
|
||||
AdvancementTab.extractTab port crates/horizon-client/src/game/advancements_screen.rs::Game::draw_advancements tab sprite per position (first, middle, last) and selected state
|
||||
@@ -94,16 +94,16 @@ AdvancementsScreen.extractWindow port crates/horizon-client/src/game/advancement
|
||||
AdvancementsScreen.extractTooltips port crates/horizon-client/src/game/advancements_screen.rs::Game::draw_advancements tab title tooltips; the card tooltip comes from adv_draw_hover
|
||||
AdvancementsScreen.onAdvancementsUpdated port crates/horizon-client/src/game/advancements_screen.rs::Game::adv_cache a changed tree rebuilds the positions; tabs and progress are read in adv_view and at draw time
|
||||
AdvancementsScreen.getAdvancementWidget skip:java lookup of a widget by node; Horizon indexes positions by tree index
|
||||
DebugOptionsScreen.init missing minor: no F3+F6 debug entry editor; the F3 overlay footer still says 'To edit: press [F3+F6]' (debug_overlay.rs)
|
||||
DebugOptionsScreen.addProfileButton missing minor: no debug profile buttons (default and performance)
|
||||
DebugOptionsScreen.repositionElements missing minor: layout of the missing debug entry editor
|
||||
DebugOptionsScreen.CategoryEntry.extractContent missing minor: category headings of the missing debug entry editor
|
||||
DebugOptionsScreen.OptionEntry.<init> missing minor: per-entry always, overlay and never buttons of the missing editor
|
||||
DebugOptionsScreen.init port crates/horizon-client/src/game/debug_options.rs::Game::debug_options_header init's vertical layout (HEADER 61, FOOTER 33, the title row and warning), the search box and scroll made in Game::toggle_debug_options, the footer in footer()
|
||||
DebugOptionsScreen.addProfileButton port crates/horizon-client/src/game/debug_options.rs::footer the two profile buttons (Default, Performance) are the first two footer buttons; clicking one loads that profile in Game::debug_options_click
|
||||
DebugOptionsScreen.repositionElements port crates/horizon-client/src/game/debug_options.rs::Game::draw_debug_options the header, the list between HEADER and h - FOOTER and the footer placed from the screen size each frame
|
||||
DebugOptionsScreen.CategoryEntry.extractContent port crates/horizon-client/src/game/debug_options.rs::rows a Row::Category before each category's entries, drawn as the heading row by Game::draw_debug_options
|
||||
DebugOptionsScreen.OptionEntry.<init> port crates/horizon-client/src/game/debug_options.rs::button_xs the three 60-wide Off / In Overlay / Always buttons of an entry row at their content offsets
|
||||
DebugOptionsScreen.OptionEntry.narrateButton skip:other narration text for screen readers
|
||||
DebugOptionsScreen.OptionEntry.setValue missing minor: sets an entry's status in the missing editor
|
||||
DebugOptionsScreen.OptionEntry.extractContent missing minor: draws the entry row of the missing editor
|
||||
DebugOptionsScreen.OptionEntry.refreshEntry missing minor: refreshes the buttons of the missing editor
|
||||
DebugOptionsScreen.OptionList.updateSearch missing minor: search filter of the missing debug entry editor
|
||||
DebugOptionsScreen.OptionEntry.setValue port crates/horizon-client/src/game/debug_options.rs::Game::debug_options_click a press on a status button sets it through debug_entries.set_status, with the click sound
|
||||
DebugOptionsScreen.OptionEntry.extractContent port crates/horizon-client/src/game/debug_options.rs::Game::draw_debug_options the entry's path and its three status buttons, the current one highlighted
|
||||
DebugOptionsScreen.OptionEntry.refreshEntry port crates/horizon-client/src/game/debug_options.rs::Game::draw_debug_options the row is redrawn from debug_entries.status every frame, so set_status needs no refresh
|
||||
DebugOptionsScreen.OptionList.updateSearch port crates/horizon-client/src/game/debug_options.rs::rows the list is rebuilt from debug_entries::search(search box) on every draw, click and scroll
|
||||
GameModeSwitcherScreen.getDefaultSelected port crates/horizon-client/src/game_mode_switcher.rs::GameModeSwitcher::new previous mode, else the opposite of the current one
|
||||
GameModeSwitcherScreen.init port crates/horizon-client/src/game/gamemode_switcher.rs::Game::open_gamemode_switcher opens with the selection state; slot positions are computed in draw
|
||||
GameModeSwitcherScreen.extractRenderState port crates/horizon-client/src/game/gamemode_switcher.rs::Game::draw_gamemode_switcher title, help line, slots, selection and hover
|
||||
@@ -123,7 +123,7 @@ DialogControlSet.addInput port crates/horizon-client/src/dialog_screen.rs::input
|
||||
DialogControlSet.createDialogButton port crates/horizon-client/src/dialog_screen.rs::Layout::new button width from the dialog; gap: minor: no button tooltips
|
||||
DialogControlSet.bindAction port crates/horizon-client/src/dialog.rs::Action::click reads the inputs' current values into the action when clicked
|
||||
DialogControlSet.createActionButton port crates/horizon-client/src/game/dialogs.rs::Game::dialog_click button press runs the action through run_dialog_action
|
||||
DialogListDialogScreen.createDialogClickAction missing player: a dialog list shows no entry buttons; only its exit button is drawn
|
||||
DialogListDialogScreen.createDialogClickAction port crates/horizon-client/src/dialog.rs::Dialog::set_list each listed dialog is a button whose action is Click::ShowDialog; game/dialogs.rs run_dialog_action opens it
|
||||
DialogScreen.repositionElements skip:ui layout only: body scroll height and warning clamp, both in Layout::new
|
||||
DialogScreen.createTitleWithWarningButton skip:ui layout only: title row, warning button 10 px right of the title in Layout::new
|
||||
DialogScreen.makeSureWarningButtonIsInBounds port crates/horizon-client/src/dialog_screen.rs::Layout::in_bounds moves the warning button on screen when it is off
|
||||
@@ -138,12 +138,12 @@ WaitingForResponseScreen.init port crates/horizon-client/src/dialog_screen.rs::w
|
||||
WaitingForResponseScreen.tick port crates/horizon-client/src/dialog_screen.rs::waiting_button Back shows after a second with a countdown label, works after five seconds
|
||||
DialogBodyHandlers.createBodyElement port crates/horizon-client/src/dialog_screen.rs::Layout::new gap: player: item bodies are dropped (Body::Item gives no element)
|
||||
DialogBodyHandlers.bootstrap skip:data registers body handlers
|
||||
DialogBodyHandlers.runActionOnParent missing player: clicking text in a dialog message or item description does nothing; dialog_click only tests fields, checkboxes and buttons
|
||||
DialogBodyHandlers.ItemHandler.createControls missing player: an item body (icon and description) is not drawn in a dialog
|
||||
DialogBodyHandlers.runActionOnParent port crates/horizon-client/src/game/dialogs.rs::Game::dialog_click a press on a message or description line reads the hovered style (dialog_screen::line_style_at) and runs its click event
|
||||
DialogBodyHandlers.ItemHandler.createControls port crates/horizon-client/src/dialog_screen.rs::item the item widget with its description 2 to the right, centred on each other vertically
|
||||
DialogBodyHandlers.PlainMessageHandler.createControls port crates/horizon-client/src/dialog_screen.rs::message centred wrapped text; gap: player: text clicks do nothing
|
||||
InputControlHandlers.createHandler port crates/horizon-client/src/dialog_screen.rs::input dispatch by control type; unknown types are dropped
|
||||
InputControlHandlers.bootstrap skip:data registers input handlers
|
||||
InputControlHandlers.BooleanHandler.addControl port crates/horizon-client/src/dialog_screen.rs::input checkbox with its label; toggled in dialog_click
|
||||
InputControlHandlers.NumberRangeHandler.addControl missing player: a number-range input (slider) in a dialog has no control
|
||||
InputControlHandlers.SingleOptionHandler.addControl missing player: a single-option input in a dialog has no control
|
||||
InputControlHandlers.NumberRangeHandler.addControl port crates/horizon-client/src/dialog_screen.rs::input Control::NumberRange lays out a 20 high Part::Slider of the input's width
|
||||
InputControlHandlers.SingleOptionHandler.addControl port crates/horizon-client/src/dialog_screen.rs::input Control::SingleOption lays out a 20 high Part::Cycle of the input's width
|
||||
InputControlHandlers.TextInputHandler.addControl port crates/horizon-client/src/dialog_screen.rs::input gap: player: multiline inputs are drawn as one 20 px line and the line limit is not used
|
||||
|
@@ -8,13 +8,13 @@ WorldSelectionList.filterAccepts port crates/horizon-client/src/title.rs::Title:
|
||||
WorldSelectionList.handleLevelLoadFailure inline crates/horizon-client/src/title.rs::Title::failed gap: minor: list_worlds never fails, so the Unable to load screen never shows
|
||||
WorldSelectionList.setSelected inline crates/horizon-client/src/title.rs::Title::click_action selection is set on the row click path and cleared by search edits
|
||||
WorldSelectionList.getSelectedOpt inline crates/horizon-client/src/title.rs::Title::click_action the selected world is looked up by index in the Select arms
|
||||
WorldSelectionList.updateWidgetNarration skip:ui narration only; Horizon has no narrator output
|
||||
WorldSelectionList.updateWidgetNarration inline crates/horizon-client/src/screen_narrator.rs::narrate narrate's list arm: the row under the mouse, else the selected one, with narrator.position.list; the list's LoadingHeader row has no counterpart
|
||||
WorldSelectionList.Builder.build skip:java builder for the list constructor
|
||||
WorldSelectionList.LoadingHeader.extractContent skip:other saves are read at once, so the loading header is never shown
|
||||
WorldSelectionList.NoWorldsEntry.extractContent skip:service empty entry of the Realms world upload list only
|
||||
WorldSelectionList.WorldListEntry.<init> port crates/horizon-client/src/title.rs::Title::draw gap: minor: no hover tooltip on overflowing name, folder or info text; the name, folder and date, and mode and version lines are drawn
|
||||
WorldSelectionList.WorldListEntry.validateIconFile port crates/horizon-client/src/title.rs::Title::icon gap: minor: no symlink check; an icon that is not a decodable 64x64 image shows the unknown-server icon
|
||||
WorldSelectionList.WorldListEntry.getNarration skip:ui narration text only; Horizon has no narrator output
|
||||
WorldSelectionList.WorldListEntry.getNarration port crates/horizon-client/src/title.rs::world_narration narrator.select.world_info(name, last played, info) joined for narration with selectWorld.locked when the world is locked, then narrator.select(...); gap: minor: a world with experimental settings has no flag, so vanilla's selectWorld.experimental is not joined
|
||||
WorldSelectionList.WorldListEntry.keyPressed port crates/horizon-client/src/title.rs::Title::join_selected the selection key joins the selected world as a click does; Enter and Space reach it when the list has focus
|
||||
WorldSelectionList.WorldListEntry.canInteract port crates/horizon-client/src/title.rs::WorldEntry::can_play LevelSummary.primaryActionActive: a locked or incompatible world does not join from a click or a key, and its icon shows the error mark instead of the join arrow
|
||||
WorldSelectionList.WorldListEntry.joinWorld port crates/horizon-client/src/title.rs::Title::click_action gap: minor: no warning for a symlinked world before it opens
|
||||
|
||||
|
+14
-14
@@ -81,16 +81,16 @@ ServerLevel.areEntitiesActuallyLoadedAndTicking skip:debug only game tests call
|
||||
ServerLevel.anyPlayerCloseEnoughForSpawning port crates/horizon-client/src/game/natural_spawning.rs::close_enough_for_spawning
|
||||
ServerLevel.fillReportDetails skip:debug crash report detail
|
||||
ServerLevel.EntityCallbacks.onCreated inline crates/horizon-client/src/lan/waypoints.rs::Waypoints::track players are the only waypoint transmitters Horizon has
|
||||
ServerLevel.EntityCallbacks.onDestroyed inline crates/horizon-client/src/lan/waypoints.rs::Waypoints::untrack gap: minor: dead non-player entities keep their scores and team membership (vanilla Scoreboard.entityRemoved clears them), so a sidebar can keep listing a dead mob
|
||||
ServerLevel.EntityCallbacks.onDestroyed inline crates/horizon-client/src/lan/waypoints.rs::Waypoints::untrack a dead non-player entity also runs Scoreboard.entityRemoved (game/scoreboard.rs::score_entity_removed: its scores are reset and it leaves its team)
|
||||
ServerLevel.EntityCallbacks.onTrackingStart inline crates/horizon-client/src/lan/entity.rs::Entities::tick an entity is tracked the first tick the level lists it; guests, waypoints and the sleep list are polled each tick, and there are no separate dragon part entities
|
||||
ServerLevel.EntityCallbacks.onTrackingEnd inline crates/horizon-client/src/lan/entity.rs::Entities::tick an entity the level stops listing is removed from every viewer (RemoveEntities)
|
||||
ServerPlayer.<init> port crates/horizon-client/src/lan/guest.rs::Guest::new
|
||||
ServerPlayer.readAdditionalSaveData port crates/horizon-client/src/save.rs::Level::read_player gap: minor: entered_nether_pos, last_explosion_impact_pos, spawn_extra_particles_on_fall, post_effects and previousPlayerGameType are not read back (kept verbatim in player_extra); recipe book, respawn, shoulders, warden tracker and raid omen are read
|
||||
ServerPlayer.addAdditionalSaveData port crates/horizon-client/src/save.rs::Level::player_tag gap: minor: writes only what it reads; the keys above come from the loaded file unchanged
|
||||
ServerPlayer.readAdditionalSaveData port crates/horizon-client/src/save.rs::Level::read_player gap: minor: entered_nether_pos, last_explosion_impact_pos and spawn_extra_particles_on_fall are not read back (kept verbatim in player_extra); post_effects, previousPlayerGameType, the recipe book, respawn, shoulders, warden tracker and raid omen are read
|
||||
ServerPlayer.addAdditionalSaveData port crates/horizon-client/src/save.rs::Level::player_tag gap: minor: writes only what it reads; the keys still listed above come from the loaded file unchanged
|
||||
ServerPlayer.saveParentVehicle port crates/horizon-client/src/save.rs::Level::player_tag the RootVehicle {Attach, Entity} tree goes in the player compound (lan/playerdata.rs::store for a guest), so the ride comes back on the next login
|
||||
ServerPlayer.loadAndSpawnParentVehicle port crates/horizon-client/src/game/persist.rs::Game::restore_saved_vehicle the mount is spawned from RootVehicle.Entity and the player is put back on it (`riding`)
|
||||
ServerPlayer.saveEnderPearls missing minor: a thrown ender pearl is not saved at all, so one in flight or hanging in a stasis chamber is gone after a reload
|
||||
ServerPlayer.loadAndSpawnEnderPearl missing minor: ender pearls are not loaded back (spawn_loaded_entities has no pearl)
|
||||
ServerPlayer.saveEnderPearls inline crates/horizon-client/src/game/persist.rs::Game::entity_chunks a thrown pearl is saved with its chunk as an ordinary entity (entity_nbt::throwable_to_nbt), not in the player file; gap: minor: a pearl in a chunk that never saves, a stasis chamber's, is not kept
|
||||
ServerPlayer.loadAndSpawnEnderPearl inline crates/horizon-client/src/game/persist.rs::Game::spawn_loaded_entities entity_nbt::throwable_from_nbt spawns a saved pearl back, in the chunk's own level; there is no per-player list to read
|
||||
ServerPlayer.setExperiencePoints port crates/horizon-client/src/game/commands.rs::Game::change_experience /xp set points
|
||||
ServerPlayer.setExperienceLevels port crates/horizon-client/src/game/commands.rs::Game::change_experience /xp set levels
|
||||
ServerPlayer.onLeaveCombat skip:other the client ignores ClientboundPlayerCombatEnd
|
||||
@@ -102,11 +102,11 @@ ServerPlayer.updateScoreForCriteria port crates/horizon-client/src/game/scoreboa
|
||||
ServerPlayer.tellNeutralMobsThatIDied port crates/horizon-client/src/game/creatures.rs::Game::tell_neutral_mobs_player_died mobs within 32 blocks across and 10 up and down forgive a dead player when the rule is on
|
||||
ServerPlayer.handleTeamKill inline crates/horizon-client/src/game/scoreboard.rs::Game::score_player_killed teamkill and killedByTeam objectives
|
||||
ServerPlayer.hurtServer port crates/horizon-client/src/game/lan_pvp.rs::Game::pvp_land pvp rule and team friendly fire gate the damage
|
||||
ServerPlayer.addPostEffect port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect gap: minor: one list shared by every target, nothing is sent to guests (an empty list at join) and no post shader is drawn
|
||||
ServerPlayer.clearPostEffects port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect gap: minor: same as addPostEffect
|
||||
ServerPlayer.removePostEffect port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect gap: minor: same as addPostEffect
|
||||
ServerPlayer.addPostEffect port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect each target keeps its own list (change_post_effects: the player's here, a guest's on its record); the client builds its post chain from the player's, and a guest's is sent when it changes (Hub::send_post_effects)
|
||||
ServerPlayer.clearPostEffects port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect the same per-target lists; clearing empties the target's
|
||||
ServerPlayer.removePostEffect port crates/horizon-client/src/game/commands/extra.rs::Game::cmd_posteffect the same per-target lists; removing takes the one effect out
|
||||
ServerPlayer.forceSetRotation inline crates/horizon-client/src/game/commands/world_cmds.rs::Game::cmd_rotate /rotate turns a guest through a teleport packet with the new rotation
|
||||
ServerPlayer.triggerDimensionChangeTriggers port crates/horizon-client/src/game/advancements.rs::Game::trigger_dimension gap: player: nether_travel is never triggered (entered_nether_pos is not kept), so the Subspace Bubble advancement can never be earned
|
||||
ServerPlayer.triggerDimensionChangeTriggers port crates/horizon-client/src/game/advancements.rs::Game::trigger_dimension nether_travel fires on the way back to the Overworld from the position the Nether was entered at (adv.marks.nether); gap: minor: that position is not restored from entered_nether_pos after a reload
|
||||
ServerPlayer.broadcastToPlayer port crates/horizon-client/src/lan/entity.rs::broadcast_to_player a spectator viewer sees a player only while its camera is that player; anyone else never sees a spectator
|
||||
ServerPlayer.startSleeping port crates/horizon-client/src/game.rs::Game::try_sleep
|
||||
ServerPlayer.isReachableBedBlock inline crates/horizon-client/src/game.rs::Game::try_sleep the reachable closure: 3 blocks sideways, 2 vertically
|
||||
@@ -119,8 +119,8 @@ ServerPlayer.awardStat port crates/horizon-client/src/game/stats.rs::Stats::add
|
||||
ServerPlayer.resetStat port crates/horizon-client/src/game/stats.rs::Stats::reset
|
||||
ServerPlayer.disconnect inline crates/horizon-client/src/game/lan.rs::Game::tick_lan HostEvent::Left: the guest is saved and removed; its mount just loses its rider (no eject or forced wake)
|
||||
ServerPlayer.transferInventoryXpAndScore inline crates/horizon-client/src/game/screens.rs::Game::respawn_player keep_inventory keeps the inventory and Experience::respawn keeps xp
|
||||
ServerPlayer.onEffectUpdated port crates/horizon-client/src/lan/hub.rs::Hub::sync_effects gap: player: the effects_changed trigger does not exist, so How Did We Get Here? and A Furious Cocktail can never be earned
|
||||
ServerPlayer.onEffectsRemoved port crates/horizon-client/src/lan/hub.rs::Hub::sync_effects gap: player: same missing effects_changed trigger
|
||||
ServerPlayer.onEffectUpdated port crates/horizon-client/src/lan/hub.rs::Hub::sync_effects the effects_changed trigger exists (advancements.rs::Game::trigger_effects_changed, from the end-of-tick comparison of the effect list); gap: minor: that comparison reads the host player's list, while this path only sends a guest its effects
|
||||
ServerPlayer.onEffectsRemoved port crates/horizon-client/src/lan/hub.rs::Hub::sync_effects same effect comparison and trigger as onEffectUpdated
|
||||
ServerPlayer.magicCrit port crates/horizon-client/src/lan/containers.rs::Hub::critical_hit
|
||||
ServerPlayer.onUpdateAbilities inline crates/horizon-client/src/lan/hub.rs::Hub::set_game_mode abilities go out with a game mode change; there is no other way abilities change
|
||||
ServerPlayer.createCommandSourceStack inline crates/horizon-client/src/game/lan_actions.rs::Game::run_guest_command the guest is swapped in as the acting player and its permission level applied
|
||||
@@ -133,14 +133,14 @@ ServerPlayer.sendServerStatus port crates/horizon-client/src/lan/hub.rs::Hub::pl
|
||||
ServerPlayer.updateInvisibilityStatus inline crates/horizon-client/src/game/lan.rs::Game::lan_host_state
|
||||
ServerPlayer.drop port crates/horizon-client/src/game.rs::Game::player_drop item_dropped and drop statistics, thrower set
|
||||
ServerPlayer.calculateGameModeForNewPlayer port crates/horizon-client/src/game/lan.rs::Game::lan_guest_joined default or forced game mode for a new or force-gamemode guest
|
||||
ServerPlayer.storeGameTypes port crates/horizon-client/src/save.rs::Level::player_tag gap: minor: playerGameType only; previousPlayerGameType is not saved, so the game mode switcher forgets the previous mode after a reload
|
||||
ServerPlayer.storeGameTypes port crates/horizon-client/src/save.rs::Level::player_tag both are saved: playerGameType, and previousPlayerGameType (absent when unset, as storeNullable is), read back into previous_game_mode
|
||||
ServerPlayer.shouldFilterMessageTo skip:service text filtering
|
||||
ServerPlayer.mayInteract inline crates/horizon-client/src/game/lan_actions.rs::Game::under_spawn_protection gap: minor: same as ServerLevel.mayInteract, no world border check
|
||||
ServerPlayer.onItemPickup port crates/horizon-client/src/game/advancements.rs::Game::trigger_thrown_picked_up_by_player a taken stack whose owner is another player fires thrown_item_picked_up_by_player, whole or partial
|
||||
ServerPlayer.getChatSession skip:java getter with an expiry check
|
||||
ServerPlayer.startRiding inline crates/horizon-client/src/game/lan_entities.rs::Game::lan_riding gap: minor: SetPassengers goes out, but the mount's active effects (a horse's speed) are not sent to the rider
|
||||
ServerPlayer.removeVehicle inline crates/horizon-client/src/game/lan_entities.rs::Game::lan_riding gap: minor: SetPassengers updates, vehicle effects are not removed from the rider
|
||||
ServerPlayer.getKnownSpeed port crates/horizon-client/src/game/spear.rs::Game::known_player_movement gap: minor: ignores the vehicle's speed for a rider who is not steering
|
||||
ServerPlayer.getKnownSpeed port crates/horizon-client/src/game/spear.rs::Game::known_player_movement a rider's speed is its root vehicle's (mob_speed walks up the mounts); a guest's is the movement it last reported
|
||||
ServerPlayer.onEquippedItemBroken port crates/horizon-client/src/game.rs::Game::damage_held gap: minor: only the held item counts toward the broken statistic; breaking armour is not counted
|
||||
ServerPlayer.registerAndUpdateEnderPearlTicket missing minor: a thrown ender pearl does not keep its chunk loaded; none are saved either
|
||||
ServerPlayer.registerAndUpdateEnderPearlTicket missing minor: a thrown ender pearl holds no chunk of its own (no ENDER_PEARL ticket); it is saved only with a chunk that saves, so one in an unloaded chunk is gone
|
||||
ServerPlayer.debugSubscriptions skip:debug debug subscriptions for the debug screen
|
||||
|
@@ -1,6 +1,6 @@
|
||||
ServerPlayerGameMode.changeGameModeForPlayer port crates/horizon-client/src/game/commands.rs::Game::set_game_mode same-mode check, mode switch, abilities; a LAN guest goes through Hub::set_game_mode which also broadcasts PlayerInfo UPDATE_GAME_MODE
|
||||
ServerPlayerGameMode.setGameModeForPlayer port crates/horizon-client/src/game/game_mode.rs::Game::set_mode previous mode kept, GameType.updatePlayerAbilities applied
|
||||
ServerPlayerGameMode.isInRangeOfGround missing minor: spectator to creative near the ground keeps flying (set_mode always sets flying); vanilla stops flying within 1 block of the ground
|
||||
ServerPlayerGameMode.isInRangeOfGround port crates/horizon-world/src/world_movement.rs::in_range_of_ground the body and the block under it are free of colliders, so a game mode change to spectator stops flying when the player stands on the ground (game/game_mode.rs set_mode, lan/hub.rs); entity colliders stay out
|
||||
ServerPlayerGameMode.incrementDestroyProgress inline crates/horizon-client/src/game/lan_actions.rs::Game::guest_dig_feedback gap: minor: crack stage is the client formula (progress*10 - 1), so other players' cracks on a guest's block run one stage behind the server value
|
||||
ServerPlayerGameMode.debugLogging skip:debug DEBUG_BLOCK_BREAK logging
|
||||
ServerPlayerGameMode.abortDestroyBlock inline crates/horizon-client/src/game/lan_actions.rs::Game::lan_guest_packet the abort action clears the guest's crack for everyone; no separate check of a mismatched destroy position
|
||||
@@ -23,8 +23,8 @@ ThreadedLevelLightEngine.waitForPendingTasks skip:java future that completes wh
|
||||
ThrottlingChunkTaskDispatcher.popTasks skip:other caps chunk tasks in flight; Horizon schedules chunk work on its own worker pool
|
||||
ThrottlingChunkTaskDispatcher.getDebugStatus skip:debug
|
||||
Ticket.toString skip:debug
|
||||
Ticket.decreaseTicksLeft missing minor: only player and forced tickets exist; timed tickets (ender pearl 40, portal 300, post teleport 5 ticks) are not modelled
|
||||
Ticket.isTimedOut missing minor: no timed tickets, so nothing expires
|
||||
Ticket.decreaseTicksLeft inline crates/horizon-client/src/game/end.rs::Game::keep_gateway_destinations an End portal ticket (300, ThrownEnderpearl.placePortalTicket) counts down once a tick while its pearl waits; the ender pearl 40 and post-teleport 5 tickets are not modelled
|
||||
Ticket.isTimedOut inline crates/horizon-client/src/game/end.rs::Game::keep_gateway_destinations the portal ticket is dropped when its count reaches 0 (vanilla waits for a negative tick); no other ticket type times out
|
||||
WorldGenRegion.<init> port crates/horizon-world/src/worldgen/feature_region.rs::TerrainRegion::new the region is a set of chunks around the centre
|
||||
WorldGenRegion.hasChunk port crates/horizon-world/src/worldgen/feature_region.rs::TerrainRegion::chunk a chunk is there when it is in the region's index, not by the step's dependency distance
|
||||
WorldGenRegion.warnIfReadOutsideWriteZone skip:debug logs an unsafe terrain read
|
||||
@@ -58,7 +58,7 @@ DifficultyInstance.calculateDifficulty port crates/horizon-client/src/mobs/spawn
|
||||
InteractionHand.asArm inline crates/horizon-client/src/mobs/ai.rs::Mob::swing_hand off_hand != main arm left; the player's first person hand does the same in game.rs hand_geometry
|
||||
InteractionResult.Success.heldItemTransformedTo skip:java result builder; Horizon replaces the held item in place where the item is used
|
||||
ItemStackWithSlot.isValidInContainer port crates/horizon-client-core/src/block_entity_nbt.rs::items slots outside 0..size are dropped when items load
|
||||
LockCode.canUnlock missing minor: a lock on a container is kept in the NBT but never checked, so any player opens a command-locked chest
|
||||
LockCode.canUnlock port crates/horizon-client/src/advancements.rs::can_unlock checked when a container opens (game/advancements.rs container_locked_for from lan_actions.rs): a spectator opens any container, otherwise the main hand must match the lock predicate
|
||||
RandomSequences.createSequence port crates/horizon-items/src/random_sequences.rs::create
|
||||
RandomSequences.DirtyMarkingRandomSource.nextInt skip:java marks the saved data dirty on each draw; Horizon saves every sequence
|
||||
RandomSequences.DirtyMarkingRandomSource.equals skip:java wrapper equality
|
||||
|
||||
|
@@ -4,8 +4,8 @@ FireworkRocketEntity.shouldRender port crates/horizon-client/src/game/fireworks.
|
||||
FireworkRocketEntity.onHitEntity port crates/horizon-client/src/game/fireworks.rs::Game::tick_rockets a rocket fired from a crossbow or dispenser tests entity hits in flight and bursts on what it strikes
|
||||
FireworkRocketEntity.onHitBlock inline crates/horizon-client/src/game/fireworks.rs::Game::tick_rockets a block hit ends the angled rocket early and explodes it; vanilla explodes only when it has explosions and skips the block entityInside effect
|
||||
FireworkRocketEntity.dealExplosionDamage port crates/horizon-client/src/game/fireworks.rs::Game::explode_rocket damage 5+2 per explosion; attached target takes the full blast, others within 5 blocks with line of sight
|
||||
FireworkRocketEntity.addAdditionalSaveData missing minor: rocket life, lifetime and item are not written to a save; Horizon does not save flying rockets
|
||||
FireworkRocketEntity.readAdditionalSaveData missing minor: rocket life, lifetime and item are not read back; Horizon does not save flying rockets
|
||||
FireworkRocketEntity.addAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::firework_rocket_to_nbt Life, LifeTime, FireworksItem, ShotAtAngle and HasBeenShot, over `Projectile`'s Owner (only when it is the player) and LeftOwner
|
||||
FireworkRocketEntity.readAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::firework_rocket_from_nbt Life, LifeTime (0 when absent), FireworksItem and ShotAtAngle, with Owner and LeftOwner
|
||||
FireworkRocketEntity.getExplosions port crates/horizon-client/src/game/fireworks.rs::fireworks_of explosion list from the item's fireworks component, empty without one
|
||||
FireworkRocketEntity.calculateHorizontalHurtKnockbackDirection inline crates/horizon-client/src/game/fireworks.rs::Game::explode_rocket knockback direction is the blast point to the target, which the mob damage gets as its from point
|
||||
FishingHook.<init> port crates/horizon-client/src/game/fishing.rs::Game::use_fishing_rod the player cast: start point, velocity with the 0.0103365 triangle, luck and lure from the rod
|
||||
@@ -21,9 +21,9 @@ FishingHook.getPlayerOwner skip:other owner is implicit: the host's hook is sel
|
||||
FishingHook.getAddEntityPacket port crates/horizon-client/src/game/fishing.rs::Hook::track add-entity payload: the owner entity id is the bobber's data field
|
||||
LlamaSpit.onHitEntity port crates/horizon-client/src/game/creatures.rs::Game::projectile_hit spit hit: 1.0 damage with the spit source to a player (mob_hits_player) or a mob
|
||||
Projectile.applyImplicitComponent missing minor: a projectile given a can_break component by its item keeps no break predicate; Horizon applies implicit components only to buckets
|
||||
Projectile.addAdditionalSaveData missing minor: owner, LeftOwner and HasBeenShot are not written; Horizon does not save flying projectiles
|
||||
Projectile.addAdditionalSaveData port crates/horizon-client/src/entity_nbt.rs::put_projectile Owner and LeftOwner only when set, HasBeenShot once it has ticked (a save before the first tick keeps what it loaded)
|
||||
Projectile.ownedBy inline crates/horizon-client/src/projectiles.rs::Projectile::tick the owner is skipped in the target loop until the projectile has left it
|
||||
Projectile.readAdditionalSaveData missing minor: owner, LeftOwner, HasBeenShot and can_break are not read back; Horizon does not save flying projectiles
|
||||
Projectile.readAdditionalSaveData inline crates/horizon-client/src/entity_nbt.rs::throwable_from_nbt no shared reader: every kind's own reader takes Owner, LeftOwner and NoGravity (this one, `fireball_from_nbt`, `arrow_from_nbt`); HasBeenShot is read for arrows only, and no projectile keeps a `can_break` predicate
|
||||
Projectile.restoreFrom missing minor: the owner is not carried over a dimension change; Horizon has no projectile dimension change
|
||||
Projectile.isOutsideOwnerCollisionRange inline crates/horizon-client/src/projectiles.rs::Projectile::tick gap: minor: left_owner tests the owner's box inflated 1.0 at the position only; vanilla sweeps along the motion and checks the owner's passengers too
|
||||
Projectile.getMovementToShoot port crates/horizon-client/src/projectiles.rs::Projectile::shoot direction plus triangle spread 0.0172275 times uncertainty, scaled by power
|
||||
@@ -83,7 +83,7 @@ ThrownTrident.getLoyaltyFromItem port crates/horizon-client/src/game/trident.rs:
|
||||
ThrownTrident.tickDespawn inline crates/horizon-client/src/arrows.rs::Ticker::tick gap: minor: the 1200-tick life limit applies to every trident; the loyalty exemption is not checked
|
||||
AbstractHurtingProjectile.shouldRenderAtSqrDistance skip:ui distance culling for the fireball model; Horizon culls with its own range check
|
||||
AbstractHurtingProjectile.canHitEntity missing minor: no-physics entities are not skipped by the fireball's target search
|
||||
WitherSkull.getBlockExplosionResistance missing minor: a dangerous skull's blast does not cap block resistance at 0.8; the blast call takes no dangerous flag
|
||||
WitherSkull.getBlockExplosionResistance port crates/horizon-client/src/game/explosion.rs::blast_resistance a dangerous skull's blast caps a breakable block's resistance at 0.8; `#wither_immune` blocks keep theirs
|
||||
WitherSkull.onHit port crates/horizon-client/src/game/wither.rs::Game::wither_skull_hit skull hit damage, wither effect, then the blast at the impact point
|
||||
AbstractWindCharge.makeBoundingBox port crates/horizon-client/src/projectiles.rs::ProjectileKind::size gap: minor: gives the width only; the box sits 0.15 below the position in vanilla
|
||||
AbstractWindCharge.canHitEntity missing minor: no filter for end crystals or other wind charges found in the target list; unsure whether the caller excludes them
|
||||
@@ -128,13 +128,13 @@ VariantUtils.readVariant port crates/horizon-client/src/entity_nbt.rs::read_vari
|
||||
ContainerEntity.addChestVehicleSaveData port crates/horizon-client/src/game/minecarts.rs::Minecart::to_nbt writes the cart's items and any loot table
|
||||
ContainerEntity.readChestVehicleSaveData port crates/horizon-client/src/game/minecarts.rs::Minecart::from_nbt reads the cart's items from the save
|
||||
ContainerEntity.chestVehicleDestroyed port crates/horizon-client/src/game/minecarts.rs::Game::hurt_cart a destroyed cart drops its items when entity drops are on
|
||||
ContainerEntity.unpackChestVehicleLootTable missing unsure: Minecart.loot is only read and written with the save and is never set here, so a chest minecart's loot table may never roll into its slots
|
||||
ContainerEntity.unpackChestVehicleLootTable port crates/horizon-client/src/game/minecarts.rs::Game::unpack_cart_loot opening a chest minecart rolls the loot table it still holds, firing `player_generates_container_loot`, and the cart keeps its items from then on
|
||||
ContainerEntity.isChestVehicleEmpty inline crates/horizon-client/src/game/minecarts.rs::Minecart::container_signal the comparator signal reads the slots' emptiness; gap: minor: no separate empty test
|
||||
ContainerEntity.removeChestVehicleItemNoUpdate skip:other slot edits happen on the chest block entity under the cart's key; store_cart_items and close_cart_container copy them back
|
||||
ContainerEntity.setChestVehicleItem skip:other slot edits happen on the chest block entity under the cart's key; store_cart_items and close_cart_container copy them back
|
||||
ContainerEntity.getChestVehicleSlot skip:other slot access happens on the chest block entity under the cart's key; store_cart_items and close_cart_container copy them back
|
||||
DismountHelper.canDismountTo port crates/horizon-client/src/game/respawn_anchor.rs::Game::safe_dismount_location gap: minor: tests the floor and a 1.8 block box for the player, not the passenger's pose box
|
||||
DismountHelper.findCeilingFrom inline crates/horizon-client/src/game/respawn_anchor.rs::Game::safe_dismount_location gap: minor: head room comes from the 1.8 box collision, not a ceiling scan
|
||||
VehicleEntity.ignoreExplosion missing minor: with mobGriefing off a mob's blast still damages carts and boats; the explosion code has no mob-source rule for them
|
||||
VehicleEntity.ignoreExplosion port crates/horizon-client/src/game/entity.rs::Entity::ignores_explosion boats and minecarts sit out a mob's blast when mob griefing is off (the breeze's burst too), and are neither hurt nor pushed
|
||||
VehicleEntity.destroy port crates/horizon-client/src/game/boats.rs::Game::hurt_boat boats drop their item when entity drops are on; a minecart breaks through hurt_cart
|
||||
VehicleEntity.defineSynchedData skip:java hurt time, hurt direction and damage fields; Horizon keeps them on the cart and boat structs
|
||||
|
@@ -76,8 +76,8 @@ LiquidBlock.neighborChanged port crates/horizon-world/src/level/fluids.rs::Sim::
|
||||
LiquidBlock.pickupBlock port crates/horizon-world/src/level/fluids.rs::Sim::pickup_block source blocks only, leaves air and yields the bucket
|
||||
LoomBlock.useWithoutItem port crates/horizon-client/src/game/stations.rs::Game::open_station opens the loom station
|
||||
LoomBlock.getMenuProvider port crates/horizon-client/src/game/stations.rs::Game::open_station the loom menu over the block position
|
||||
Mirror.mirror missing - minor: unsure: integer rotation mirror for 16-step rotations (banners, heads) not found; template transform works on positions only
|
||||
Mirror.getRotation missing - minor: unsure: the 180 degree turn that a mirror implies is not found; template transform applies mirror to positions only
|
||||
Mirror.mirror inline crates/horizon-world/src/worldgen/structure/processor.rs::turn_facing a hanging entity's Facing takes the same axis flips (LEFT_RIGHT swaps north and south, FRONT_BACK west and east) before the rotation; a block state's mirrored result is the exported per-state table (StateTransforms::mirror)
|
||||
Mirror.getRotation inline crates/horizon-world/src/worldgen/structure/processor.rs::turn_facing the 180 degree turn an axis-flipped facing implies is the swap turn_facing makes; for a block state it is already in the exported mirror table
|
||||
MossyCarpetBlock.makeShapes skip:data - collision and outline shapes are precomputed from the data
|
||||
MossyCarpetBlock.getCollisionShape skip:data - collision shape per state comes from the data table
|
||||
MossyCarpetBlock.canSurvive port crates/horizon-world/src/level/survive.rs::Sim::can_survive_class base needs a non-air block below; a topper needs a moss carpet below
|
||||
|
||||
|
@@ -4,7 +4,7 @@ SkullBlockEntity.applyImplicitComponents port crates/horizon-client/src/block_en
|
||||
SkullBlockEntity.collectImplicitComponents port crates/horizon-client/src/block_entity_item.rs::collect per-part component read; the skull's three parts come from the parts table
|
||||
SkullBlockEntity.removeComponentsFromTag inline crates/horizon-client/src/block_entity_item.rs::pick the three keys are removed from the saved NBT inside pick's part loop
|
||||
SpawnerBlockEntity.triggerEvent port crates/horizon-client/src/mobs/spawner.rs::Spawner::client_event event 1 resets the client spawn delay to the minimum; other events return false
|
||||
SpawnerBlockEntity.setEntityData missing minor: an op's spawn egg with an ENTITY_DATA component only sets the mob type on a spawner here (use_spawn_egg_on_spawner); the rest of the egg's entity data is dropped
|
||||
SpawnerBlockEntity.setEntityData port crates/horizon-client/src/mobs/spawner.rs::Spawner::set_entity_data use_spawn_egg_on_spawner passes the egg's entity data, which is merged into the spawner's next data; the BlockUpdated event sets it changed
|
||||
StructureBlockEntity.updateBlockState port crates/horizon-client/src/game/structure_blocks.rs::Game::set_structure_mode the mode is written to the block's mode property too
|
||||
StructureBlockEntity.usedBy port crates/horizon-client/src/game/block_editor.rs::Game::open_block_editor_if_editable a game master's right click opens the structure block screen
|
||||
StructureBlockEntity.setStructureName port crates/horizon-client-render/src/structure_block.rs::StructureBlock::set_structure_name the SET_STRUCTURE_BLOCK packet's name reaches the entity
|
||||
@@ -16,7 +16,7 @@ StructureBlockEntity.placeStructureIfSameSize port crates/horizon-client/src/gam
|
||||
StructureBlockEntity.loadStructureInfo port crates/horizon-client/src/game/structure_blocks.rs::Game::load_structure_info the template's size and author are read back
|
||||
StructureBlockEntity.placeStructure port crates/horizon-client/src/game/structure_blocks.rs::Game::place_structure mirror, rotation, integrity, seed, strict and ignore entities come from the block entity; the redstone path is Game::trigger_structure_block
|
||||
StructureBlockEntity.getStructureTemplate port crates/horizon-world/src/worldgen/structure.rs::StructureResources::template name lookup only; nothing calls it for a structure block
|
||||
StructureBlockEntity.unloadStructure missing minor: no structure block to unload a template from; templates in StructureResources are never dropped
|
||||
StructureBlockEntity.unloadStructure inline crates/horizon-client/src/game/structure_blocks.rs::Game::trigger_structure_block the Corner arm drops the saved template (`structure_templates.remove`), so the next use reads the file
|
||||
StructureBlockEntity.isStructureLoadable port crates/horizon-client/src/game/structure_blocks.rs::Game::structure_loadable the Load button reports whether the template exists
|
||||
StructureBlockEntity.renderMode port crates/horizon-client-render/src/structure_block.rs::StructureBlock::render_mode a creative structure block shows its mode's outline
|
||||
StructureBlockEntity.getRenderableBox port crates/horizon-client-render/src/structure_block.rs::StructureBlock::renderable_box the outline box of SAVE and LOAD modes
|
||||
@@ -92,7 +92,7 @@ TreeGrower.resetSaplings inline crates/horizon-world/src/level/growth.rs::Sim::g
|
||||
TreeGrower.isTwoByTwoSapling inline crates/horizon-world/src/level/growth.rs::Sim::two_by_two all four blocks must be the sapling's own block
|
||||
MovingPistonBlock.destroy missing minor: breaking a moving piston does not remove the extended base piston next to it
|
||||
MovingPistonBlock.useWithoutItem missing minor: a right click on a moving piston with no block entity does not remove it
|
||||
MovingPistonBlock.getDrops missing minor: a moving piston drops nothing; vanilla drops the drops of the block it carries
|
||||
MovingPistonBlock.getDrops port crates/horizon-world/src/level/pistons.rs::dropped_state the block the moving piston carries, or None (vanilla's empty list) when its block entity is gone; drop_resources calls it
|
||||
MovingPistonBlock.getBlockEntity port crates/horizon-world/src/level/pistons.rs::Sim::moving_piston
|
||||
MovingPistonBlock.rotate port crates/horizon-world/src/worldgen/structure.rs::StateTransforms::rotate rotation goes through the table built from block data
|
||||
MovingPistonBlock.createBlockStateDefinition skip:data state properties come from the block data tables
|
||||
@@ -117,8 +117,8 @@ PistonMovingBlockEntity.getYOff port crates/horizon-world/src/piston_shape.rs::M
|
||||
PistonMovingBlockEntity.getZOff port crates/horizon-world/src/piston_shape.rs::MovingPistonState::interpolated_offset the z part of the offset
|
||||
PistonMovingBlockEntity.moveEntityByPiston port crates/horizon-client/src/game/piston_push.rs::Game::move_pushed moves a body along the push with the piston no-clip rule
|
||||
PistonMovingBlockEntity.moveStuckEntities port crates/horizon-client/src/game/piston_push.rs::Game::push_for_piston the honey branch selects sticky passengers after the collided ones
|
||||
PistonMovingBlockEntity.loadAdditional missing minor: moving piston data is not read from the save; moving pistons are not persisted at all
|
||||
PistonMovingBlockEntity.saveAdditional missing minor: moving pistons are not written to the save, so a save taken mid-move leaves no entry for the moving_piston block
|
||||
PistonMovingBlockEntity.loadAdditional port crates/horizon-client/src/game/persist.rs::Game::moving_piston_from_nbt a `minecraft:piston` entity whose block is still a moving piston: blockState, facing, progress, extending and source
|
||||
PistonMovingBlockEntity.saveAdditional port crates/horizon-client/src/game/persist.rs::Game::moving_piston_to_nbt the moving piston of each moving_piston block as a `minecraft:piston` entity in attach_save_data
|
||||
PistonMovingBlockEntity.setLevel skip:data on load an unknown moved block becomes air; Horizon resolves moved states from the block registry
|
||||
PistonStructureResolver.isSticky port crates/horizon-world/src/level/pistons.rs::Sim::is_sticky_piston
|
||||
PistonStructureResolver.canStickToEachOther port crates/horizon-world/src/level/pistons.rs::Sim::can_stick
|
||||
@@ -139,7 +139,7 @@ BlockBehaviour.Properties.ofLegacyCopy skip:java builder copy; values come from
|
||||
BlockBehaviour.Properties.mapColor skip:java builder setter; values come from block data
|
||||
BlockBehaviour.Properties.strength skip:java builder setter; values come from block data
|
||||
BlockBehaviour.Properties.offsetType skip:java builder setter; values come from block data
|
||||
StateHolder.findNextInCollection missing minor: cycling a block property to its next value (the debug stick's cycle) is not in Horizon
|
||||
StateHolder.findNextInCollection port crates/horizon-client/src/game/debug_stick.rs::relative_index the next value in a property's list, wrapping to the first; the debug stick's cycle picks its value with it
|
||||
StateHolder.toString skip:debug string form of a state for logs and debug output
|
||||
StateHolder.valueIndex skip:java index lookup over a fixed array; Horizon keeps properties in a name-keyed map
|
||||
StateHolder.getNullableValue port crates/horizon-world/src/worldgen/structure/legacy.rs::PieceContext::property returns None for a missing property
|
||||
|
||||
|
@@ -75,10 +75,10 @@ WoodlandMansionStructure.generatePieces port crates/horizon-world/src/worldgen/s
|
||||
StructurePlaceSettings.copy skip:java copy of a settings record; Rust clones the struct
|
||||
StructurePlaceSettings.getRandom port crates/horizon-world/src/worldgen/structure/processor.rs::PlaceSettings::with_random shared random, else position-seeded one
|
||||
StructureTemplate.getSize port crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::size rotated size
|
||||
StructureTemplate.fillFromWorld missing minor: saving a template from the world (structure block save); Horizon only reads templates
|
||||
StructureTemplate.fillFromWorld port crates/horizon-client/src/game/structure_blocks.rs::Game::template_from_world every block but structure voids (air too when asked) with its block entity's data, then the entities, for a box at the origin
|
||||
StructureTemplate.addToLists inline crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::from_nbt block classes sorted inside from_nbt
|
||||
StructureTemplate.buildInfoList inline crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::from_nbt full, other, block-entity order inside from_nbt
|
||||
StructureTemplate.fillEntityList missing minor: part of template save (structure block); Horizon only reads entities
|
||||
StructureTemplate.fillEntityList port crates/horizon-client/src/game/structure_blocks.rs::Game::template_entities the entities inside the box at positions relative to its minimum corner, the UUID dropped
|
||||
StructureTemplate.createEntityIgnoreException inline crates/horizon-world/src/worldgen/structure/processor.rs::place_entities entity NBT goes straight to add_entity; no exception catch here
|
||||
StructureTemplate.loadPalette port crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::from_nbt
|
||||
StructureTemplate.newIntegerList skip:java NBT list builder for template save only
|
||||
@@ -86,11 +86,11 @@ StructureTemplate.newDoubleList skip:java NBT list builder for template save on
|
||||
StructureTemplate.getJointType inline crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::jigsaws joint read from NBT, default from block facing inside jigsaws
|
||||
StructureTemplate.JigsawBlockInfo.toString skip:debug
|
||||
StructureTemplate.JigsawBlockInfo.withInfo inline crates/horizon-world/src/worldgen/structure/jigsaw.rs::template_jigsaws moved and rotated jigsaw position and state computed here
|
||||
StructureTemplate.SimplePalette.idFor missing minor: state to palette id mapping for template save only
|
||||
StructureTemplate.SimplePalette.idFor inline crates/horizon-world/src/worldgen/structure/template.rs::save_nbt palette ids handed out in first-use order, a new state appended, inside save_nbt
|
||||
StructureTemplate.SimplePalette.stateFor inline crates/horizon-world/src/worldgen/structure/template.rs::StructureTemplate::from_nbt palette index resolved to states inside from_nbt
|
||||
StructureTemplate.StructureBlockInfo.toString skip:debug
|
||||
StructureTemplateManager.tryLoad port crates/horizon-world/src/worldgen/structure.rs::StructureResources::template load by id from resources
|
||||
StructureTemplateManager.save missing minor: writes a template into the world folder (structure block save); not implemented
|
||||
StructureTemplateManager.save port crates/horizon-client/src/game/structure_blocks.rs::Game::write_template the tree gzipped to the world's generated/<namespace>/structures/<path>.nbt
|
||||
BlendedNoise.computeFbmRange port crates/horizon-core/src/density/terrain_noise.rs::BlendedNoise::range 16 octaves, the only firstOctave vanilla uses
|
||||
BlendedNoise.FbmSet.parityConfigString skip:debug test parity dump
|
||||
NoiseStack.get port crates/horizon-core/src/noise/stack.rs::NoiseStack::get3 weighted layer sum
|
||||
|
||||
|
@@ -2,7 +2,7 @@ AbstractCommandBlockEditScreen.getUsageNarration skip:ui narration text of the
|
||||
AbstractCommandBlockEditScreen.resize skip:ui re-init on window resize; Horizon redraws the screen every frame and keeps the text
|
||||
AbstractCommandBlockEditScreen.updatePreviousOutput port crates/horizon-client/src/game/command_blocks.rs::CommandBlockScreen::show_previous
|
||||
AbstractCommandBlockEditScreen.onDone port crates/horizon-client/src/game/command_blocks.rs::Game::set_command_block sends the packet and clears last output when not tracking; close is close_command_block
|
||||
AbstractCommandBlockEditScreen.mouseScrolled missing no command suggestion list in the command block screen, so no wheel scrolling of suggestions
|
||||
AbstractCommandBlockEditScreen.mouseScrolled port crates/horizon-client/src/game/command_blocks.rs::Game::command_block_scroll the wheel over the command suggestions list scrolls it, as CommandSuggestions.mouseScrolled does
|
||||
AbstractCommandBlockEditScreen.mouseClicked port crates/horizon-client/src/game/command_blocks.rs::Game::command_block_click buttons only; clicking inside the command box does not move the cursor and there are no suggestions to click
|
||||
AbstractCommandBlockEditScreen.extractRenderState port crates/horizon-client/src/game/command_blocks.rs::Game::draw_command_block
|
||||
AbstractContainerScreen.extractRenderState port crates/horizon-client/src/game.rs::Game::draw_inventory contents, carried item, tooltip in vanilla order
|
||||
@@ -10,10 +10,10 @@ AbstractContainerScreen.extractContents inline crates/horizon-client/src/game.rs
|
||||
AbstractContainerScreen.extractCarriedItem port crates/horizon-client/src/game.rs::Game::draw_carried shows what a quick-craft drag leaves in hand
|
||||
AbstractContainerScreen.extractSlots port crates/horizon-client/src/game.rs::Game::draw_inventory_slots
|
||||
AbstractContainerScreen.mouseScrolled port crates/horizon-client/src/game/bundles.rs::Game::bundle_scroll the bundle wheel is the only ItemSlotMouseAction
|
||||
AbstractContainerScreen.extractSlotHighlightBack missing hover highlight is a flat 50% white square on top of the item; vanilla draws the 24x24 slot_highlight_back sprite behind it, and Slot.isHighlightable is not modelled
|
||||
AbstractContainerScreen.extractSlotHighlightFront missing no slot_highlight_front sprite over the item (see extractSlotHighlightBack)
|
||||
AbstractContainerScreen.extractSlotHighlightBack port crates/horizon-client/src/game.rs::Game::draw_slot_highlight the 24x24 container/slot_highlight_back sprite at -4 behind the slots; the crafter's result slot is left out (Slot.isHighlightable)
|
||||
AbstractContainerScreen.extractSlotHighlightFront port crates/horizon-client/src/game.rs::Game::draw_slot_highlight the container/slot_highlight_front sprite over the item; draw_hovered_slot_highlight draws back, then the slots, then front
|
||||
AbstractContainerScreen.extractTooltip port crates/horizon-client/src/game/stations.rs::Game::draw_slot_tooltip skipped while a stack is carried, even over a bundle
|
||||
AbstractContainerScreen.showTooltipWithItemInHand missing hovering a bundle while carrying a stack shows no tooltip; vanilla still shows the bundle contents
|
||||
AbstractContainerScreen.showTooltipWithItemInHand port crates/horizon-client/src/game/stations.rs::Game::tooltip_with_carried with a stack carried only a bundle's contents keep their tooltip (BundleContents.showTooltipWithItemInHand)
|
||||
AbstractContainerScreen.extractFloatingItem port crates/horizon-client/src/game.rs::Game::draw_carried carried stack drawn at cursor minus 8
|
||||
AbstractContainerScreen.extractLabels inline crates/horizon-client/src/game.rs::Game::draw_inventory title and Inventory labels are drawn per screen kind
|
||||
AbstractContainerScreen.recalculateQuickCraftRemaining port crates/horizon-client/src/menu.rs::Menu::quick_craft_preview returns the count left in hand
|
||||
@@ -41,14 +41,14 @@ AbstractRecipeBookScreen.extractSlots port crates/horizon-client/src/game/recipe
|
||||
AbstractRecipeBookScreen.charTyped port crates/horizon-client/src/game/recipe_book.rs::Game::recipe_text
|
||||
AbstractRecipeBookScreen.keyPressed port crates/horizon-client/src/game/recipe_book.rs::Game::recipe_key
|
||||
AbstractRecipeBookScreen.isInputCaptured port crates/horizon-client/src/game/recipe_book.rs::Game::recipe_search_focused
|
||||
AbstractRecipeBookScreen.mouseDragged missing dragging inside the recipe search box does not select text
|
||||
AbstractRecipeBookScreen.isHovering missing in a narrow window with the book open the slots under the book can still be hovered and clicked; vanilla disables them
|
||||
AbstractRecipeBookScreen.mouseDragged port crates/horizon-client/src/game/recipe_book.rs::Game::recipe_book_drag a drag out of the focused search box moves its selection end (EditBox.onDrag)
|
||||
AbstractRecipeBookScreen.isHovering port crates/horizon-client/src/game/recipe_book.rs::Game::book_covers_menu an open book in a window narrower than the menu covers it, so slot_at finds no slot and clicks miss
|
||||
AbstractRecipeBookScreen.slotClicked inline crates/horizon-client/src/game/recipe_book.rs::Game::recipe_book_click clicking a crafting slot drops the ghost recipe; done on mouse press only
|
||||
AbstractSignEditScreen.<init> port crates/horizon-client/src/game/sign_edit.rs::Game::open_sign_editor lines, wood type and text colour come from the sign
|
||||
AbstractSignEditScreen.init inline crates/horizon-client/src/game/sign_edit.rs::Game::draw_sign_editor Done button is laid out here and handled in sign_edit_click
|
||||
AbstractSignEditScreen.isValid missing the editor stays open when the sign is broken or the player ends up out of range; vanilla closes it each tick and sends the text
|
||||
AbstractSignEditScreen.isValid inline crates/horizon-client/src/game/sign_edit.rs::Game::tick_sign_editor the check is the editor's tick: a removed sign, or eyes past the reach + 4, closes it and removed sends the text
|
||||
AbstractSignEditScreen.keyPressed port crates/horizon-client/src/game/sign_edit.rs::Game::sign_input Up, Down and Enter move between lines
|
||||
AbstractSignEditScreen.preeditUpdated missing no IME composition text while typing on a sign
|
||||
AbstractSignEditScreen.preeditUpdated inline crates/horizon-client/src/game/ime.rs::Game::ime_preedit the composition reaches the focused field of any screen (a sign editor counts) and is drawn under its caret
|
||||
AbstractSignEditScreen.extractRenderState port crates/horizon-client/src/game/sign_edit.rs::Game::draw_sign_editor
|
||||
AbstractSignEditScreen.extractSign inline crates/horizon-client/src/game/sign_edit.rs::Game::draw_sign_editor sign sprite and text scale
|
||||
AbstractSignEditScreen.extractSignText inline crates/horizon-client/src/game/sign_edit.rs::Game::draw_sign_editor cursor at the end of a line is a bar; vanilla draws an underscore there; no bidirectional shaping
|
||||
@@ -117,31 +117,31 @@ CrafterScreen.extractRenderState port crates/horizon-client/src/game/machines/cr
|
||||
CrafterScreen.extractRedstone port crates/horizon-client/src/screen_layout.rs::crafter powered or unpowered arrow
|
||||
CraftingScreen.getRecipeBookButtonPosition port crates/horizon-client/src/game/recipe_book.rs::Game::book_button_pos
|
||||
CraftingScreen.extractBackground inline crates/horizon-client/src/game.rs::Game::draw_inventory crafting table texture
|
||||
CreativeModeInventoryScreen.tryRefreshInvalidatedTabs missing tabs are read once from creative-inventory.json; they are not rebuilt when feature flags, permissions or datapacks change (no Operator Utilities tab)
|
||||
CreativeModeInventoryScreen.tryRebuildTabContents missing same as tryRefreshInvalidatedTabs; the search trees are not rebuilt either
|
||||
CreativeModeInventoryScreen.tryRefreshInvalidatedTabs port crates/horizon-client/src/creative.rs::Creative::set_permissions rebuilt when hasPermissions changes, the selected tab keeping its first row or giving way to the default tab
|
||||
CreativeModeInventoryScreen.tryRebuildTabContents port crates/horizon-client/src/creative.rs::Creative::rebuild gap: minor: the tabs and search trees are rebuilt from the export when permissions change; feature flags and datapacks are not re-read
|
||||
CreativeModeInventoryScreen.refreshCurrentTabContents inline crates/horizon-client/src/creative.rs::Creative::items the grid is worked out again when the tab, search or language changed
|
||||
CreativeModeInventoryScreen.containerTick missing the creative screen stays open if the player is no longer in creative (vanilla swaps to the survival inventory); no tab refresh
|
||||
CreativeModeInventoryScreen.containerTick port crates/horizon-client/src/game.rs::Game::tick refresh_creative_tabs each tick, then a player without infinite materials gets the survival inventory
|
||||
CreativeModeInventoryScreen.init port crates/horizon-client/src/creative.rs::Creative::reopen fresh search box and scrollbar when the screen opens
|
||||
CreativeModeInventoryScreen.resize skip:ui re-init on window resize keeping search text and scroll row
|
||||
CreativeModeInventoryScreen.removed skip:other unregisters the slot listener; Horizon sends the creative slots to the server from its own tick
|
||||
CreativeModeInventoryScreen.charTyped port crates/horizon-client/src/game/clipboard.rs::Game::creative_search_edit
|
||||
CreativeModeInventoryScreen.preeditUpdated missing no IME composition text in the search box
|
||||
CreativeModeInventoryScreen.preeditUpdated inline crates/horizon-client/src/game/ime.rs::Game::ime_preedit the search box is a focused field, so the composition shows under its caret
|
||||
CreativeModeInventoryScreen.isInputCaptured inline crates/horizon-client/src/game/debug_keys.rs::Game::debug_key typing gate for the search tab; vanilla only uses it to stop the friends hotkey
|
||||
CreativeModeInventoryScreen.updateVisibleTags missing a # tag search does not list the matching tags in item tooltips
|
||||
CreativeModeInventoryScreen.updateVisibleTags port crates/horizon-client/src/creative.rs::Creative::search_tag_lines the tags the text after # matches, each as a #namespace:path line
|
||||
CreativeModeInventoryScreen.extractLabels inline crates/horizon-client/src/game.rs::Game::draw_creative tab title at 8,6 except on the inventory tab
|
||||
CreativeModeInventoryScreen.mouseReleased port crates/horizon-client/src/creative.rs::Creative::release ends the scrollbar drag; tabs are selected on press, not on release
|
||||
CreativeModeInventoryScreen.mouseScrolled port crates/horizon-client/src/creative.rs::Creative::wheel
|
||||
CreativeModeInventoryScreen.hasClickedOutside port crates/horizon-client/src/game.rs::Game::clicked_outside creative window size; tab clicks are handled before it in click_creative
|
||||
CreativeModeInventoryScreen.mouseDragged port crates/horizon-client/src/creative.rs::Creative::drag_scrollbar
|
||||
CreativeModeInventoryScreen.extractRenderState port crates/horizon-client/src/game.rs::Game::draw_creative trash tooltip text is fixed English; no pointing-hand or resize cursor over tabs and the scrollbar
|
||||
CreativeModeInventoryScreen.getTooltipFromContainerItem missing item tooltips in the creative screen do not list the tabs that hold the item (blue lines) or, in a # search, the matching tags (purple)
|
||||
CreativeModeInventoryScreen.getTooltipFromContainerItem port crates/horizon-client/src/game.rs::Game::creative_tooltip_tabs the containing tabs' names in blue, then a # search's tags in dark purple; none for a category tab's own grid slot
|
||||
CreativeModeInventoryScreen.getTabY port crates/horizon-client/src/creative.rs::Creative::tab_position click area uses the drawn tab position, 4 px off vanilla's -32 / image height
|
||||
CreativeModeInventoryScreen.checkTabClicked inline crates/horizon-client/src/game.rs::Game::click_creative loop over the tab rectangles
|
||||
CreativeModeInventoryScreen.checkTabHovering inline crates/horizon-client/src/game.rs::Game::draw_creative tab title tooltip
|
||||
CreativeModeInventoryScreen.extractTabButton inline crates/horizon-client/src/game.rs::Game::draw_creative tab sprite and icon item
|
||||
CreativeModeInventoryScreen.CustomCreativeSlot.mayPickup missing no CREATIVE_SLOT_LOCK or disabled-feature refusal on display slots; only matters for the saved hotbars tab, which Horizon does not have
|
||||
CreativeModeInventoryScreen.CustomCreativeSlot.mayPickup inline crates/horizon-client/src/creative.rs::click_display a display slot holding a creative_slot_lock stack takes no click; gap: minor: isItemEnabled's feature check is not repeated
|
||||
CreativeModeInventoryScreen.ItemPickerMenu.getRowIndexForScroll port crates/horizon-client/src/creative.rs::Creative::first_row
|
||||
CreativeModeInventoryScreen.ItemPickerMenu.scrollTo inline crates/horizon-client/src/creative.rs::Creative::first_row display slots are read from the first visible row when drawn and clicked
|
||||
CyclingSlotBackground missing empty smithing table slots do not cycle hint icons: only a static netherite upgrade template icon shows, none for base item or addition
|
||||
CyclingSlotBackground home crates/horizon-client/src/game/stations.rs CyclingSlot: an empty slot's icons advance every 30 ticks with a 4-tick fade
|
||||
DispenserScreen.init inline crates/horizon-client/src/game/machines.rs::Game::draw_machine_screen title centred
|
||||
DispenserScreen.extractBackground port crates/horizon-client/src/game/machines.rs::Game::draw_machine_screen
|
||||
|
+19
-19
@@ -47,8 +47,8 @@ Screenshot.takeScreenshot port crates/horizon-client-render/src/gfx.rs::Renderer
|
||||
Screenshot.getFile port crates/horizon-client/src/game/chat.rs::screenshot_name minor: UTC instead of local time in the name
|
||||
ScrollWheelHandler.getNextScrollWheelSelection port crates/horizon-client-input/src/mouse.rs::ScrollWheelHandler::next_selection
|
||||
SectionUpdateTracker.setDirty port crates/horizon-client-render/src/world.rs::DirtySections::insert gap: minor: the from-player flag that orders remeshing is not kept
|
||||
SectionUpdateTracker.hasAllNeighbors missing minor: unsure: no separate neighbour-chunk check found; the mesher works from a 3x3 region
|
||||
SectionUpdateTracker.doesChunkExistAt missing minor: unsure: see hasAllNeighbors
|
||||
SectionUpdateTracker.hasAllNeighbors inline crates/horizon-client-render/src/streaming.rs::Streaming::update the meshing loop waits until all eight neighbouring columns are lit and not lighting, and Streaming::region yields None unless all nine chunks are there, as doesChunkExistAt's chunk-at-FULL test
|
||||
SectionUpdateTracker.doesChunkExistAt inline crates/horizon-client-render/src/streaming.rs::Streaming::region region() looks up each of the 3x3 chunks and gives None if one is absent; the light-on-in-column half is the `lit` set the update loop waits on
|
||||
SectionUpdateTracker.SectionDirtyState.setDirty port crates/horizon-client-render/src/world.rs::DirtySections::insert gap: minor: the from-player flag is not kept
|
||||
SectionUpdateTracker.SectionDirtyState.setSectionNode skip:java section node exists only for the rotating storage; Horizon keys sections by coordinates
|
||||
StringSplitter.stringWidth port crates/horizon-client-render/src/font.rs::Font::width
|
||||
@@ -63,8 +63,8 @@ StringSplitter.WidthLimitedCharSink.accept port crates/horizon-client-render/src
|
||||
AnimationDefinition.Builder.addAnimation skip:java builder for code-made animations; Horizon parses animation JSON
|
||||
KeyframeAnimation.bake inline crates/horizon-client/src/mobs/keyframes.rs::Animation::apply gap: minor: bones are looked up per frame; no check that a bone exists
|
||||
KeyframeAnimation.getElapsedSeconds inline crates/horizon-client/src/mobs/keyframes.rs::Animation::apply seconds modulo the length when looping
|
||||
KeyframeAnimations.degreeVec missing minor: unsure: no degree-to-radian conversion found in mobs/keyframes.rs or horizon-assets; check where keyframe rotations are converted
|
||||
KeyframeAnimations.scaleVec missing minor: unsure: no scale-offset conversion found; see degreeVec
|
||||
KeyframeAnimations.degreeVec inline crates/horizon-client/src/mobs/keyframes.rs::Animation::apply the vanilla animation definitions call degreeVec when they build their keyframes, so the pre/post targets the exporter writes and Horizon parses are already radians; apply adds them straight into the pose
|
||||
KeyframeAnimations.scaleVec inline crates/horizon-client/src/mobs/keyframes.rs::Animation::apply the definitions call scaleVec first, so a keyframe scale arrives with 1 already subtracted and adds onto the part's scale, as ModelPart.offsetScale does
|
||||
ColorLerper.getLerpedColor port crates/horizon-client/src/mobs/render.rs::jeb_wool_rgb a sheep whose custom name is exactly jeb_ cycles through the dye colours by age, as MobRenderer.checkMagicName does
|
||||
ColorLerper.getModifiedColor inline crates/horizon-client/src/mobs/render.rs::jeb_wool_rgb the same table walk, inlined for the jeb_ name
|
||||
BlockColors.getTintSource port crates/horizon-client-render/src/mesher.rs::Mesher::tint
|
||||
@@ -81,15 +81,15 @@ Firework.calculate port crates/horizon-assets/src/item_model.rs::Resolve::tint
|
||||
ItemTintSources.bootstrap skip:data item tint ids are registered from data
|
||||
net/minecraft/client/color/item/Potion#calculate port crates/horizon-assets/src/item_model.rs::Resolve::tint
|
||||
net/minecraft/client/color/item/TeamColor#calculate port crates/horizon-assets/src/item_model.rs::Resolve::tint
|
||||
ClientAvatarState.moveCloak missing minor: no cape lag; capes are not drawn by Horizon's renderer
|
||||
ClientAvatarState.moveCloak port crates/horizon-client-render/src/camera.rs::AvatarBob::tick the cloak point eases a quarter of the way to the player each tick, or jumps to it from 10 blocks away; the cape layer leans from it
|
||||
ClientMannequin.registerOverrides skip:other client-side constructor override; Horizon creates mannequins from the species table
|
||||
ClientMannequin.tick missing minor: unsure: the mannequin avatar state (walk bob, cloak) is not ticked; skins come from skins.rs
|
||||
AbstractSelectionList.getRowLeft port crates/horizon-client-render/src/pack_screen.rs::List::row_left
|
||||
CycleButton.setValue skip:ui widgets read the settings each frame; no separate value setter
|
||||
CreateFlatWorldScreen.DetailsList.LayerEntry.getNarration skip:ui screen-reader text
|
||||
InputQuirks.isQuitShortcutDown port crates/horizon-client/src/game.rs the close path reads settings.quit_shortcuts and input::is_quit_shortcut_down, so with the option off the shortcut no longer closes the window
|
||||
InputWithModifiers.isSelection missing minor: unsure: Space and Enter do not activate focused buttons on the screens checked
|
||||
InputWithModifiers.isConfirmation missing minor: unsure: Enter checks are per screen (options_ui.rs key, chat.rs); no shared predicate
|
||||
InputWithModifiers.isSelection inline crates/horizon-client/src/game/key_focus.rs::nav_of Enter, Space and keypad Enter all map to Nav::Select, which presses the focused widget
|
||||
InputWithModifiers.isConfirmation inline crates/horizon-client-render/src/chat.rs::ChatScreen::key Enter and keypad Enter only, as the text-field screens do (chat, sign, command block, books); no shared predicate
|
||||
InputWithModifiers.isCopy port crates/horizon-client-input/src/clipboard.rs::edit_shortcut
|
||||
InputWithModifiers.isPaste port crates/horizon-client-input/src/clipboard.rs::edit_shortcut
|
||||
InputWithModifiers.isCut port crates/horizon-client-input/src/clipboard.rs::edit_shortcut
|
||||
@@ -100,13 +100,13 @@ net/minecraft/client/main/Main#getQuickPlayVariant port crates/horizon-client/sr
|
||||
net/minecraft/client/main/Main#parseArgument inline crates/horizon-client/src/game.rs::Options::read
|
||||
net/minecraft/client/main/Main#hasValidUuid missing minor: unsure: no --uuid argument found in the client
|
||||
net/minecraft/client/main/Main#isUuidValid missing minor: unsure: see hasValidUuid
|
||||
AbstractClientPlayer.getPlayerInfo missing minor: unsure: no per-player tab entry lookup found on the client
|
||||
AbstractClientPlayer.getSkin missing minor: unsure: remote player skins are not tied to a player info; skins.rs has the lookup
|
||||
AbstractClientPlayer.getParrotVariantOnShoulder missing player: a parrot on your shoulder is never drawn (no shoulder parrot code)
|
||||
AbstractClientPlayer.getPlayerInfo inline crates/horizon-client/src/game/remote.rs::Game::remote_pushes the entity id -> uuid -> tab entry lookups stand in for the PlayerInfo; the name, team and game mode are read from that entry
|
||||
AbstractClientPlayer.getSkin port crates/horizon-client/src/game/remote.rs::Game::update_remote_skins the downloaded skin and slim flag, else DefaultPlayerSkin by uuid, as PlayerInfo.getSkin
|
||||
AbstractClientPlayer.getParrotVariantOnShoulder port crates/horizon-client/src/mobs/render.rs::shoulder_parrot the shoulder slot's stored variant picks the parrot texture and model in the layer
|
||||
ClientInput.makeJump inline crates/horizon-client/src/motion.rs::MotionWorld::controlled_simulation_tick gap: minor: carries the auto-jump flag; no separate jump input
|
||||
FirstPersonHandsAndItems.extractRenderState inline crates/horizon-client/src/game/hand.rs::Game::visible_hand_items gap: minor: bob, swing and map state are read elsewhere; no render-state struct
|
||||
FirstPersonHandsAndItems.shouldInstantlyReplaceVisibleItem missing minor: unsure: no instant swap rule found in first_person.rs; HandHeights::tick takes a changed flag
|
||||
FirstPersonHandsAndItems.extractMapRenderState missing minor: unsure: map-in-hand data lookup not found; one_handed_map_pose only sets the pose
|
||||
FirstPersonHandsAndItems.extractMapRenderState inline crates/horizon-client/src/game/maps.rs::Game::held_map the MAP_ID component picks the map data drawn in the hand, its decorations included, and decides the checkerboard background
|
||||
FirstPersonHandsAndItems.isChargedCrossbow inline crates/horizon-client/src/first_person.rs::hands_to_render
|
||||
ItemActivation.tick missing player: the totem-of-undying item pop is never drawn; game/totem.rs draws particles and sound only
|
||||
ItemActivation.activate missing player: same as tick
|
||||
@@ -118,15 +118,15 @@ LocalPlayer.sendIsSprintingIfNeeded inline crates/horizon-client/src/game/remote
|
||||
LocalPlayer.closeContainer port crates/horizon-client/src/game/remote.rs::Game::remote_close_container
|
||||
LocalPlayer.isSuppressingSlidingDownLadder port crates/horizon-client/src/motion.rs::MotionWorld::suppressing_ladder_slide gap: minor: sneak only; vanilla also requires not flying
|
||||
LocalPlayer.canSpawnSprintParticle port crates/horizon-client/src/game/client_ambient.rs::Game::sprint_dust gap: minor: flying check is the caller's
|
||||
LocalPlayer.sendRidingJump missing player: mounted jumps (horses, camels) never send START_RIDING_JUMP, so the server ignores the jump charge
|
||||
LocalPlayer.sendRidingJump port crates/horizon-client/src/game/remote_vehicles.rs::riding_jump START_RIDING_JUMP carrying the jump scale
|
||||
LocalPlayer.removeRecipeHighlight port crates/horizon-client/src/recipe_book.rs::Settings::remove_highlight gap: minor: the seen-recipe packet is not sent, so the server keeps the highlight
|
||||
LocalPlayer.moveTowardsClosestSpace missing player: you are not nudged out of blocks at your four corners each tick (aiStep)
|
||||
LocalPlayer.suffocatesAt missing player: no suffocation test for the corner nudge (see moveTowardsClosestSpace)
|
||||
LocalPlayer.moveTowardsClosestSpace port crates/horizon-client/src/game.rs::Game::closest_space_nudge the four body corners, 0.1 towards the nearest free side on its axis, a later corner overwriting an earlier one
|
||||
LocalPlayer.suffocatesAt inline crates/horizon-client/src/game.rs::closest_space_nudge the suffocates_at closure tests a full collision cube that is also a full render cube, over the body's Y span
|
||||
LocalPlayer.setExperienceDisplayStartTickToTickCount inline crates/horizon-client/src/game/locator_bar.rs::Game::track_experience_display
|
||||
LocalPlayer.handleEntityEvent port crates/horizon-client/src/game/remote.rs::Game::handle_packet gap: minor: only the permission events 24 to 28 of the local player
|
||||
LocalPlayer.startUsingItem port crates/horizon-client/src/game.rs::Game::use_hand
|
||||
LocalPlayer.isSlowDueToUsingItem missing player: sprinting is not blocked while eating or drawing a bow; sprint_input_tick never sets slow_item
|
||||
LocalPlayer.onSyncedDataUpdated missing minor: unsure: server living flags and the elytra start sound are not applied to the local player
|
||||
LocalPlayer.isSlowDueToUsingItem port crates/horizon-client/src/game.rs::Game::sync_player_body the used item's UseEffects.canSprint reaches sprint's slow_item, which stops a sprint starting and ends one
|
||||
LocalPlayer.onSyncedDataUpdated inline crates/horizon-client/src/game/music.rs::Game::tick_sound_engine starting to glide starts the elytra flying sound; the living flags are local state on this side
|
||||
LocalPlayer.jumpableVehicle inline crates/horizon-client/src/game/mounts.rs::Game::charge_mount_jump gap: minor: saddle and jump-capable check only; no separate vehicle lookup
|
||||
LocalPlayer.openTextEdit port crates/horizon-client/src/game/sign_edit.rs::Game::open_sign_editor
|
||||
LocalPlayer.modifyInputSpeedForSquareMovement port crates/horizon-client-input/src/input.rs::square_movement
|
||||
@@ -135,14 +135,14 @@ LocalPlayer.resetPos inline crates/horizon-client/src/game/screens.rs::Game::res
|
||||
LocalPlayer.shouldStopRunSprinting port crates/horizon-client/src/sprint.rs::Conditions::should_stop gap: player: minor_horizontal_collision is always false, so wall slides stop the sprint
|
||||
LocalPlayer.shouldStopSwimSprinting port crates/horizon-client/src/sprint.rs::Conditions::should_stop
|
||||
LocalPlayer.tickDeath missing minor: unsure: the dead local player is not removed after 20 ticks; the death screen flow covers it
|
||||
LocalPlayer.rideTick missing minor: unsure: no code found that feeds movement keys into a boat's paddling
|
||||
LocalPlayer.rideTick port crates/horizon-client/src/game/boats.rs::Game::tick_riding the keys are latched into the boat's input and the seat follows its turn
|
||||
LocalPlayer.isHorizontalCollisionMinor port crates/horizon-client/src/motion.rs::EntityMoveWorld::minor_horizontal_collision the sprint keeps when a move hits a wall at under 8 degrees
|
||||
LocalPlayer.isMoving inline crates/horizon-client/src/auto_jump.rs::can_auto_jump
|
||||
LocalPlayer.isSprintingPossible port crates/horizon-client/src/sprint.rs::Conditions::possible
|
||||
LocalPlayer.canStartSprinting port crates/horizon-client/src/sprint.rs::Conditions::can_start gap: player: slow_item is never set, so eating does not block starting a sprint
|
||||
LocalPlayer.onGameModeChanged missing minor: switching to spectator keeps vertical momentum
|
||||
LocalPlayer.getRopeHoldPosition missing player: no leash or lead rope exists in Horizon, so no rope is drawn
|
||||
LocalPlayer.getRopeHoldPosition port crates/horizon-client/src/game/leads.rs::Game::player_rope_hold the first-person rope point from the look angles and the main arm
|
||||
LocalPlayer.raycastHitResult port crates/horizon-client/src/game/hand.rs::GameHands::hit gap: minor: block fallback is Game::pick; no separate item attack-range pass
|
||||
LocalPlayer.filterHitResult inline crates/horizon-client/src/game.rs::Game::pick gap: minor: reach is applied inside the clip; no miss direction is returned
|
||||
LocalPlayerResolver.fetchByName missing minor: unsure: no player-list lookup by name on the client
|
||||
LocalPlayerResolver.fetchById missing minor: unsure: no player-list lookup by id on the client
|
||||
LocalPlayerResolver.fetchById inline crates/horizon-client/src/game/remote.rs::Game::remote_pushes the uuid -> tab entry lookup is inline wherever a player's name, team or skin is needed
|
||||
|
+25
-25
@@ -1,8 +1,8 @@
|
||||
RemotePlayer.shouldRenderAtSqrDistance port crates/horizon-client/src/game/entity_culling.rs::entity_view_scale every entity's draw distance is scaled by the view scale and the limit, remote players included
|
||||
RemotePlayer.aiStep missing unsure: remote players are drawn from Mob records in game/remote.rs; no per-tick motion lerp or push step found
|
||||
RemotePlayer.aiStep inline crates/horizon-client/src/game/remote.rs::Game::tick_remote_entities gap: minor: the head yaws over its lerp steps; the smoothed delta movement and the push step are not ported
|
||||
RemotePlayer.lerpMotion missing unsure: no lerp of received remote-player motion found in game/remote.rs
|
||||
Hotbar.storeFrom port crates/horizon-client/src/game/creative_hotbar.rs::Game::hotbar_load_or_save save copies the nine slots into the hotbar.nbt row
|
||||
Hotbar.isEmpty port crates/horizon-client/src/game/creative_hotbar.rs the empty creative hotbar row carries the inventory.hotbarInfo hint
|
||||
Hotbar.isEmpty inline crates/horizon-client/src/game/creative_hotbar.rs::Game::refresh_saved_hotbars the empty creative hotbar row carries the inventory.hotbarInfo hint
|
||||
ClientMetricsSamplersProvider.registerStaticSamplers skip:debug F3 metrics samplers
|
||||
ClientMetricsSamplersProvider.samplers skip:debug F3 metrics samplers
|
||||
QuickPlay.connect port crates/horizon-client/src/game.rs::Options::read gap: minor: no Realms variant and no latest-world fallback
|
||||
@@ -30,12 +30,12 @@ IntegratedServer.getPersonalGameMode port crates/horizon-client/src/game/integra
|
||||
IntegratedServer.updateGameModeBasedOnPermission inline crates/horizon-client/src/game/lan.rs::Game::lan_guest_joined gap: player: a guest already in the world keeps their mode when force-gamemode or the default mode changes; only a join applies it
|
||||
IntegratedServer.updatePermissions port crates/horizon-client/src/lan/hub.rs::Hub::resend_commands permission level and commands sent to every guest
|
||||
IntegratedServer.setDefaultGameType port crates/horizon-client/src/game/lan.rs::Game::set_default_game_mode
|
||||
IntegratedServer.isSingleplayerOwner port crates/horizon-client/src/game/integrated.rs: host.hub.singleplayer_owner the owner is kept by uuid on the hub and read back in commands and LAN actions
|
||||
IntegratedServer.getScaledTrackingDistance missing player: the Entity Distance option is not applied to what a LAN host tracks
|
||||
IntegratedServer.isSingleplayerOwner port crates/horizon-client/src/lan/hub.rs::Hub::player_info the owner is kept by uuid on the hub, and player_info marks the guest it names
|
||||
IntegratedServer.getScaledTrackingDistance inline crates/horizon-client/src/game/lan.rs::Game::tick_lan the Entity Distance option becomes the hub's entity range percent for an integrated or LAN host
|
||||
IntegratedServer.getForcedGameType inline crates/horizon-client/src/game/lan.rs::Game::lan_guest_joined forced mode is sent when a guest joins
|
||||
IntegratedServer.selectLevelLoadFocusPos missing unsure: no load focus at the owner's saved position found in game/integrated.rs open_integrated
|
||||
IntegratedServer.reportChunkLoadFailure port crates/horizon-client/src/chunk_io.rs::load_failed a failed load sets low_disk_space, which is warnOnLowDiskSpace plus reportChunkLoadFailure
|
||||
IntegratedServer.reportChunkSaveFailure port crates/horizon-client/src/chunk_io.rs the same low_disk_space flag is raised by the save side
|
||||
IntegratedServer.reportChunkSaveFailure port crates/horizon-client/src/chunk_io.rs::Pending::save_failed the same low_disk_space flag is raised by the save side
|
||||
LanServerDetection.LanServerDetector.run port crates/horizon-client/src/lan/discovery.rs::listen receive loop for LAN announcements
|
||||
LanServerDetection.LanServerList.takeDirtyServers skip:java dirty flag; Scanner::games returns a copy on each call
|
||||
LanServerPinger.run port crates/horizon-client/src/lan/discovery.rs::Pinger::start announce loop on a thread until dropped
|
||||
@@ -67,7 +67,7 @@ SoundBufferLibrary.enumerate port crates/horizon-client-render/src/audio.rs::Aud
|
||||
SoundBufferLibrary.DebugOutput.Counter.accountBuffer inline crates/horizon-client-render/src/audio.rs::Audio::census counts buffers and sizes
|
||||
SoundEngine.reload port crates/horizon-client-render/src/audio.rs::Audio::reload stops sounds and reads the new resource root
|
||||
SoundEngine.loadLibrary port crates/horizon-client-render/src/audio.rs::Audio::with_output opens the output device
|
||||
SoundEngine.shouldChangeDevice port crates/horizon-client-render/src/audio.rs: devices_seen / last_seen_devices the output device list is watched and the sink reopened when it changes
|
||||
SoundEngine.shouldChangeDevice port crates/horizon-client-render/src/audio.rs::Audio::tick the device list is watched once a second and the output reopened when the default or the chosen device changes
|
||||
SoundEngine.notifyListeners port crates/horizon-client-render/src/sound_engine.rs::SoundEngine::notify subtitle and listener notification with range
|
||||
SoundEngine.updateSource port crates/horizon-client-render/src/audio.rs::Audio::set_listener listener position and orientation
|
||||
SoundEngineExecutor.createThread skip:other sound thread creation; Horizon's audio runs on the cpal callback
|
||||
@@ -81,25 +81,25 @@ SoundManager.Preparations.apply inline crates/horizon-client-render/src/sound_ev
|
||||
SoundPreviewHandler.preview port crates/horizon-client-render/src/audio.rs::preview the pack screen's sound preview
|
||||
SoundPreviewHandler.stopOtherCategoryPreview port crates/horizon-client-render/src/sound_preview.rs::SoundPreview::stop_other_category_preview
|
||||
WeighedSoundEvents.preloadIfRequired skip:java preload is a cache; Horizon decodes on demand
|
||||
CraftPlanksTutorialStep.tick missing player: a new survival world shows no craft-planks tutorial toast; Horizon has no tutorial steps (tutorialStep is only stored in options)
|
||||
CraftPlanksTutorialStep.hasCraftedPlanksPreviously missing minor: part of the craft-planks tutorial
|
||||
FindTreeTutorialStepInstance.tick missing player: no find-a-tree tutorial toast
|
||||
FindTreeTutorialStepInstance.onLookAt missing minor: part of the find-a-tree tutorial
|
||||
FindTreeTutorialStepInstance.hasPunchedTreesPreviously missing minor: part of the find-a-tree tutorial
|
||||
MovementTutorialStepInstance.tick missing player: no move and look tutorial toasts
|
||||
MovementTutorialStepInstance.clear missing minor: part of the movement tutorial
|
||||
MovementTutorialStepInstance.onInput missing minor: part of the movement tutorial
|
||||
MovementTutorialStepInstance.onMouse missing minor: part of the movement tutorial
|
||||
OpenInventoryTutorialStep.tick missing player: no open-inventory tutorial toast
|
||||
PunchTreeTutorialStepInstance.tick missing player: no punch-a-tree tutorial toast
|
||||
PunchTreeTutorialStepInstance.onDestroyBlock missing minor: part of the punch-a-tree tutorial
|
||||
Tutorial.onLookAt missing minor: tutorial driver; no tutorial exists
|
||||
Tutorial.onDestroyBlock missing minor: tutorial driver; no tutorial exists
|
||||
Tutorial.stop missing minor: tutorial driver; no tutorial exists
|
||||
Tutorial.start missing minor: tutorial driver; no tutorial exists
|
||||
Tutorial.tick missing player: the tutorial driver that shows the first toasts is absent
|
||||
Tutorial.setStep missing minor: tutorial driver; no tutorial exists
|
||||
Tutorial.isSurvival missing minor: only the tutorial asks whether the player is in survival
|
||||
CraftPlanksTutorialStep.tick inline crates/horizon-client/src/game/tutorial.rs::Tutorial::tick the CraftPlanks arm: a plank already held or crafted on the first tick ends the step; its toast is Tutorial::hint
|
||||
CraftPlanksTutorialStep.hasCraftedPlanksPreviously inline crates/horizon-client/src/game/tutorial.rs::Game::tick_tutorial Previous::crafted_plank: a planks item with a count in the player's minecraft:crafted stats
|
||||
FindTreeTutorialStepInstance.tick inline crates/horizon-client/src/game/tutorial.rs::Tutorial::tick the FindTree arm: a tree item held or a tree already mined moves the step on to craft planks; its toast is Tutorial::hint
|
||||
FindTreeTutorialStepInstance.onLookAt port crates/horizon-client/src/game/tutorial.rs::Tutorial::look_at_tree looking at a block in completes_find_tree_tutorial moves the step on to punch tree
|
||||
FindTreeTutorialStepInstance.hasPunchedTreesPreviously inline crates/horizon-client/src/game/tutorial.rs::Game::tick_tutorial Previous::mined_tree: a block in completes_find_tree_tutorial with a count in the minecraft:mined stats
|
||||
MovementTutorialStepInstance.tick inline crates/horizon-client/src/game/tutorial.rs::Tutorial::tick the Movement arm: 40 ticks moved and 40 ticks looked, then find-tree in survival and none in creative; the toasts are Tutorial::hint
|
||||
MovementTutorialStepInstance.clear inline crates/horizon-client/src/game/tutorial.rs::Tutorial::set_step a new step starts from Tutorial::new, which zeroes the movement counters
|
||||
MovementTutorialStepInstance.onInput port crates/horizon-client/src/game/tutorial.rs::Tutorial::input a movement key held in the world marks the player as moved
|
||||
MovementTutorialStepInstance.onMouse port crates/horizon-client/src/game/tutorial.rs::Tutorial::mouse a mouse delta over 0.01 marks the player as turned
|
||||
OpenInventoryTutorialStep.tick inline crates/horizon-client/src/game/tutorial.rs::Tutorial::tick the OpenInventory arm stops outside survival; the step itself ends in Tutorial::open_inventory, its toast is Tutorial::hint
|
||||
PunchTreeTutorialStepInstance.tick inline crates/horizon-client/src/game/tutorial.rs::Tutorial::tick the PunchTree arm: the break progress and the reset count of bad breaks feed the hint
|
||||
PunchTreeTutorialStepInstance.onDestroyBlock port crates/horizon-client/src/game/tutorial.rs::Tutorial::destroy a log's break progress is kept and a finished break moves on to open inventory; anything else resets it
|
||||
Tutorial.onLookAt inline crates/horizon-client/src/game/tutorial.rs::Game::tick_tutorial the pick's block is tested against completes_find_tree_tutorial, then Tutorial::look_at_tree
|
||||
Tutorial.onDestroyBlock port crates/horizon-client/src/game/tutorial.rs::Game::tutorial_destroy the broken block's log tag and break progress go to Tutorial::destroy
|
||||
Tutorial.stop inline crates/horizon-client/src/game/tutorial.rs::Tutorial::set_step the step becomes None, which shows no hint
|
||||
Tutorial.start inline crates/horizon-client/src/game/tutorial.rs::Game::reset_tutorial a Tutorial built from the persisted tutorialStep option
|
||||
Tutorial.tick port crates/horizon-client/src/game/tutorial.rs::Game::tick_tutorial the step's tick, the movement input, and the look-at pick, once per tick in the world
|
||||
Tutorial.setStep port crates/horizon-client/src/game/tutorial.rs::Tutorial::set_step the step with a fresh state; Game::persist_tutorial_step writes it to options.txt
|
||||
Tutorial.isSurvival inline crates/horizon-client/src/game/tutorial.rs::Game::tick_tutorial the game mode is read there and passed to Tutorial::tick, which stops the step outside survival
|
||||
TutorialSteps.getByName port crates/horizon-client-render/src/options_file.rs::OptionsFile::try_apply tutorialStep name read from options
|
||||
ClientWaypointManager.updateWaypoint port crates/horizon-client/src/locator_bar.rs::ClientWaypoints::apply updates a tracked waypoint by id
|
||||
ClientWaypointManager.forEachWaypoint port crates/horizon-client/src/locator_bar.rs::ClientWaypoints::draw drawn farthest first
|
||||
|
||||
|
@@ -30,13 +30,13 @@ RegistryFixedCodec.decode skip:java codec decode of fixed registry references
|
||||
CircleGizmo.emit missing minor: debug circle gizmo (F3 debug renderers only); gizmos.rs has no circle primitive
|
||||
GizmoStyle.hasStroke skip:other style predicate; Horizon debug lines always carry one width (gizmos.rs::Line), so there is no stroke to test
|
||||
Gizmos.addGizmo skip:other registration into vanilla's thread-local collector; Horizon's gizmos.rs::Gizmos holds the lines directly
|
||||
Gizmos.rect missing minor: debug rectangles (F3 debug renderers only); gizmos.rs draws cuboid edges only, no faces
|
||||
Gizmos.rect inline crates/horizon-client/src/game/debug_renderers.rs::Game::solid_face_shapes the box-and-direction fill overload `SolidFaceRenderer` uses: one cuboid face's four corners from gizmos.rs::cuboid_fill_quads, filled with a plain colour; the four-corner overload has no caller
|
||||
Gizmos.billboardTextOverBlock missing minor: debug text above a block (debug renderers only); gizmos.rs has no billboard text
|
||||
Gizmos.billboardTextOverMob missing minor: debug text above a mob (debug renderers only); gizmos.rs has no billboard text
|
||||
Gizmos.TemporaryCollection.close skip:other restores vanilla's thread-local gizmo collector; Horizon has no collector stack
|
||||
LineGizmo.emit port crates/horizon-client/src/gizmos.rs::Gizmos::line gap: minor: no alpha multiplier, so debug lines do not fade
|
||||
PointGizmo.emit missing minor: debug point gizmo (F3 debug renderers only); gizmos.rs has no point primitive
|
||||
RectGizmo.fromCuboidFace missing minor: face rectangle for debug rects (F3 debug renderers only); not ported
|
||||
RectGizmo.fromCuboidFace inline crates/horizon-client/src/game/debug_renderers.rs::Game::solid_face_shapes the four corners of one cuboid face, in gizmos.rs::cuboid_fill_quads' order (+X, -X, -Z, +Z, +Y, -Y), for the sturdy sides
|
||||
RectGizmo.emit missing minor: filled and outlined debug quads (F3 debug renderers only); gizmos.rs has no quad primitive
|
||||
SimpleGizmoCollector.add skip:other adds to vanilla's per-frame gizmo collector; Horizon has no collector object, gizmos.rs::Gizmos holds the lines
|
||||
SimpleGizmoCollector.drainGizmos skip:other per-frame hand-off and expiry of vanilla's collector; Horizon's debug gizmos have no expiry
|
||||
|
||||
|
@@ -22,10 +22,10 @@ DiscardedPayload.codec missing minor: no 32767-byte cap on unknown custom paylo
|
||||
ServerboundCookieResponsePacket.write port crates/horizon-protocol/src/buf.rs::write packet! CookieResponse {key Ident, payload Option<Bytes>}
|
||||
ClientboundAddEntityPacket.<init> port crates/horizon-client/src/lan/entity.rs::ServerEntity::pairing builds the spawn packet from the entity state
|
||||
ClientboundAddEntityPacket.write port crates/horizon-protocol/src/buf.rs::write packet! AddEntity (play.rs) in the vanilla field order
|
||||
ClientboundAddTransientBlockPacket.write inline crates/horizon-client/src/game/remote.rs: C::AddTransientBlock => add_transient_block the client applies a transient block when a server sends one; the LAN host does not send them, which is the remaining half of the row
|
||||
ClientboundAddTransientBlockPacket.write inline crates/horizon-client/src/game/transient_blocks.rs::Game::add_transient_block written once when the block is placed and again on the tick it goes back to air; the client applies each with no state send, and the LAN host does not send the packet
|
||||
ClientboundAnimatePacket.write port crates/horizon-protocol/src/buf.rs::write packet! Animate {id VarInt, action UByte}
|
||||
ClientboundBlockDestructionPacket.write port crates/horizon-protocol/src/buf.rs::write packet! BlockDestruction {id, pos, progress}
|
||||
ClientboundBlockEntityDataPacket.create port crates/horizon-client/src/game/command_blocks.rs:952 + game/decorated_pot.rs block entity changes are pushed to guests as the packet (command block text, decorated pot sherds)
|
||||
ClientboundBlockEntityDataPacket.create port crates/horizon-client/src/lan/hub.rs::Hub::broadcast_block_changes the changed block entities of the tick's block updates go out as the packet, a decorated pot's tag coming from its chunk's saved data
|
||||
ClientboundBlockEventPacket.write port crates/horizon-protocol/src/buf.rs::write packet! BlockEvent {pos, b0, b1, block}
|
||||
ClientboundBossEventPacket.createUpdateProgressPacket inline crates/horizon-client/src/game/bossbars.rs::Game::diff_boss_events UpdateProgress goes out to every viewer of the bar (a guest by connection, the host's own overlay in place)
|
||||
ClientboundBossEventPacket.createUpdateNamePacket inline crates/horizon-client/src/game/bossbars.rs::Game::diff_boss_events UpdateName when the bar's name differs from what that viewer was sent
|
||||
@@ -82,8 +82,8 @@ ClientboundSetEntityDataPacket.pack port crates/horizon-protocol/src/entity_data
|
||||
ClientboundSetEntityDataPacket.unpack port crates/horizon-protocol/src/entity_data.rs::EntityData::read entries until 0xFF
|
||||
ClientboundSetExperiencePacket.write port crates/horizon-protocol/src/buf.rs::write packet! SetExperience {progress Float, level, total VarInt}
|
||||
ClientboundSetHealthPacket.write port crates/horizon-protocol/src/buf.rs::write packet! SetHealth {health, food VarInt, saturation}
|
||||
ClientboundSetPlayerTeamPacket.createAddOrModifyPacket port crates/horizon-client/src/lan/scoreboard.rs:124 team add/modify packets are built for guests from the host's teams
|
||||
ClientboundSetPlayerTeamPacket.createPlayerPacket inline crates/horizon-client/src/lan/scoreboard.rs the same builder covers the player add/remove method
|
||||
ClientboundSetPlayerTeamPacket.createAddOrModifyPacket port crates/horizon-client/src/lan/scoreboard.rs::View::changes the method and parameters of a team the view gained or changed, sent before its players
|
||||
ClientboundSetPlayerTeamPacket.createPlayerPacket inline crates/horizon-client/src/lan/scoreboard.rs::View::changes the same builder sends a player's add and remove methods, every leave before any join
|
||||
ClientboundSetPlayerTeamPacket.shouldHavePlayerList port crates/horizon-protocol/src/packets/play.rs::SetPlayerTeam::read the player list is read only for methods 0, 3 and 4
|
||||
ClientboundSetTitlesAnimationPacket.write port crates/horizon-protocol/src/buf.rs::write packet! TitlesAnimation {fade_in, stay, fade_out Int}
|
||||
ClientboundSoundEntityPacket.write port crates/horizon-protocol/src/buf.rs::write packet! SoundEntity with the sound holder
|
||||
@@ -134,7 +134,7 @@ SynchedEntityData.DataValue.read port crates/horizon-protocol/src/entity_data.rs
|
||||
RealmsConnect.connect skip:service Realms
|
||||
RealmsConnect.abort skip:service Realms
|
||||
RealmsConnect.tick skip:service Realms
|
||||
RepeatedNarrator.narrate skip:other accessibility narration; Horizon has no narrator
|
||||
RepeatedNarrator.narrate skip:service Realms only: the long-running task screen's progress, said through GameNarrator.saySystemNow at most once per repeat period; Horizon has no Realms client
|
||||
ServerPlaceRecipe.tryPlaceRecipe port crates/horizon-client/src/menu/place.rs::Menu::place_recipe places when craftable, else clears the grid and shows the ghost
|
||||
ServerPlaceRecipe.clearGrid port crates/horizon-client/src/menu/place.rs::Menu::clear_grid returns the grid to the inventory
|
||||
ServerPlaceRecipe.clampToMaxStackSize inline crates/horizon-client/src/menu/place.rs::Menu::place gap: minor: clamps by the slot's stack, not by each candidate item
|
||||
|
||||
|
Reference in new issue
Block a user