force of mount in teleporting commands

This commit is contained in:
Isse 2023-04-18 20:07:45 +02:00
parent e39790e9e4
commit 57551c479c
5 changed files with 104 additions and 53 deletions

View File

@ -461,6 +461,7 @@ impl ServerChatCommand {
Float("x", 0.0, Required), Float("x", 0.0, Required),
Float("y", 0.0, Required), Float("y", 0.0, Required),
Float("z", 0.0, Required), Float("z", 0.0, Required),
Boolean("Force from mount", "true".to_string(), Optional),
], ],
"Teleport to a position", "Teleport to a position",
Some(Admin), Some(Admin),
@ -505,6 +506,7 @@ impl ServerChatCommand {
Float("x", 0.0, Required), Float("x", 0.0, Required),
Float("y", 0.0, Required), Float("y", 0.0, Required),
Float("z", 0.0, Required), Float("z", 0.0, Required),
Boolean("Force from mount", "true".to_string(), Optional),
], ],
"Offset your current position", "Offset your current position",
Some(Admin), Some(Admin),
@ -637,7 +639,10 @@ impl ServerChatCommand {
// Uses Message because site names can contain spaces, // Uses Message because site names can contain spaces,
// which would be assumed to be separators otherwise // which would be assumed to be separators otherwise
ServerChatCommand::Site => cmd( ServerChatCommand::Site => cmd(
vec![SiteName(Required)], vec![
SiteName(Required),
Boolean("Force from mount", "true".to_string(), Optional),
],
"Teleport to a site", "Teleport to a site",
Some(Moderator), Some(Moderator),
), ),
@ -681,12 +686,18 @@ impl ServerChatCommand {
Some(Admin), Some(Admin),
), ),
ServerChatCommand::Tp => cmd( ServerChatCommand::Tp => cmd(
vec![PlayerName(Optional)], vec![
PlayerName(Optional),
Boolean("Force from mount", "true".to_string(), Optional),
],
"Teleport to another player", "Teleport to another player",
Some(Moderator), Some(Moderator),
), ),
ServerChatCommand::RtsimTp => cmd( 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", "Teleport to an rtsim npc",
Some(Moderator), Some(Moderator),
), ),

View File

@ -40,7 +40,7 @@ use common::{
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
generation::{EntityConfig, EntityInfo}, generation::{EntityConfig, EntityInfo},
link::Is, link::Is,
mounting::Rider, mounting::{Rider, VolumeRider},
npc::{self, get_npc_name}, npc::{self, get_npc_name},
outcome::Outcome, outcome::Outcome,
parse_cmd_args, parse_cmd_args,
@ -227,22 +227,52 @@ fn position_mut<T>(
server: &mut Server, server: &mut Server,
entity: EcsEntity, entity: EcsEntity,
descriptor: &str, descriptor: &str,
force_from_mount: Option<bool>,
f: impl for<'a> FnOnce(&'a mut comp::Pos) -> T, f: impl for<'a> FnOnce(&'a mut comp::Pos) -> T,
) -> CmdResult<T> { ) -> CmdResult<T> {
// TODO: Handle volume mount let entity = if force_from_mount.unwrap_or(false) {
let entity = server server
.state .state
.ecs() .ecs()
.read_storage::<Is<Rider>>() .write_storage::<Is<Rider>>()
.get(entity) .remove(entity);
.and_then(|is_rider| { server
server .state
.ecs()
.write_storage::<Is<VolumeRider>>()
.remove(entity);
entity
} else {
server
.state
.read_storage::<Is<Rider>>()
.get(entity)
.and_then(|is_rider| {
server
.state
.ecs()
.read_resource::<UidAllocator>()
.retrieve_entity_internal(is_rider.mount.into())
})
.or(server
.state .state
.ecs() .read_storage::<Is<VolumeRider>>()
.read_resource::<UidAllocator>() .get(entity)
.retrieve_entity_internal(is_rider.mount.into()) .and_then(|volume_rider| {
}) Some(match volume_rider.pos.kind {
.unwrap_or(entity); common::mounting::Volume::Terrain => {
Err("Tried to move the world.".to_string())
},
common::mounting::Volume::Entity(uid) => Ok(server
.state
.ecs()
.read_resource::<UidAllocator>()
.retrieve_entity_internal(uid.into())?),
})
})
.transpose()?)
.unwrap_or(entity)
};
let mut maybe_pos = None; let mut maybe_pos = None;
@ -830,8 +860,10 @@ fn handle_jump(
args: Vec<String>, args: Vec<String>,
action: &ServerChatCommand, action: &ServerChatCommand,
) -> CmdResult<()> { ) -> CmdResult<()> {
if let (Some(x), Some(y), Some(z)) = parse_cmd_args!(args, f32, f32, f32) { if let (Some(x), Some(y), Some(z), force_from_mount) =
position_mut(server, target, "target", |current_pos| { 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) current_pos.0 += Vec3::new(x, y, z)
}) })
} else { } else {
@ -846,8 +878,10 @@ fn handle_goto(
args: Vec<String>, args: Vec<String>,
action: &ServerChatCommand, action: &ServerChatCommand,
) -> CmdResult<()> { ) -> CmdResult<()> {
if let (Some(x), Some(y), Some(z)) = parse_cmd_args!(args, f32, f32, f32) { if let (Some(x), Some(y), Some(z), force_from_mount) =
position_mut(server, target, "target", |current_pos| { 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) current_pos.0 = Vec3::new(x, y, z)
}) })
} else { } else {
@ -865,7 +899,7 @@ fn handle_site(
action: &ServerChatCommand, action: &ServerChatCommand,
) -> CmdResult<()> { ) -> CmdResult<()> {
#[cfg(feature = "worldgen")] #[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 let site = server
.world .world
.civs() .civs()
@ -882,7 +916,7 @@ fn handle_site(
false, false,
); );
position_mut(server, target, "target", |current_pos| { position_mut(server, target, "target", force_from_mount, |current_pos| {
current_pos.0 = site_pos current_pos.0 = site_pos
}) })
} else { } else {
@ -907,7 +941,7 @@ fn handle_respawn(
.ok_or("No waypoint set")? .ok_or("No waypoint set")?
.get_pos(); .get_pos();
position_mut(server, target, "target", |current_pos| { position_mut(server, target, "target", Some(true), |current_pos| {
current_pos.0 = waypoint; current_pos.0 = waypoint;
}) })
} }
@ -1206,7 +1240,8 @@ fn handle_tp(
args: Vec<String>, args: Vec<String>,
action: &ServerChatCommand, action: &ServerChatCommand,
) -> CmdResult<()> { ) -> 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 find_alias(server.state.ecs(), &alias)?.0
} else if client != target { } else if client != target {
client client
@ -1214,7 +1249,7 @@ fn handle_tp(
return Err(action.help_string()); return Err(action.help_string());
}; };
let player_pos = position(server, player, "player")?; 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 *target_pos = player_pos
}) })
} }
@ -1227,7 +1262,8 @@ fn handle_rtsim_tp(
action: &ServerChatCommand, action: &ServerChatCommand,
) -> CmdResult<()> { ) -> CmdResult<()> {
use crate::rtsim::RtSim; 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. // TODO: Take some other identifier than an integer to this command.
server server
.state .state
@ -1243,7 +1279,7 @@ fn handle_rtsim_tp(
} else { } else {
return Err(action.help_string()); 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; target_pos.0 = pos;
}) })
} }
@ -3935,7 +3971,7 @@ fn handle_location(
if let Some(name) = parse_cmd_args!(args, String) { if let Some(name) = parse_cmd_args!(args, String) {
let loc = server.state.ecs().read_resource::<Locations>().get(&name); let loc = server.state.ecs().read_resource::<Locations>().get(&name);
match loc { 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; target_pos.0 = loc;
}), }),
Err(e) => Err(e.to_string()), Err(e) => Err(e.to_string()),

