Added command to teleport to sites by name

This commit is contained in:
Treeco 2021-03-27 00:38:56 +00:00
parent f16c2b8b4c
commit 12cf8847c8
2 changed files with 92 additions and 0 deletions

View File

@ -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",

View File

@ -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::<comp::Pos>(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,