mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'isse/spectator-fixes' into 'master'
Various spectator fixes. See merge request veloren/veloren!3534
This commit is contained in:
commit
6c17f7b95b
@ -30,7 +30,7 @@ use common::{
|
||||
slot::{EquipSlot, InvSlotId, Slot},
|
||||
CharacterState, ChatMode, ControlAction, ControlEvent, Controller, ControllerInputs,
|
||||
GroupManip, InputKind, InventoryAction, InventoryEvent, InventoryUpdateEvent,
|
||||
MapMarkerChange, Pos, UtteranceKind,
|
||||
MapMarkerChange, UtteranceKind,
|
||||
},
|
||||
event::{EventBus, LocalEvent},
|
||||
grid::Grid,
|
||||
@ -106,6 +106,7 @@ pub enum Event {
|
||||
CharacterEdited(CharacterId),
|
||||
CharacterError(String),
|
||||
MapMarker(comp::MapMarkerUpdate),
|
||||
StartSpectate(Vec3<f32>),
|
||||
SpectatePosition(Vec3<f32>),
|
||||
}
|
||||
|
||||
@ -881,7 +882,7 @@ impl Client {
|
||||
pub fn request_character(&mut self, character_id: CharacterId) {
|
||||
self.send_msg(ClientGeneral::Character(character_id));
|
||||
|
||||
//Assume we are in_game unless server tells us otherwise
|
||||
// Assume we are in_game unless server tells us otherwise
|
||||
self.presence = Some(PresenceKind::Character(character_id));
|
||||
}
|
||||
|
||||
@ -889,7 +890,6 @@ impl Client {
|
||||
pub fn request_spectate(&mut self) {
|
||||
self.send_msg(ClientGeneral::Spectate);
|
||||
|
||||
//Assume we are in_game unless server tells us otherwise
|
||||
self.presence = Some(PresenceKind::Spectator);
|
||||
}
|
||||
|
||||
@ -1348,16 +1348,24 @@ impl Client {
|
||||
self.send_msg(ClientGeneral::UpdateMapMarker(event));
|
||||
}
|
||||
|
||||
pub fn spectate_position(&mut self, pos: Vec3<f32>) {
|
||||
if let Some(position) = self
|
||||
/// Set the current position to spectate, returns true if the client's
|
||||
/// player has a Pos component to write to.
|
||||
pub fn spectate_position(&mut self, pos: Vec3<f32>) -> bool {
|
||||
let write = if let Some(position) = self
|
||||
.state
|
||||
.ecs()
|
||||
.write_storage::<comp::Pos>()
|
||||
.get_mut(self.entity())
|
||||
{
|
||||
position.0 = pos;
|
||||
true
|
||||
} else {
|
||||
false
|
||||
};
|
||||
if write {
|
||||
self.send_msg(ClientGeneral::SpectatePosition(pos));
|
||||
}
|
||||
self.send_msg(ClientGeneral::SpectatePosition(pos));
|
||||
write
|
||||
}
|
||||
|
||||
/// Checks whether a player can swap their weapon+ability `Loadout` settings
|
||||
@ -2346,12 +2354,7 @@ impl Client {
|
||||
},
|
||||
ServerGeneral::SpectatorSuccess(spawn_point) => {
|
||||
if let Some(vd) = self.view_distance {
|
||||
self.state
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(self.entity(), Pos(spawn_point))
|
||||
.expect("This shouldn't exist");
|
||||
events.push(Event::SpectatePosition(spawn_point));
|
||||
events.push(Event::StartSpectate(spawn_point));
|
||||
debug!("client is now in ingame state on server");
|
||||
self.set_view_distance(vd);
|
||||
}
|
||||
|
@ -37,6 +37,8 @@ pub struct ServerProfile {
|
||||
pub characters: HashMap<CharacterId, CharacterProfile>,
|
||||
/// Selected character in the chararacter selection screen
|
||||
pub selected_character: Option<CharacterId>,
|
||||
/// Last spectate position
|
||||
pub spectate_position: Option<vek::Vec3<f32>>,
|
||||
}
|
||||
|
||||
impl Default for ServerProfile {
|
||||
@ -44,6 +46,7 @@ impl Default for ServerProfile {
|
||||
ServerProfile {
|
||||
characters: HashMap::new(),
|
||||
selected_character: None,
|
||||
spectate_position: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -192,6 +195,41 @@ impl Profile {
|
||||
.selected_character = selected_character;
|
||||
}
|
||||
|
||||
/// Get the selected_character for the provided server.
|
||||
///
|
||||
/// if the server does not exist then the default spectate_position (None)
|
||||
/// is returned.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * server - current server the player is on.
|
||||
pub fn get_spectate_position(&self, server: &str) -> Option<vek::Vec3<f32>> {
|
||||
self.servers
|
||||
.get(server)
|
||||
.map(|s| s.spectate_position)
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
/// Set the spectate_position for the provided server.
|
||||
///
|
||||
/// If the server does not exist then the appropriate fields
|
||||
/// will be initialised and the selected_character added.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * server - current server the player is on.
|
||||
/// * spectate_position - option containing the position we're spectating
|
||||
pub fn set_spectate_position(
|
||||
&mut self,
|
||||
server: &str,
|
||||
spectate_position: Option<vek::Vec3<f32>>,
|
||||
) {
|
||||
self.servers
|
||||
.entry(server.to_string())
|
||||
.or_insert(ServerProfile::default())
|
||||
.spectate_position = spectate_position;
|
||||
}
|
||||
|
||||
/// Save the current profile to disk.
|
||||
fn save_to_file(&self, config_dir: &Path) -> std::io::Result<()> {
|
||||
let path = Profile::get_path(config_dir);
|
||||
|
@ -5706,7 +5706,7 @@ impl FigureMgr {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render_player<'a>(
|
||||
pub fn render_viewpoint<'a>(
|
||||
&'a self,
|
||||
drawer: &mut FigureDrawer<'_, 'a>,
|
||||
state: &State,
|
||||
@ -5774,7 +5774,7 @@ impl FigureMgr {
|
||||
entity: EcsEntity,
|
||||
body: &Body,
|
||||
inventory: Option<&Inventory>,
|
||||
is_player: bool,
|
||||
is_viewpoint: bool,
|
||||
pos: Vec3<f32>,
|
||||
figure_lod_render_distance: f32,
|
||||
mut_count: usize,
|
||||
@ -5783,14 +5783,14 @@ impl FigureMgr {
|
||||
) -> Option<FigureModelRef> {
|
||||
let body = *body;
|
||||
|
||||
let player_camera_mode = if is_player {
|
||||
let viewpoint_camera_mode = if is_viewpoint {
|
||||
camera.get_mode()
|
||||
} else {
|
||||
CameraMode::default()
|
||||
};
|
||||
let focus_pos = camera.get_focus_pos();
|
||||
let cam_pos = camera.dependents().cam_pos + focus_pos.map(|e| e.trunc());
|
||||
let character_state = if is_player { character_state } else { None };
|
||||
let character_state = if is_viewpoint { character_state } else { None };
|
||||
|
||||
let FigureMgr {
|
||||
col_lights: ref col_lights_,
|
||||
@ -5847,7 +5847,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5864,7 +5864,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5881,7 +5881,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5898,7 +5898,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5915,7 +5915,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5932,7 +5932,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5949,7 +5949,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5966,7 +5966,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -5983,7 +5983,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6000,7 +6000,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6017,7 +6017,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6034,7 +6034,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6051,7 +6051,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6068,7 +6068,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6085,7 +6085,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6102,7 +6102,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
item_key,
|
||||
),
|
||||
@ -6121,7 +6121,7 @@ impl FigureMgr {
|
||||
body,
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
@ -6139,7 +6139,7 @@ impl FigureMgr {
|
||||
VolumeKey { entity, mut_count },
|
||||
inventory,
|
||||
tick,
|
||||
player_camera_mode,
|
||||
viewpoint_camera_mode,
|
||||
character_state,
|
||||
None,
|
||||
),
|
||||
|
@ -562,7 +562,7 @@ impl Scene {
|
||||
let yaw = siny_cosp.atan2(cosy_cosp);
|
||||
|
||||
self.camera
|
||||
.set_orientation_instant(Vec3::new(yaw, pitch, -roll));
|
||||
.set_orientation_instant(Vec3::new(-yaw, pitch, roll));
|
||||
}
|
||||
|
||||
// Alter camera position to match player.
|
||||
@ -1192,7 +1192,7 @@ impl Scene {
|
||||
&'a self,
|
||||
drawer: &mut Drawer<'a>,
|
||||
state: &State,
|
||||
player_entity: EcsEntity,
|
||||
viewpoint_entity: EcsEntity,
|
||||
tick: u64,
|
||||
scene_data: &SceneData,
|
||||
) {
|
||||
@ -1251,10 +1251,10 @@ impl Scene {
|
||||
|
||||
prof_span!(guard, "main pass");
|
||||
if let Some(mut first_pass) = drawer.first_pass() {
|
||||
self.figure_mgr.render_player(
|
||||
self.figure_mgr.render_viewpoint(
|
||||
&mut first_pass.draw_figures(),
|
||||
state,
|
||||
player_entity,
|
||||
viewpoint_entity,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
@ -1264,7 +1264,7 @@ impl Scene {
|
||||
self.figure_mgr.render(
|
||||
&mut first_pass.draw_figures(),
|
||||
state,
|
||||
player_entity,
|
||||
viewpoint_entity,
|
||||
tick,
|
||||
camera_data,
|
||||
);
|
||||
|
@ -81,7 +81,6 @@ pub struct SessionState {
|
||||
selected_block: Block,
|
||||
walk_forward_dir: Vec2<f32>,
|
||||
walk_right_dir: Vec2<f32>,
|
||||
freefly_vel: Vec3<f32>,
|
||||
free_look: bool,
|
||||
auto_walk: bool,
|
||||
camera_clamp: bool,
|
||||
@ -143,7 +142,6 @@ impl SessionState {
|
||||
selected_block: Block::new(BlockKind::Misc, Rgb::broadcast(255)),
|
||||
walk_forward_dir,
|
||||
walk_right_dir,
|
||||
freefly_vel: Vec3::zero(),
|
||||
free_look: false,
|
||||
auto_walk: false,
|
||||
camera_clamp: false,
|
||||
@ -368,6 +366,22 @@ impl SessionState {
|
||||
client::Event::MapMarker(event) => {
|
||||
self.hud.show.update_map_markers(event);
|
||||
},
|
||||
client::Event::StartSpectate(spawn_point) => {
|
||||
let server_name = &client.server_info().name;
|
||||
let spawn_point = global_state
|
||||
.profile
|
||||
.get_spectate_position(server_name)
|
||||
.unwrap_or(spawn_point);
|
||||
|
||||
client
|
||||
.state()
|
||||
.ecs()
|
||||
.write_storage()
|
||||
.insert(client.entity(), Pos(spawn_point))
|
||||
.expect("This shouldn't exist");
|
||||
|
||||
self.scene.camera_mut().force_focus_pos(spawn_point);
|
||||
},
|
||||
client::Event::SpectatePosition(pos) => {
|
||||
self.scene.camera_mut().force_focus_pos(pos);
|
||||
},
|
||||
@ -493,7 +507,14 @@ impl PlayState for SessionState {
|
||||
drop(client);
|
||||
|
||||
if presence == PresenceKind::Spectator {
|
||||
self.client.borrow_mut().spectate_position(cam_pos);
|
||||
let mut client = self.client.borrow_mut();
|
||||
if client.spectate_position(cam_pos) {
|
||||
let server_name = &client.server_info().name;
|
||||
global_state.profile.set_spectate_position(
|
||||
server_name,
|
||||
Some(self.scene.camera().get_focus_pos()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Nearest block to consider with GameInput primary or secondary key.
|
||||
@ -906,11 +927,9 @@ impl PlayState for SessionState {
|
||||
let client = self.client.borrow();
|
||||
camera.next_mode(
|
||||
client.is_moderator(),
|
||||
client
|
||||
.presence()
|
||||
.map(|presence| presence != PresenceKind::Spectator)
|
||||
.unwrap_or(true)
|
||||
|| self.viewpoint_entity.is_some(),
|
||||
client.presence().map_or(true, |presence| {
|
||||
presence != PresenceKind::Spectator
|
||||
}) || self.viewpoint_entity.is_some(),
|
||||
);
|
||||
},
|
||||
GameInput::Select => {
|
||||
@ -1091,46 +1110,32 @@ impl PlayState for SessionState {
|
||||
self.inputs.move_dir =
|
||||
self.walk_right_dir * axis_right + self.walk_forward_dir * axis_up;
|
||||
}
|
||||
self.freefly_vel = Vec3::zero();
|
||||
},
|
||||
CameraMode::Freefly => {
|
||||
// Move the camera freely in 3d space. Apply acceleration so that
|
||||
// the movement feels more natural and controlled.
|
||||
const FREEFLY_ACCEL: f32 = 120.0;
|
||||
const FREEFLY_DAMPING: f32 = 80.0;
|
||||
const FREEFLY_MAX_SPEED: f32 = 50.0;
|
||||
const FREEFLY_SPEED: f32 = 50.0;
|
||||
const FREEFLY_SPEED_BOOST: f32 = 5.0;
|
||||
|
||||
let forward = self.scene.camera().forward();
|
||||
let right = self.scene.camera().right();
|
||||
let dir = right * axis_right + forward * axis_up;
|
||||
let forward = self.scene.camera().forward().with_z(0.0).normalized();
|
||||
let right = self.scene.camera().right().with_z(0.0).normalized();
|
||||
let up = Vec3::unit_z();
|
||||
let up_axis = self.key_state.swim_up as i32 as f32
|
||||
- self.key_state.swim_down as i32 as f32;
|
||||
|
||||
if self.freefly_vel.magnitude_squared() > 0.01 {
|
||||
let new_vel = self.freefly_vel
|
||||
- self.freefly_vel.normalized() * (FREEFLY_DAMPING * dt);
|
||||
if self.freefly_vel.dot(new_vel) > 0.0 {
|
||||
self.freefly_vel = new_vel;
|
||||
let dir = (right * axis_right + forward * axis_up + up * up_axis).normalized();
|
||||
|
||||
let speed = FREEFLY_SPEED
|
||||
* if self.inputs_state.contains(&GameInput::SpectateSpeedBoost) {
|
||||
FREEFLY_SPEED_BOOST
|
||||
} else {
|
||||
self.freefly_vel = Vec3::zero();
|
||||
}
|
||||
}
|
||||
if dir.magnitude_squared() > 0.01 {
|
||||
self.freefly_vel += dir * (FREEFLY_ACCEL * dt);
|
||||
if self.freefly_vel.magnitude() > FREEFLY_MAX_SPEED {
|
||||
self.freefly_vel = self.freefly_vel.normalized() * FREEFLY_MAX_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
let boost = if self.inputs_state.contains(&GameInput::SpectateSpeedBoost) {
|
||||
FREEFLY_SPEED_BOOST
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
1.0
|
||||
};
|
||||
|
||||
let pos = self.scene.camera().get_focus_pos();
|
||||
self.scene
|
||||
.camera_mut()
|
||||
.set_focus_pos(pos + self.freefly_vel * dt * boost);
|
||||
.set_focus_pos(pos + dir * dt * speed);
|
||||
|
||||
// Do not apply any movement to the player character
|
||||
self.inputs.move_dir = Vec2::zero();
|
||||
@ -1773,7 +1778,7 @@ impl PlayState for SessionState {
|
||||
self.scene.render(
|
||||
drawer,
|
||||
client.state(),
|
||||
client.entity(),
|
||||
viewpoint_entity,
|
||||
client.get_tick(),
|
||||
&scene_data,
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user