save spectate position

This commit is contained in:
IsseW 2022-08-12 10:52:11 +02:00
parent 14aad5fde7
commit 689376ec70
3 changed files with 80 additions and 18 deletions

View File

@ -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);
}

View File

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

View File

@ -368,6 +368,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 +509,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 +929,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 => {