Clean up client state code

Former-commit-id: 2469a49abd23038838f6176b7f5cf0b303e8bee5
This commit is contained in:
timokoesters 2019-04-20 19:54:37 +02:00
parent 794b9cafad
commit fc2e6c3624
5 changed files with 50 additions and 44 deletions

View File

@ -241,15 +241,12 @@ impl Client {
self.pending_chunks.remove(&key);
},
ServerMsg::StateAnswer(Ok(state)) => {
println!("ok state: {:?}", state);
self.client_state = state;
},
ServerMsg::StateAnswer(Err((error, state))) => {
println!("err state: {:?}", state);
self.client_state = state;
},
ServerMsg::ForceState { state } => {
println!("forced state: {:?}", state);
ServerMsg::ForceState(state) => {
self.client_state = state;
},
}

View File

@ -7,9 +7,10 @@ pub use self::server::{ServerMsg, RequestStateError};
pub use self::client::ClientMsg;
pub use self::ecs_packet::EcsPacket;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub enum ClientState {
Disconnected,
Connected,
Spectator,
Character,
}

View File

@ -15,9 +15,7 @@ pub enum RequestStateError {
#[derive(Clone, Serialize, Deserialize)]
pub enum ServerMsg {
StateAnswer(Result<ClientState, (RequestStateError, ClientState)>),
ForceState {
state: ClientState,
},
ForceState(ClientState),
InitialSync {
ecs_state: sphynx::StatePackage<EcsPacket>,
player_entity_uid: u64,

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use specs::Entity as EcsEntity;
use common::{
comp,
msg::{ServerMsg, ClientMsg, ClientState},
msg::{ServerMsg, ClientMsg, ClientState, RequestStateError},
net::PostBox,
};
use crate::Error;
@ -17,6 +17,20 @@ impl Client {
pub fn notify(&mut self, msg: ServerMsg) {
self.postbox.send_message(msg);
}
pub fn allow_state(&mut self, new_state: ClientState) {
self.client_state = new_state;
self.postbox.send_message(ServerMsg::StateAnswer(
Ok(new_state)));
}
pub fn error_state(&mut self, error: RequestStateError) {
self.postbox.send_message(ServerMsg::StateAnswer(
Err((error, self.client_state))));
}
pub fn force_state(&mut self, new_state: ClientState) {
self.client_state = new_state;
self.postbox.send_message(ServerMsg::ForceState(
new_state));
}
}
pub struct Clients {

View File

@ -250,51 +250,44 @@ impl Server {
for msg in new_msgs {
match msg {
ClientMsg::RequestState(requested_state) => match requested_state {
ClientState::Spectator => match client.client_state {
// Use ClientMsg::Connect instead
ClientState::Disconnected => {},
ClientState::Spectator => {
// Already
client.postbox.send_message(ServerMsg::StateAnswer(
Err((RequestStateError::Already, ClientState::Spectator))));
},
ClientState::Character => {
// Always allow
client.postbox.send_message(ServerMsg::StateAnswer(
Ok(ClientState::Spectator)));
},
},
// Use ClientMsg::Character instead
ClientState::Character => { unimplemented!("TODO: Check for previously used character"); },
ClientState::Disconnected => disconnect = true,
ClientState::Connected => match client.client_state {
ClientState::Disconnected => {}, // Use ClientMsg::Connect instead
ClientState::Connected => client.error_state(RequestStateError::Already),
ClientState::Spectator => client.allow_state(ClientState::Connected),
ClientState::Character => client.allow_state(ClientState::Connected),
},
ClientState::Spectator => match requested_state {
ClientState::Disconnected => {}, // Become Connected first
ClientState::Connected => client.allow_state(ClientState::Spectator),
ClientState::Spectator => client.error_state(RequestStateError::Already),
ClientState::Character => client.allow_state(ClientState::Spectator),
},
ClientState::Character => {}, // Use ClientMsg::Character instead
},
ClientMsg::Connect { player } => match client.client_state {
ClientState::Disconnected => Self::initialize_client(state, entity, client, player),
_ => {},
},
ClientMsg::Character(character) => match client.client_state {
ClientState::Spectator => Self::create_player_character(state, entity, client, character),
// Currently only possible from spectator
_ => disconnect = true,
ClientState::Disconnected => {},
ClientState::Connected | ClientState::Spectator =>
Self::create_player_character(state, entity, client, character),
ClientState::Character => client.error_state(RequestStateError::Already),
},
// Always possible
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
ClientMsg::Pong => {}
ClientMsg::Disconnect => disconnect = true,
ClientMsg::Chat(msg) => match client.client_state {
ClientState::Disconnected => {}
_ => new_chat_msgs.push((entity, msg)),
ClientState::Disconnected => {},
ClientState::Connected => new_chat_msgs.push((entity, msg)),
ClientState::Spectator => new_chat_msgs.push((entity, msg)),
ClientState::Character => new_chat_msgs.push((entity, msg)),
},
ClientMsg::PlayerAnimation(animation_history) => match client.client_state {
ClientState::Character => {
state.write_component(entity, animation_history);
}
// Only characters can send animations
ClientState::Character => state.write_component(entity, animation_history),
_ => disconnect = true,
},
ClientMsg::PlayerPhysics { pos, vel, dir } => match client.client_state {
// Only characters send their position
ClientState::Character => {
state.write_component(entity, pos);
state.write_component(entity, vel);
@ -303,6 +296,8 @@ impl Server {
_ => disconnect = true,
},
ClientMsg::TerrainChunkRequest { key } => match client.client_state {
ClientState::Disconnected => {},
ClientState::Connected => disconnect = true,
ClientState::Spectator | ClientState::Character => {
match state.terrain().get_key(key) {
Some(chunk) => {} /*client.postbox.send_message(ServerMsg::TerrainChunkUpdate {
@ -312,8 +307,11 @@ impl Server {
None => requested_chunks.push(key),
}
},
ClientState::Disconnected => {},
}
// Always possible
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
ClientMsg::Pong => {},
ClientMsg::Disconnect => disconnect = true,
}
}
} else if state.get_time() - client.last_ping > CLIENT_TIMEOUT || // Timeout
@ -327,7 +325,6 @@ impl Server {
}
if disconnect {
println!("Someone disconnected!");
disconnected_clients.push(entity);
client.postbox.send_message(ServerMsg::StateAnswer(
Err((RequestStateError::Impossible, ClientState::Disconnected))));
@ -410,8 +407,7 @@ impl Server {
}
// Tell the client his request was successful
client.notify(ServerMsg::StateAnswer(Ok(ClientState::Spectator)));
client.client_state = ClientState::Spectator;
client.allow_state(ClientState::Connected);
}
/// Sync client states with the most up to date information