diff --git a/common/src/cmd.rs b/common/src/cmd.rs index 1e565d1c7b..7810cf2777 100644 --- a/common/src/cmd.rs +++ b/common/src/cmd.rs @@ -461,6 +461,7 @@ impl ServerChatCommand { Float("x", 0.0, Required), Float("y", 0.0, Required), Float("z", 0.0, Required), + Boolean("Force from mount", "true".to_string(), Optional), ], "Teleport to a position", Some(Admin), @@ -505,6 +506,7 @@ impl ServerChatCommand { Float("x", 0.0, Required), Float("y", 0.0, Required), Float("z", 0.0, Required), + Boolean("Force from mount", "true".to_string(), Optional), ], "Offset your current position", Some(Admin), @@ -637,7 +639,10 @@ impl ServerChatCommand { // Uses Message because site names can contain spaces, // which would be assumed to be separators otherwise ServerChatCommand::Site => cmd( - vec![SiteName(Required)], + vec![ + SiteName(Required), + Boolean("Force from mount", "true".to_string(), Optional), + ], "Teleport to a site", Some(Moderator), ), @@ -681,12 +686,18 @@ impl ServerChatCommand { Some(Admin), ), ServerChatCommand::Tp => cmd( - vec![PlayerName(Optional)], + vec![ + PlayerName(Optional), + Boolean("Force from mount", "true".to_string(), Optional), + ], "Teleport to another player", Some(Moderator), ), ServerChatCommand::RtsimTp => cmd( - vec![Integer("npc index", 0, Required)], + vec![ + Integer("npc index", 0, Required), + Boolean("Force from mount", "true".to_string(), Optional), + ], "Teleport to an rtsim npc", Some(Moderator), ), diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 0b3c664922..8d1fdb7fae 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -40,7 +40,7 @@ use common::{ event::{EventBus, ServerEvent}, generation::{EntityConfig, EntityInfo}, link::Is, - mounting::Rider, + mounting::{Rider, VolumeRider}, npc::{self, get_npc_name}, outcome::Outcome, parse_cmd_args, @@ -227,22 +227,52 @@ fn position_mut( server: &mut Server, entity: EcsEntity, descriptor: &str, + force_from_mount: Option, f: impl for<'a> FnOnce(&'a mut comp::Pos) -> T, ) -> CmdResult { - // TODO: Handle volume mount - let entity = server - .state - .ecs() - .read_storage::>() - .get(entity) - .and_then(|is_rider| { - server + let entity = if force_from_mount.unwrap_or(false) { + server + .state + .ecs() + .write_storage::>() + .remove(entity); + server + .state + .ecs() + .write_storage::>() + .remove(entity); + entity + } else { + server + .state + .read_storage::>() + .get(entity) + .and_then(|is_rider| { + server + .state + .ecs() + .read_resource::() + .retrieve_entity_internal(is_rider.mount.into()) + }) + .or(server .state - .ecs() - .read_resource::() - .retrieve_entity_internal(is_rider.mount.into()) - }) - .unwrap_or(entity); + .read_storage::>() + .get(entity) + .and_then(|volume_rider| { + Some(match volume_rider.pos.kind { + common::mounting::Volume::Terrain => { + Err("Tried to move the world.".to_string()) + }, + common::mounting::Volume::Entity(uid) => Ok(server + .state + .ecs() + .read_resource::() + .retrieve_entity_internal(uid.into())?), + }) + }) + .transpose()?) + .unwrap_or(entity) + }; let mut maybe_pos = None; @@ -830,8 +860,10 @@ fn handle_jump( args: Vec, action: &ServerChatCommand, ) -> CmdResult<()> { - if let (Some(x), Some(y), Some(z)) = parse_cmd_args!(args, f32, f32, f32) { - position_mut(server, target, "target", |current_pos| { + if let (Some(x), Some(y), Some(z), force_from_mount) = + parse_cmd_args!(args, f32, f32, f32, bool) + { + position_mut(server, target, "target", force_from_mount, |current_pos| { current_pos.0 += Vec3::new(x, y, z) }) } else { @@ -846,8 +878,10 @@ fn handle_goto( args: Vec, action: &ServerChatCommand, ) -> CmdResult<()> { - if let (Some(x), Some(y), Some(z)) = parse_cmd_args!(args, f32, f32, f32) { - position_mut(server, target, "target", |current_pos| { + if let (Some(x), Some(y), Some(z), force_from_mount) = + parse_cmd_args!(args, f32, f32, f32, bool) + { + position_mut(server, target, "target", force_from_mount, |current_pos| { current_pos.0 = Vec3::new(x, y, z) }) } else { @@ -865,7 +899,7 @@ fn handle_site( action: &ServerChatCommand, ) -> CmdResult<()> { #[cfg(feature = "worldgen")] - if let Some(dest_name) = parse_cmd_args!(args, String) { + if let (Some(dest_name), force_from_mount) = parse_cmd_args!(args, String, bool) { let site = server .world .civs() @@ -882,7 +916,7 @@ fn handle_site( false, ); - position_mut(server, target, "target", |current_pos| { + position_mut(server, target, "target", force_from_mount, |current_pos| { current_pos.0 = site_pos }) } else { @@ -907,7 +941,7 @@ fn handle_respawn( .ok_or("No waypoint set")? .get_pos(); - position_mut(server, target, "target", |current_pos| { + position_mut(server, target, "target", Some(true), |current_pos| { current_pos.0 = waypoint; }) } @@ -1206,7 +1240,8 @@ fn handle_tp( args: Vec, action: &ServerChatCommand, ) -> CmdResult<()> { - let player = if let Some(alias) = parse_cmd_args!(args, String) { + let (player, force_from_mount) = parse_cmd_args!(args, String, bool); + let player = if let Some(alias) = player { find_alias(server.state.ecs(), &alias)?.0 } else if client != target { client @@ -1214,7 +1249,7 @@ fn handle_tp( return Err(action.help_string()); }; let player_pos = position(server, player, "player")?; - position_mut(server, target, "target", |target_pos| { + position_mut(server, target, "target", force_from_mount, |target_pos| { *target_pos = player_pos }) } @@ -1227,7 +1262,8 @@ fn handle_rtsim_tp( action: &ServerChatCommand, ) -> CmdResult<()> { use crate::rtsim::RtSim; - let pos = if let Some(id) = parse_cmd_args!(args, u32) { + let (npc_index, force_from_mount) = parse_cmd_args!(args, u32, bool); + let pos = if let Some(id) = npc_index { // TODO: Take some other identifier than an integer to this command. server .state @@ -1243,7 +1279,7 @@ fn handle_rtsim_tp( } else { return Err(action.help_string()); }; - position_mut(server, target, "target", |target_pos| { + position_mut(server, target, "target", force_from_mount, |target_pos| { target_pos.0 = pos; }) } @@ -3935,7 +3971,7 @@ fn handle_location( if let Some(name) = parse_cmd_args!(args, String) { let loc = server.state.ecs().read_resource::().get(&name); match loc { - Ok(loc) => position_mut(server, target, "target", |target_pos| { + Ok(loc) => position_mut(server, target, "target", Some(true), |target_pos| { target_pos.0 = loc; }), Err(e) => Err(e.to_string()), diff --git a/voxygen/src/scene/figure/cache.rs b/voxygen/src/scene/figure/cache.rs index 03d27c02cc..760dafd949 100644 --- a/voxygen/src/scene/figure/cache.rs +++ b/voxygen/src/scene/figure/cache.rs @@ -878,9 +878,7 @@ where pub fn get_sprites( &self, body: Skel::Body, - ) -> Option< - &[Instances; SPRITE_LOD_LEVELS], - > { + ) -> Option<&[Instances; SPRITE_LOD_LEVELS]> { let key = FigureKey { body, item_key: None, diff --git a/voxygen/src/scene/figure/mod.rs b/voxygen/src/scene/figure/mod.rs index 782ff0a2c5..b99521ff6f 100644 --- a/voxygen/src/scene/figure/mod.rs +++ b/voxygen/src/scene/figure/mod.rs @@ -473,10 +473,15 @@ impl FigureMgrStates { .count() } - fn get_terrain_locals<'a, Q: ?Sized>(&'a self, body: &Body, entity: &Q) -> Option<&'a BoundTerrainLocals> + fn get_terrain_locals<'a, Q: ?Sized>( + &'a self, + body: &Body, + entity: &Q, + ) -> Option<&'a BoundTerrainLocals> where EcsEntity: Borrow, - Q: Hash + Eq, { + Q: Hash + Eq, + { match body { Body::Ship(body) => { if matches!(body, ship::Body::Volume) { @@ -486,7 +491,7 @@ impl FigureMgrStates { } else { None } - } + }, _ => None, } } @@ -6345,8 +6350,9 @@ impl FigureMgr { // Don't render dead entities .filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) { - if let Some((sprite_instances, data)) = - self.get_sprite_instances(entity, body, collider).zip(self.states.get_terrain_locals(body, &entity)) + if let Some((sprite_instances, data)) = self + .get_sprite_instances(entity, body, collider) + .zip(self.states.get_terrain_locals(body, &entity)) { let dist = collider .and_then(|collider| { @@ -6973,8 +6979,7 @@ impl FigureMgr { entity: EcsEntity, body: &Body, collider: Option<&Collider>, - ) -> Option< - &'a [Instances; SPRITE_LOD_LEVELS]> { + ) -> Option<&'a [Instances; SPRITE_LOD_LEVELS]> { match body { Body::Ship(body) => { if let Some(Collider::Volume(vol)) = collider { @@ -7359,24 +7364,28 @@ pub trait FigureData: Sized { } impl FigureData for () { - fn new(_renderer: &mut Renderer) -> Self { - () - } + fn new(_renderer: &mut Renderer) {} - fn update(&mut self, _renderer: &mut Renderer, _parameters: &FigureUpdateCommonParameters) { - () - } + fn update(&mut self, _renderer: &mut Renderer, _parameters: &FigureUpdateCommonParameters) {} } impl FigureData for BoundTerrainLocals { fn new(renderer: &mut Renderer) -> Self { - renderer.create_terrain_bound_locals(&[TerrainLocals::new(Vec3::zero(), Quaternion::identity(), Vec2::zero(), 0.0)]) + renderer.create_terrain_bound_locals(&[TerrainLocals::new( + Vec3::zero(), + Quaternion::identity(), + Vec2::zero(), + 0.0, + )]) } fn update(&mut self, renderer: &mut Renderer, parameters: &FigureUpdateCommonParameters) { - renderer.update_consts(self, &[ - TerrainLocals::new(parameters.pos.into(), parameters.ori.into_vec4().into(), Vec2::zero(), 0.0), - ]) + renderer.update_consts(self, &[TerrainLocals::new( + parameters.pos.into(), + parameters.ori.into_vec4().into(), + Vec2::zero(), + 0.0, + )]) } } diff --git a/voxygen/src/scene/figure/volume.rs b/voxygen/src/scene/figure/volume.rs index 41bc3c927e..c01e1e0e6e 100644 --- a/voxygen/src/scene/figure/volume.rs +++ b/voxygen/src/scene/figure/volume.rs @@ -3,10 +3,7 @@ use super::{ load::{BodySpec, ShipBoneMeshes}, EcsEntity, }; -use common::{ - assets, - comp::ship::figuredata::VoxelCollider, -}; +use common::{assets, comp::ship::figuredata::VoxelCollider}; use std::{convert::TryFrom, sync::Arc}; #[derive(Copy, Clone, PartialEq, Eq, Hash)]