mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-08 17:19:10 -10:00
Merge pull request #5575 from horizon-rust/fix/commands-take-nicknames
🤖 Agent: players can /msg, /tell and /w a player by their nickname (shown as ~name); server guests included. SMP proof and pr_ready --quick passed on this head (comment above).
This commit is contained in:
2 files changed
+41
-4
No files matched your search
@@ -61,7 +61,11 @@ impl Game<'_> {
|
||||
.unwrap_or(Target::Player)
|
||||
}
|
||||
|
||||
/// `PlayerList.getPlayerByName`: names are not case sensitive.
|
||||
/// `PlayerList.getPlayerByName`: names are not case sensitive. Horizon:
|
||||
/// on a server where a mod gave players nicknames
|
||||
/// (`native_set_nickname`), a name no player has finds the player going
|
||||
/// by it, without its `~` or with it (quoted), so `/msg` and `/tell`
|
||||
/// reach a player by the name chat shows. No nickname, no change.
|
||||
pub(super) fn player_named(&self, name: &str) -> Option<Target> {
|
||||
if self.player.is_some() && name.eq_ignore_ascii_case(self.acting_player_name()) {
|
||||
return Some(Target::Player);
|
||||
@@ -69,6 +73,21 @@ impl Game<'_> {
|
||||
self.command_players()
|
||||
.find(|g| g.name.eq_ignore_ascii_case(name))
|
||||
.map(|g| Target::Guest(g.conn))
|
||||
.or_else(|| self.player_nicknamed(name))
|
||||
}
|
||||
|
||||
/// The player whose nickname is `name` (any case, a leading `~` either
|
||||
/// side ignored).
|
||||
fn player_nicknamed(&self, name: &str) -> Option<Target> {
|
||||
let bare = |s: &str| s.strip_prefix('~').unwrap_or(s).to_ascii_lowercase();
|
||||
let wanted = bare(name);
|
||||
let hub = &self.lan.as_ref()?.hub;
|
||||
let uuid = hub
|
||||
.nicknames
|
||||
.iter()
|
||||
.find(|(_, nick)| bare(nick) == wanted)?
|
||||
.0;
|
||||
self.target_by_uuid(*uuid)
|
||||
}
|
||||
|
||||
/// `EntitySelector.findEntities` with a UUID: the player with it, else
|
||||
|
||||
@@ -186,9 +186,27 @@ impl Game<'_> {
|
||||
let targets: Vec<usize> = match (raw, &selector.player_name, selector.uuid) {
|
||||
(Some("@s"), ..) => vec![i],
|
||||
(Some("@a"), ..) => (0..guests.len()).filter(placed).collect(),
|
||||
(_, Some(name), _) => (0..guests.len())
|
||||
.filter(|&k| placed(&k) && guests[k].name.eq_ignore_ascii_case(name))
|
||||
.collect(),
|
||||
(_, Some(name), _) => {
|
||||
let named: Vec<usize> = (0..guests.len())
|
||||
.filter(|&k| placed(&k) && guests[k].name.eq_ignore_ascii_case(name))
|
||||
.collect();
|
||||
if named.is_empty() {
|
||||
// No player has that name: the one going by it as a nickname (`~` optional).
|
||||
let bare = |s: &str| s.strip_prefix('~').unwrap_or(s).to_ascii_lowercase();
|
||||
let wanted = bare(name);
|
||||
let nicknamed = |k: &usize| {
|
||||
host.hub
|
||||
.nicknames
|
||||
.get(&guests[*k].uuid)
|
||||
.is_some_and(|nick| bare(nick) == wanted)
|
||||
};
|
||||
(0..guests.len())
|
||||
.filter(|k| placed(k) && nicknamed(k))
|
||||
.collect()
|
||||
} else {
|
||||
named
|
||||
}
|
||||
}
|
||||
(_, None, Some(uuid)) => (0..guests.len())
|
||||
.filter(|&k| placed(&k) && guests[k].uuid == uuid)
|
||||
.collect(),
|
||||
|
||||
Reference in new issue
Block a user