From 12cf8847c867de29a0943af0ac76dbf2cf5fae84 Mon Sep 17 00:00:00 2001 From: Treeco <5021038-Treeco@users.noreply.gitlab.com> Date: Sat, 27 Mar 2021 00:38:56 +0000 Subject: [PATCH] Added command to teleport to sites by name --- common/src/cmd.rs | 6 ++++ server/src/cmd.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/common/src/cmd.rs b/common/src/cmd.rs index a1692dbabf..e2868f0f10 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -80,6 +80,7 @@ pub enum ChatCommand { Safezone, Say, SetMotd, + Site, SkillPoint, Spawn, Sudo, @@ -140,6 +141,7 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[ ChatCommand::Safezone, ChatCommand::Say, ChatCommand::SetMotd, + ChatCommand::Site, ChatCommand::SkillPoint, ChatCommand::Spawn, ChatCommand::Sudo, @@ -438,6 +440,9 @@ impl ChatCommand { ChatCommand::SetMotd => { cmd(vec![Message(Optional)], "Set the server description", Admin) }, + // Uses Message because site names can contain spaces, which would be assumed to be + // separators otherwise + ChatCommand::Site => cmd(vec![Message(Required)], "Teleport to a site", Admin), ChatCommand::SkillPoint => cmd( vec![ Enum("skill tree", SKILL_TREES.clone(), Required), @@ -546,6 +551,7 @@ impl ChatCommand { ChatCommand::Safezone => "safezone", ChatCommand::Say => "say", ChatCommand::SetMotd => "set_motd", + ChatCommand::Site => "site", ChatCommand::SkillPoint => "skill_point", ChatCommand::Spawn => "spawn", ChatCommand::Sudo => "sudo", diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 90796fce26..61a49ca553 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -127,6 +127,7 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler { ChatCommand::Safezone => handle_safezone, ChatCommand::Say => handle_say, ChatCommand::SetMotd => handle_set_motd, + ChatCommand::Site => handle_site, ChatCommand::SkillPoint => handle_skill_point, ChatCommand::Spawn => handle_spawn, ChatCommand::Sudo => handle_sudo, @@ -463,6 +464,91 @@ fn handle_goto( } } +fn handle_site( + server: &mut Server, + client: EcsEntity, + target: EcsEntity, + args: String, + action: &ChatCommand, +) { + if let Ok(dest_name) = scan_fmt!(&args, &action.arg_fmt(), String) { + if server + .state + .read_component_copied::(target) + .is_some() + { + match server.world.civs().sites().find(|site| { + site.site_tmp + .map_or(false, |id| server.index.sites[id].name() == dest_name) + }) { + Some(site) => { + // The bulk of this code is to find the z coordinate to teleport to, searching + // for the lowest available one. Copied nearly verbatim from server's lib.rs + let dest_chunk = site.center; + // Unwrapping because generate_chunk only returns err when should_continue evals + // to true + let (tc, _cs) = server + .world + .generate_chunk(server.index.as_index_ref(), dest_chunk, || false) + .unwrap(); + let min_z = tc.get_min_z(); + let max_z = tc.get_max_z(); + + let pos = TerrainChunkSize::center_wpos(dest_chunk); + let pos = Vec3::new(pos.x, pos.y, min_z); + let pos = { + use common::vol::ReadVol; + (0..(max_z - min_z)) + .map(|z_diff| pos + Vec3::unit_z() * z_diff) + .find(|test_pos| { + let chunk_relative_xy = + test_pos.xy().map2(TerrainChunkSize::RECT_SIZE, |e, sz| { + e.rem_euclid(sz as i32) + }); + tc.get( + Vec3::new(chunk_relative_xy.x, chunk_relative_xy.y, test_pos.z) + - Vec3::unit_z(), + ) + .map_or(false, |b| b.is_filled()) + && (0..3).all(|z| { + tc.get( + Vec3::new( + chunk_relative_xy.x, + chunk_relative_xy.y, + test_pos.z, + ) + Vec3::unit_z() * z, + ) + .map_or(true, |b| !b.is_solid()) + }) + }) + .unwrap_or(pos) + .map(|e| e as f32) + + 0.5 + }; + server.state.write_component(target, comp::Pos(pos)); + server.state.write_component(target, comp::ForceUpdate); + }, + None => { + server.notify_client( + client, + ServerGeneral::server_msg(ChatType::CommandError, "Site not found"), + ); + }, + }; + } else { + server.notify_client( + client, + ServerGeneral::server_msg(ChatType::CommandError, "You have no position."), + ); + } + } else { + server.notify_client( + client, + ServerGeneral::server_msg(ChatType::CommandError, action.help_string()), + ); + } +} + fn handle_home( server: &mut Server, client: EcsEntity,