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("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),
),

View File

@ -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<T>(
server: &mut Server,
entity: EcsEntity,
descriptor: &str,
force_from_mount: Option<bool>,
f: impl for<'a> FnOnce(&'a mut comp::Pos) -> T,
) -> CmdResult<T> {
// TODO: Handle volume mount
let entity = server
.state
.ecs()
.read_storage::<Is<Rider>>()
.get(entity)
.and_then(|is_rider| {
server
let entity = if force_from_mount.unwrap_or(false) {
server
.state
.ecs()
.write_storage::<Is<Rider>>()
.remove(entity);
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
.ecs()
.read_resource::<UidAllocator>()
.retrieve_entity_internal(is_rider.mount.into())
})
.unwrap_or(entity);
.read_storage::<Is<VolumeRider>>()
.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::<UidAllocator>()
.retrieve_entity_internal(uid.into())?),
})
})
.transpose()?)
.unwrap_or(entity)
};
let mut maybe_pos = None;
@ -830,8 +860,10 @@ fn handle_jump(
args: Vec<String>,
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<String>,
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<String>,
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::<Locations>().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()),

View File

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

View File

@ -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>,
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<SpriteInstance>; SPRITE_LOD_LEVELS]> {
) -> Option<&'a [Instances<SpriteInstance>; 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,
)])
}
}

View File

@ -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)]