View File

@ -878,9 +878,7 @@ where
pub fn get_sprites( pub fn get_sprites(
&self, &self,
body: Skel::Body, body: Skel::Body,
) -> Option< ) -> Option<&[Instances<SpriteInstance>; SPRITE_LOD_LEVELS]> {
&[Instances<SpriteInstance>; SPRITE_LOD_LEVELS],
> {
let key = FigureKey { let key = FigureKey {
body, body,
item_key: None, item_key: None,

View File

@ -473,10 +473,15 @@ impl FigureMgrStates {
.count() .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 where
EcsEntity: Borrow<Q>, EcsEntity: Borrow<Q>,
Q: Hash + Eq, { Q: Hash + Eq,
{
match body { match body {
Body::Ship(body) => { Body::Ship(body) => {
if matches!(body, ship::Body::Volume) { if matches!(body, ship::Body::Volume) {
@ -486,7 +491,7 @@ impl FigureMgrStates {
} else { } else {
None None
} }
} },
_ => None, _ => None,
} }
} }
@ -6345,8 +6350,9 @@ impl FigureMgr {
// Don't render dead entities // Don't render dead entities
.filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead)) .filter(|(_, _, _, _, health, _)| health.map_or(true, |h| !h.is_dead))
{ {
if let Some((sprite_instances, data)) = if let Some((sprite_instances, data)) = self
self.get_sprite_instances(entity, body, collider).zip(self.states.get_terrain_locals(body, &entity)) .get_sprite_instances(entity, body, collider)
.zip(self.states.get_terrain_locals(body, &entity))
{ {
let dist = collider let dist = collider
.and_then(|collider| { .and_then(|collider| {
@ -6973,8 +6979,7 @@ impl FigureMgr {
entity: EcsEntity, entity: EcsEntity,
body: &Body, body: &Body,
collider: Option<&Collider>, collider: Option<&Collider>,
) -> Option< ) -> Option<&'a [Instances<SpriteInstance>; SPRITE_LOD_LEVELS]> {
&'a [Instances<SpriteInstance>; SPRITE_LOD_LEVELS]> {
match body { match body {
Body::Ship(body) => { Body::Ship(body) => {
if let Some(Collider::Volume(vol)) = collider { if let Some(Collider::Volume(vol)) = collider {
@ -7359,24 +7364,28 @@ pub trait FigureData: Sized {
} }
impl FigureData for () { 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 { impl FigureData for BoundTerrainLocals {
fn new(renderer: &mut Renderer) -> Self { 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) { fn update(&mut self, renderer: &mut Renderer, parameters: &FigureUpdateCommonParameters) {
renderer.update_consts(self, &[ renderer.update_consts(self, &[TerrainLocals::new(
TerrainLocals::new(parameters.pos.into(), parameters.ori.into_vec4().into(), Vec2::zero(), 0.0), parameters.pos.into(),
]) parameters.ori.into_vec4().into(),
Vec2::zero(),
0.0,
)])
} }
} }

View File

@ -3,10 +3,7 @@ use super::{
load::{BodySpec, ShipBoneMeshes}, load::{BodySpec, ShipBoneMeshes},
EcsEntity, EcsEntity,
}; };
use common::{ use common::{assets, comp::ship::figuredata::VoxelCollider};
assets,
comp::ship::figuredata::VoxelCollider,
};
use std::{convert::TryFrom, sync::Arc}; use std::{convert::TryFrom, sync::Arc};
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]