From a151a6f5509f7de5ddcbbbdd02df514fcdd23098 Mon Sep 17 00:00:00 2001 From: Isse Date: Thu, 23 Nov 2023 22:22:34 +0100 Subject: [PATCH] tether length argument --- common/src/cmd.rs | 5 ++++- server/src/cmd.rs | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 0a60c8adbb..1d84f1ed5f 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -900,7 +900,10 @@ impl ServerChatCommand { cmd(vec![], "Repairs all equipped items", Some(Admin)) }, ServerChatCommand::Tether => cmd( - vec![EntityTarget(Required)], + vec![ + EntityTarget(Required), + Boolean("automatic length", "true".to_string(), Optional), + ], "Tether another entity to yourself", Some(Admin), ), diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 5612ff95ed..2862b3ac23 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -4564,18 +4564,46 @@ fn handle_tether( args: Vec, action: &ServerChatCommand, ) -> CmdResult<()> { - if let Some(entity_target) = parse_cmd_args!(args, EntityTarget) { + enum Either { + Left(A), + Right(B), + } + + impl FromStr for Either { + type Err = B::Err; + + fn from_str(s: &str) -> Result { + match A::from_str(s) { + Ok(a) => Ok(Either::Left(a)), + Err(_) => match B::from_str(s) { + Ok(b) => Ok(Either::Right(b)), + Err(e) => Err(e), + }, + } + } + } + if let (Some(entity_target), length) = parse_cmd_args!(args, EntityTarget, Either) { let entity_target = get_entity_target(entity_target, server)?; let tether_leader = server.state.ecs().uid_from_entity(target); let tether_follower = server.state.ecs().uid_from_entity(entity_target); if let (Some(leader), Some(follower)) = (tether_leader, tether_follower) { - let tether_length = tether_leader - .and_then(|uid| server.state.ecs().entity_from_uid(uid)) - .and_then(|e| server.state.read_component_cloned::(e)) + let base_len = server + .state + .read_component_cloned::(target) .map(|b| b.dimensions().y * 1.5 + 1.0) .unwrap_or(6.0); + let tether_length = match length { + Some(Either::Left(l)) => l.max(0.0) + base_len, + Some(Either::Right(true)) => { + let leader_pos = position(server, target, "leader")?; + let follower_pos = position(server, entity_target, "follower")?; + + leader_pos.0.distance(follower_pos.0) + base_len + }, + _ => base_len, + }; server .state .link(Tethered {