Merge pull request #3589 from d3grando/fix-3427

Commands: coordinate suggestions skip entities and offer the hit point
This commit is contained in:
levzzz authored and GitHub committed 2026-10-29 17:55:49 +05:00
commit 89f949155c
4 files changed
+58 -2

No files matched your search

@@ -54,6 +54,9 @@ pub struct Registries {
pub function_tags: Vec<String>,
/// The block the source is looking at (relevant coordinates).
pub target_block: Option<[i32; 3]>,
/// `ClientSuggestionProvider.getAbsoluteCoordinates`: the exact point of
/// that block hit, each coordinate as `%.2f` (`Locale.ROOT`).
pub target_point: Option<[String; 3]>,
/// Every registry's element and tag ids (`minecraft:item` -> ...), as
/// the server's registry access and reloadable registries hold them.
pub by_registry: BTreeMap<String, RegistryIds>,
+11 -1
View File
@@ -428,8 +428,18 @@ impl Game<'_> {
.collect();
}
/// The block the player is looking at, for coordinate suggestions.
/// `ClientSuggestionProvider.getRelevantCoordinates` and
/// `getAbsoluteCoordinates` read `Minecraft.hitResult` only when it is a
/// block: an entity in front of the block leaves the `~` defaults.
fn refresh_dynamic_registries(&mut self) {
self.ui.registries.target_block = self.pick().map(|h| h.pos);
let hit = if self.pick_entity_hit().is_some() {
None
} else {
self.pick()
};
self.ui.registries.target_block = hit.as_ref().map(|h| h.pos);
self.ui.registries.target_point =
hit.map(|h| h.point.map(horizon_client::java_text::format_fixed2));
// ClientPacketListener.getOnlinePlayerNames on a server.
if let Some(names) = self.remote_online_names() {
self.ui.registries.players = names;
+5 -1
View File
@@ -798,7 +798,9 @@ fn java_split(s: &str) -> Vec<&str> {
parts
}
/// SharedSuggestionProvider.suggestCoordinates / suggest2DCoordinates: the
/// candidates `ty` parses completely.
/// candidates `ty` parses completely. `relevant` arguments (block and column
/// positions) offer the targeted block (`getRelevantCoordinates`), the others
/// (`Vec3`, `Vec2`) the exact hit point (`getAbsoluteCoordinates`).
fn suggest_coordinates(
builder: &mut SuggestionsBuilder,
reg: &Registries,
@@ -811,6 +813,8 @@ fn suggest_coordinates(
["^".into(), "^".into(), "^".into()]
} else if let (true, Some(t)) = (relevant, reg.target_block) {
[t[0].to_string(), t[1].to_string(), t[2].to_string()]
} else if let (false, Some(p)) = (relevant, &reg.target_point) {
p.clone()
} else {
["~".into(), "~".into(), "~".into()]
};
+39
View File
@@ -256,6 +256,45 @@ fn suggestions_like_vanilla() {
assert_eq!(suggestions("time set 5"), ["d", "s", "t"]);
assert!(suggestions("time set ").contains(&"minecraft:day".to_owned()));
}
/// ClientSuggestionProvider: block and column positions offer the targeted
/// block (`getRelevantCoordinates`), `Vec3` and `Vec2` the exact hit point
/// with two decimals (`getAbsoluteCoordinates`); with no block hit, `~`.
#[test]
fn coordinates_suggest_the_crosshair_block_or_hit_point() {
let d = vanilla::dispatcher();
let suggest = |reg: &Registries, input: &str| -> Vec<String> {
let parse = d.parse(input, reg);
d.suggestions(&parse, input.len(), reg)
.1
.into_iter()
.map(|s| s.text)
.collect()
};
let mut hit = reg();
hit.target_block = Some([-29, 73, 8]);
hit.target_point = Some(["-28.77".into(), "73.28".into(), "8.00".into()]);
assert_eq!(suggest(&hit, "setblock "), ["-29", "-29 73", "-29 73 8"]);
assert_eq!(
suggest(&hit, "summon minecraft:pig "),
["-28.77", "-28.77 73.28", "-28.77 73.28 8.00"]
);
assert_eq!(
suggest(&hit, "summon minecraft:pig -28.77 "),
["-28.77 73.28", "-28.77 73.28 8.00"]
);
// Vec2Argument: x and z.
assert_eq!(
suggest(&hit, "worldborder center "),
["-28.77", "-28.77 8.00"]
);
// An entity in front of the block (or no hit): the defaults.
let none = reg();
assert_eq!(suggest(&none, "setblock "), ["~", "~ ~", "~ ~ ~"]);
assert_eq!(
suggest(&none, "summon minecraft:pig "),
["~", "~ ~", "~ ~ ~"]
);
}
#[test]
fn smart_usage_matches_brigadier() {
let d = vanilla::dispatcher();