mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
pack together InGame, CharacterScreen and General variant in a single enum, as requested by zesterer.
His reason to reqeust that is, that there might not be a perfect disctinction in the future. Now we need to send ServerGeneral over streams and do additional checking at various places to verify that not the wrong variant is send.
This commit is contained in:
parent
55b59fbe07
commit
2a7378b4ae
@ -25,10 +25,9 @@ use common::{
|
||||
},
|
||||
event::{EventBus, LocalEvent},
|
||||
msg::{
|
||||
validate_chat_msg, ChatMsgValidationError, ClientCharacterScreen, ClientGeneral,
|
||||
ClientInGame, ClientIngame, ClientMsg, ClientRegister, ClientType, DisconnectReason,
|
||||
InviteAnswer, Notification, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError,
|
||||
ServerCharacterScreen, ServerGeneral, ServerInGame, ServerInfo, ServerInit,
|
||||
validate_chat_msg, ChatMsgValidationError, ClientGeneral, ClientInGame, ClientMsg,
|
||||
ClientRegister, ClientType, DisconnectReason, InviteAnswer, Notification, PingMsg,
|
||||
PlayerInfo, PlayerListUpdate, RegisterError, ServerGeneral, ServerInfo, ServerInit,
|
||||
ServerRegisterAnswer, MAX_BYTES_CHAT_MSG,
|
||||
},
|
||||
outcome::Outcome,
|
||||
@ -71,7 +70,7 @@ pub enum Event {
|
||||
|
||||
pub struct Client {
|
||||
registered: bool,
|
||||
in_game: Option<ClientIngame>,
|
||||
in_game: Option<ClientInGame>,
|
||||
thread_pool: ThreadPool,
|
||||
pub server_info: ServerInfo,
|
||||
/// Just the "base" layer for LOD; currently includes colors and nothing
|
||||
@ -466,39 +465,46 @@ impl Client {
|
||||
let msg: ClientMsg = msg.into();
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
// These assertions verify that the state is correct when a message is sent!
|
||||
match &msg {
|
||||
ClientMsg::Type(_) | ClientMsg::Register(_) => assert!(
|
||||
!self.registered,
|
||||
"must not send msg when already registered"
|
||||
),
|
||||
ClientMsg::CharacterScreen(_) => {
|
||||
assert!(
|
||||
self.registered,
|
||||
"must not send character_screen msg when not registered"
|
||||
);
|
||||
assert!(
|
||||
self.in_game.is_none(),
|
||||
"must not send character_screen msg when not in character screen"
|
||||
);
|
||||
},
|
||||
ClientMsg::InGame(_) => assert!(
|
||||
self.in_game.is_some(),
|
||||
"must not send in_game msg when not in game"
|
||||
),
|
||||
ClientMsg::General(_) => assert!(
|
||||
self.registered,
|
||||
"must not send general msg when not registered"
|
||||
),
|
||||
ClientMsg::Ping(_) => (),
|
||||
}
|
||||
const C_TYPE: ClientType = ClientType::Game;
|
||||
let verified = msg.verify(C_TYPE, self.registered, self.in_game);
|
||||
assert!(
|
||||
verified,
|
||||
format!(
|
||||
"c_type: {:?}, registered: {}, in_game: {:?}, msg: {:?}",
|
||||
C_TYPE, self.registered, self.in_game, msg
|
||||
)
|
||||
);
|
||||
}
|
||||
match msg {
|
||||
ClientMsg::Type(msg) => self.register_stream.send(msg),
|
||||
ClientMsg::Register(msg) => self.register_stream.send(msg),
|
||||
ClientMsg::CharacterScreen(msg) => self.character_screen_stream.send(msg),
|
||||
ClientMsg::InGame(msg) => self.in_game_stream.send(msg),
|
||||
ClientMsg::General(msg) => self.general_stream.send(msg),
|
||||
ClientMsg::General(msg) => {
|
||||
let stream = match msg {
|
||||
ClientGeneral::RequestCharacterList
|
||||
| ClientGeneral::CreateCharacter { .. }
|
||||
| ClientGeneral::DeleteCharacter(_)
|
||||
| ClientGeneral::Character(_)
|
||||
| ClientGeneral::Spectate => &mut self.character_screen_stream,
|
||||
//Only in game
|
||||
ClientGeneral::ControllerInputs(_)
|
||||
| ClientGeneral::ControlEvent(_)
|
||||
| ClientGeneral::ControlAction(_)
|
||||
| ClientGeneral::SetViewDistance(_)
|
||||
| ClientGeneral::BreakBlock(_)
|
||||
| ClientGeneral::PlaceBlock(_, _)
|
||||
| ClientGeneral::ExitInGame
|
||||
| ClientGeneral::PlayerPhysics { .. }
|
||||
| ClientGeneral::TerrainChunkRequest { .. }
|
||||
| ClientGeneral::UnlockSkill(_)
|
||||
| ClientGeneral::RefundSkill(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_) => &mut self.in_game_stream,
|
||||
//Always possible
|
||||
ClientGeneral::ChatMsg(_)
|
||||
| ClientGeneral::Disconnect
|
||||
| ClientGeneral::Terminate => &mut self.general_stream,
|
||||
};
|
||||
stream.send(msg)
|
||||
},
|
||||
ClientMsg::Ping(msg) => self.ping_stream.send(msg),
|
||||
}
|
||||
}
|
||||
@ -518,10 +524,10 @@ impl Client {
|
||||
|
||||
/// Request a state transition to `ClientState::Character`.
|
||||
pub fn request_character(&mut self, character_id: CharacterId) {
|
||||
self.send_msg(ClientCharacterScreen::Character(character_id));
|
||||
self.send_msg(ClientGeneral::Character(character_id));
|
||||
|
||||
//Assume we are in_game unless server tells us otherwise
|
||||
self.in_game = Some(ClientIngame::Character);
|
||||
self.in_game = Some(ClientInGame::Character);
|
||||
|
||||
self.active_character_id = Some(character_id);
|
||||
}
|
||||
@ -529,19 +535,19 @@ impl Client {
|
||||
/// Load the current players character list
|
||||
pub fn load_character_list(&mut self) {
|
||||
self.character_list.loading = true;
|
||||
self.send_msg(ClientCharacterScreen::RequestCharacterList);
|
||||
self.send_msg(ClientGeneral::RequestCharacterList);
|
||||
}
|
||||
|
||||
/// New character creation
|
||||
pub fn create_character(&mut self, alias: String, tool: Option<String>, body: comp::Body) {
|
||||
self.character_list.loading = true;
|
||||
self.send_msg(ClientCharacterScreen::CreateCharacter { alias, tool, body });
|
||||
self.send_msg(ClientGeneral::CreateCharacter { alias, tool, body });
|
||||
}
|
||||
|
||||
/// Character deletion
|
||||
pub fn delete_character(&mut self, character_id: CharacterId) {
|
||||
self.character_list.loading = true;
|
||||
self.send_msg(ClientCharacterScreen::DeleteCharacter(character_id));
|
||||
self.send_msg(ClientGeneral::DeleteCharacter(character_id));
|
||||
}
|
||||
|
||||
/// Send disconnect message to the server
|
||||
@ -552,34 +558,34 @@ impl Client {
|
||||
|
||||
/// Request a state transition to `ClientState::Registered` from an ingame
|
||||
/// state.
|
||||
pub fn request_remove_character(&mut self) { self.send_msg(ClientInGame::ExitInGame); }
|
||||
pub fn request_remove_character(&mut self) { self.send_msg(ClientGeneral::ExitInGame); }
|
||||
|
||||
pub fn set_view_distance(&mut self, view_distance: u32) {
|
||||
self.view_distance = Some(view_distance.max(1).min(65));
|
||||
self.send_msg(ClientInGame::SetViewDistance(self.view_distance.unwrap()));
|
||||
self.send_msg(ClientGeneral::SetViewDistance(self.view_distance.unwrap()));
|
||||
}
|
||||
|
||||
pub fn use_slot(&mut self, slot: comp::slot::Slot) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Use(slot),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn swap_slots(&mut self, a: comp::slot::Slot, b: comp::slot::Slot) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Swap(a, b),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn drop_slot(&mut self, slot: comp::slot::Slot) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Drop(slot),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn pick_up(&mut self, entity: EcsEntity) {
|
||||
if let Some(uid) = self.state.read_component_copied(entity) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Pickup(uid),
|
||||
)));
|
||||
}
|
||||
@ -599,7 +605,7 @@ impl Client {
|
||||
|
||||
pub fn craft_recipe(&mut self, recipe: &str) -> bool {
|
||||
if self.can_craft_recipe(recipe) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::CraftRecipe(recipe.to_string()),
|
||||
)));
|
||||
true
|
||||
@ -618,11 +624,11 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn enable_lantern(&mut self) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::EnableLantern));
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::EnableLantern));
|
||||
}
|
||||
|
||||
pub fn disable_lantern(&mut self) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::DisableLantern));
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::DisableLantern));
|
||||
}
|
||||
|
||||
pub fn max_group_size(&self) -> u32 { self.max_group_size }
|
||||
@ -640,7 +646,7 @@ impl Client {
|
||||
pub fn pending_invites(&self) -> &HashSet<Uid> { &self.pending_invites }
|
||||
|
||||
pub fn send_group_invite(&mut self, invitee: Uid) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Invite(invitee),
|
||||
)))
|
||||
}
|
||||
@ -648,7 +654,7 @@ impl Client {
|
||||
pub fn accept_group_invite(&mut self) {
|
||||
// Clear invite
|
||||
self.group_invite.take();
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Accept,
|
||||
)));
|
||||
}
|
||||
@ -656,25 +662,25 @@ impl Client {
|
||||
pub fn decline_group_invite(&mut self) {
|
||||
// Clear invite
|
||||
self.group_invite.take();
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Decline,
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn leave_group(&mut self) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Leave,
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn kick_from_group(&mut self, uid: Uid) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::Kick(uid),
|
||||
)));
|
||||
}
|
||||
|
||||
pub fn assign_group_leader(&mut self, uid: Uid) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::GroupManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::GroupManip(
|
||||
GroupManip::AssignLeader(uid),
|
||||
)));
|
||||
}
|
||||
@ -697,11 +703,11 @@ impl Client {
|
||||
|
||||
pub fn mount(&mut self, entity: EcsEntity) {
|
||||
if let Some(uid) = self.state.read_component_copied(entity) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::Mount(uid)));
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Mount(uid)));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn unmount(&mut self) { self.send_msg(ClientInGame::ControlEvent(ControlEvent::Unmount)); }
|
||||
pub fn unmount(&mut self) { self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Unmount)); }
|
||||
|
||||
pub fn respawn(&mut self) {
|
||||
if self
|
||||
@ -711,7 +717,7 @@ impl Client {
|
||||
.get(self.entity)
|
||||
.map_or(false, |s| s.is_dead)
|
||||
{
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::Respawn));
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::Respawn));
|
||||
}
|
||||
}
|
||||
|
||||
@ -808,7 +814,7 @@ impl Client {
|
||||
{
|
||||
controller.actions.push(control_action);
|
||||
}
|
||||
self.send_msg(ClientInGame::ControlAction(control_action));
|
||||
self.send_msg(ClientGeneral::ControlAction(control_action));
|
||||
}
|
||||
|
||||
pub fn view_distance(&self) -> Option<u32> { self.view_distance }
|
||||
@ -852,13 +858,15 @@ impl Client {
|
||||
}
|
||||
|
||||
pub fn place_block(&mut self, pos: Vec3<i32>, block: Block) {
|
||||
self.send_msg(ClientInGame::PlaceBlock(pos, block));
|
||||
self.send_msg(ClientGeneral::PlaceBlock(pos, block));
|
||||
}
|
||||
|
||||
pub fn remove_block(&mut self, pos: Vec3<i32>) { self.send_msg(ClientInGame::BreakBlock(pos)); }
|
||||
pub fn remove_block(&mut self, pos: Vec3<i32>) {
|
||||
self.send_msg(ClientGeneral::BreakBlock(pos));
|
||||
}
|
||||
|
||||
pub fn collect_block(&mut self, pos: Vec3<i32>) {
|
||||
self.send_msg(ClientInGame::ControlEvent(ControlEvent::InventoryManip(
|
||||
self.send_msg(ClientGeneral::ControlEvent(ControlEvent::InventoryManip(
|
||||
InventoryManip::Collect(pos),
|
||||
)));
|
||||
}
|
||||
@ -915,7 +923,7 @@ impl Client {
|
||||
"Couldn't access controller component on client entity"
|
||||
);
|
||||
}
|
||||
self.send_msg_err(ClientInGame::ControllerInputs(inputs))?;
|
||||
self.send_msg_err(ClientGeneral::ControllerInputs(inputs))?;
|
||||
}
|
||||
|
||||
// 2) Build up a list of events for this frame, to be passed to the frontend.
|
||||
@ -1019,7 +1027,7 @@ impl Client {
|
||||
if self.state.terrain().get_key(*key).is_none() {
|
||||
if !skip_mode && !self.pending_chunks.contains_key(key) {
|
||||
if self.pending_chunks.len() < 4 {
|
||||
self.send_msg_err(ClientInGame::TerrainChunkRequest {
|
||||
self.send_msg_err(ClientGeneral::TerrainChunkRequest {
|
||||
key: *key,
|
||||
})?;
|
||||
self.pending_chunks.insert(*key, Instant::now());
|
||||
@ -1065,7 +1073,7 @@ impl Client {
|
||||
self.state.read_storage().get(self.entity).cloned(),
|
||||
) {
|
||||
self.in_game_stream
|
||||
.send(ClientInGame::PlayerPhysics { pos, vel, ori })?;
|
||||
.send(ClientGeneral::PlayerPhysics { pos, vel, ori })?;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1237,6 +1245,7 @@ impl Client {
|
||||
ServerGeneral::Notification(n) => {
|
||||
frontend_events.push(Event::Notification(n));
|
||||
},
|
||||
_ => unreachable!("Not a general msg"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1244,10 +1253,10 @@ impl Client {
|
||||
fn handle_server_in_game_msg(
|
||||
&mut self,
|
||||
frontend_events: &mut Vec<Event>,
|
||||
msg: ServerInGame,
|
||||
msg: ServerGeneral,
|
||||
) -> Result<(), Error> {
|
||||
match msg {
|
||||
ServerInGame::GroupUpdate(change_notification) => {
|
||||
ServerGeneral::GroupUpdate(change_notification) => {
|
||||
use comp::group::ChangeNotification::*;
|
||||
// Note: we use a hashmap since this would not work with entities outside
|
||||
// the view distance
|
||||
@ -1319,15 +1328,15 @@ impl Client {
|
||||
},
|
||||
}
|
||||
},
|
||||
ServerInGame::GroupInvite { inviter, timeout } => {
|
||||
ServerGeneral::GroupInvite { inviter, timeout } => {
|
||||
self.group_invite = Some((inviter, std::time::Instant::now(), timeout));
|
||||
},
|
||||
ServerInGame::InvitePending(uid) => {
|
||||
ServerGeneral::InvitePending(uid) => {
|
||||
if !self.pending_invites.insert(uid) {
|
||||
warn!("Received message about pending invite that was already pending");
|
||||
}
|
||||
},
|
||||
ServerInGame::InviteComplete { target, answer } => {
|
||||
ServerGeneral::InviteComplete { target, answer } => {
|
||||
if !self.pending_invites.remove(&target) {
|
||||
warn!(
|
||||
"Received completed invite message for invite that was not in the list of \
|
||||
@ -1345,11 +1354,11 @@ impl Client {
|
||||
frontend_events.push(Event::Chat(comp::ChatType::Meta.chat_msg(msg)));
|
||||
},
|
||||
// Cleanup for when the client goes back to the `in_game = None`
|
||||
ServerInGame::ExitInGameSuccess => {
|
||||
ServerGeneral::ExitInGameSuccess => {
|
||||
self.in_game = None;
|
||||
self.clean_state();
|
||||
},
|
||||
ServerInGame::InventoryUpdate(mut inventory, event) => {
|
||||
ServerGeneral::InventoryUpdate(mut inventory, event) => {
|
||||
match event {
|
||||
InventoryUpdateEvent::CollectFailed => {},
|
||||
_ => {
|
||||
@ -1363,25 +1372,25 @@ impl Client {
|
||||
|
||||
frontend_events.push(Event::InventoryUpdated(event));
|
||||
},
|
||||
ServerInGame::TerrainChunkUpdate { key, chunk } => {
|
||||
ServerGeneral::TerrainChunkUpdate { key, chunk } => {
|
||||
if let Ok(chunk) = chunk {
|
||||
self.state.insert_chunk(key, *chunk);
|
||||
}
|
||||
self.pending_chunks.remove(&key);
|
||||
},
|
||||
ServerInGame::TerrainBlockUpdates(mut blocks) => {
|
||||
ServerGeneral::TerrainBlockUpdates(mut blocks) => {
|
||||
blocks.drain().for_each(|(pos, block)| {
|
||||
self.state.set_block(pos, block);
|
||||
});
|
||||
},
|
||||
ServerInGame::SetViewDistance(vd) => {
|
||||
ServerGeneral::SetViewDistance(vd) => {
|
||||
self.view_distance = Some(vd);
|
||||
frontend_events.push(Event::SetViewDistance(vd));
|
||||
},
|
||||
ServerInGame::Outcomes(outcomes) => {
|
||||
ServerGeneral::Outcomes(outcomes) => {
|
||||
frontend_events.extend(outcomes.into_iter().map(Event::Outcome))
|
||||
},
|
||||
ServerInGame::Knockback(impulse) => {
|
||||
ServerGeneral::Knockback(impulse) => {
|
||||
self.state
|
||||
.ecs()
|
||||
.read_resource::<EventBus<LocalEvent>>()
|
||||
@ -1390,35 +1399,34 @@ impl Client {
|
||||
impulse,
|
||||
});
|
||||
},
|
||||
_ => unreachable!("Not a in_game message"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_server_character_screen_msg(
|
||||
&mut self,
|
||||
msg: ServerCharacterScreen,
|
||||
) -> Result<(), Error> {
|
||||
fn handle_server_character_screen_msg(&mut self, msg: ServerGeneral) -> Result<(), Error> {
|
||||
match msg {
|
||||
ServerCharacterScreen::CharacterListUpdate(character_list) => {
|
||||
ServerGeneral::CharacterListUpdate(character_list) => {
|
||||
self.character_list.characters = character_list;
|
||||
self.character_list.loading = false;
|
||||
},
|
||||
ServerCharacterScreen::CharacterActionError(error) => {
|
||||
ServerGeneral::CharacterActionError(error) => {
|
||||
warn!("CharacterActionError: {:?}.", error);
|
||||
self.character_list.error = Some(error);
|
||||
},
|
||||
ServerCharacterScreen::CharacterDataLoadError(error) => {
|
||||
ServerGeneral::CharacterDataLoadError(error) => {
|
||||
trace!("Handling join error by server");
|
||||
self.in_game = None;
|
||||
self.clean_state();
|
||||
self.character_list.error = Some(error);
|
||||
},
|
||||
ServerCharacterScreen::CharacterSuccess => {
|
||||
ServerGeneral::CharacterSuccess => {
|
||||
debug!("client is now in ingame state on server");
|
||||
if let Some(vd) = self.view_distance {
|
||||
self.set_view_distance(vd);
|
||||
}
|
||||
},
|
||||
_ => unreachable!("Not a character_screen msg"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -1518,7 +1526,7 @@ impl Client {
|
||||
|
||||
pub fn uid(&self) -> Option<Uid> { self.state.read_component_copied(self.entity) }
|
||||
|
||||
pub fn in_game(&self) -> Option<ClientIngame> { self.in_game }
|
||||
pub fn in_game(&self) -> Option<ClientInGame> { self.in_game }
|
||||
|
||||
pub fn registered(&self) -> bool { self.registered }
|
||||
|
||||
|
@ -12,16 +12,13 @@ use vek::*;
|
||||
/// streams though). It's used to verify the correctness of the state in
|
||||
/// debug_assertions
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::clippy::large_enum_variant)]
|
||||
pub enum ClientMsg {
|
||||
///Send on the first connection ONCE to identify client intention for
|
||||
/// server
|
||||
Type(ClientType),
|
||||
///Send ONCE to register/auth to the server
|
||||
Register(ClientRegister),
|
||||
///Msg only to send while in character screen, e.g. `CreateCharacter`
|
||||
CharacterScreen(ClientCharacterScreen),
|
||||
///Msg only to send while playing in game, e.g. `PlayerPositionUpdates`
|
||||
InGame(ClientInGame),
|
||||
///Msg that can be send ALWAYS as soon as we are registered, e.g. `Chat`
|
||||
General(ClientGeneral),
|
||||
Ping(PingMsg),
|
||||
@ -47,9 +44,10 @@ pub struct ClientRegister {
|
||||
pub token_or_username: String,
|
||||
}
|
||||
|
||||
//messages send by clients only valid when in character screen
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClientCharacterScreen {
|
||||
/// Messages sent from the client to the server
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ClientGeneral {
|
||||
//Only in Character Screen
|
||||
RequestCharacterList,
|
||||
CreateCharacter {
|
||||
alias: String,
|
||||
@ -59,11 +57,7 @@ pub enum ClientCharacterScreen {
|
||||
DeleteCharacter(CharacterId),
|
||||
Character(CharacterId),
|
||||
Spectate,
|
||||
}
|
||||
|
||||
//messages send by clients only valid when in game (with a character)
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClientInGame {
|
||||
//Only in game
|
||||
ControllerInputs(comp::ControllerInputs),
|
||||
ControlEvent(comp::ControlEvent),
|
||||
ControlAction(comp::ControlAction),
|
||||
@ -82,16 +76,59 @@ pub enum ClientInGame {
|
||||
UnlockSkill(Skill),
|
||||
RefundSkill(Skill),
|
||||
UnlockSkillGroup(SkillGroupType),
|
||||
}
|
||||
|
||||
/// Messages sent from the client to the server
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ClientGeneral {
|
||||
//Always possible
|
||||
ChatMsg(String),
|
||||
Disconnect,
|
||||
Terminate,
|
||||
}
|
||||
|
||||
impl ClientMsg {
|
||||
pub fn verify(
|
||||
&self,
|
||||
c_type: ClientType,
|
||||
registered: bool,
|
||||
in_game: Option<super::ClientInGame>,
|
||||
) -> bool {
|
||||
match self {
|
||||
ClientMsg::Type(t) => c_type == *t,
|
||||
ClientMsg::Register(_) => !registered && in_game.is_none(),
|
||||
ClientMsg::General(g) => {
|
||||
registered
|
||||
&& match g {
|
||||
ClientGeneral::RequestCharacterList
|
||||
| ClientGeneral::CreateCharacter { .. }
|
||||
| ClientGeneral::DeleteCharacter(_) => {
|
||||
c_type != ClientType::ChatOnly && in_game.is_none()
|
||||
},
|
||||
ClientGeneral::Character(_) | ClientGeneral::Spectate => {
|
||||
c_type == ClientType::Game && in_game.is_none()
|
||||
},
|
||||
//Only in game
|
||||
ClientGeneral::ControllerInputs(_)
|
||||
| ClientGeneral::ControlEvent(_)
|
||||
| ClientGeneral::ControlAction(_)
|
||||
| ClientGeneral::SetViewDistance(_)
|
||||
| ClientGeneral::BreakBlock(_)
|
||||
| ClientGeneral::PlaceBlock(_, _)
|
||||
| ClientGeneral::ExitInGame
|
||||
| ClientGeneral::PlayerPhysics { .. }
|
||||
| ClientGeneral::TerrainChunkRequest { .. }
|
||||
| ClientGeneral::UnlockSkill(_)
|
||||
| ClientGeneral::RefundSkill(_)
|
||||
| ClientGeneral::UnlockSkillGroup(_) => {
|
||||
c_type == ClientType::Game && in_game.is_some()
|
||||
},
|
||||
//Always possible
|
||||
ClientGeneral::ChatMsg(_)
|
||||
| ClientGeneral::Disconnect
|
||||
| ClientGeneral::Terminate => true,
|
||||
}
|
||||
},
|
||||
ClientMsg::Ping(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
end of 2nd level Enums
|
||||
*/
|
||||
@ -104,14 +141,6 @@ impl Into<ClientMsg> for ClientRegister {
|
||||
fn into(self) -> ClientMsg { ClientMsg::Register(self) }
|
||||
}
|
||||
|
||||
impl Into<ClientMsg> for ClientCharacterScreen {
|
||||
fn into(self) -> ClientMsg { ClientMsg::CharacterScreen(self) }
|
||||
}
|
||||
|
||||
impl Into<ClientMsg> for ClientInGame {
|
||||
fn into(self) -> ClientMsg { ClientMsg::InGame(self) }
|
||||
}
|
||||
|
||||
impl Into<ClientMsg> for ClientGeneral {
|
||||
fn into(self) -> ClientMsg { ClientMsg::General(self) }
|
||||
}
|
||||
|
@ -5,21 +5,18 @@ pub mod world_packet;
|
||||
|
||||
// Reexports
|
||||
pub use self::{
|
||||
client::{
|
||||
ClientCharacterScreen, ClientGeneral, ClientInGame, ClientMsg, ClientRegister, ClientType,
|
||||
},
|
||||
client::{ClientGeneral, ClientMsg, ClientRegister, ClientType},
|
||||
ecs_packet::EcsCompPacket,
|
||||
server::{
|
||||
CharacterInfo, DisconnectReason, InviteAnswer, Notification, PlayerInfo, PlayerListUpdate,
|
||||
RegisterError, ServerCharacterScreen, ServerGeneral, ServerInGame, ServerInfo, ServerInit,
|
||||
ServerMsg, ServerRegisterAnswer,
|
||||
RegisterError, ServerGeneral, ServerInfo, ServerInit, ServerMsg, ServerRegisterAnswer,
|
||||
},
|
||||
world_packet::WorldMapMsg,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
|
||||
pub enum ClientIngame {
|
||||
pub enum ClientInGame {
|
||||
Spectator,
|
||||
Character,
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use super::{EcsCompPacket, PingMsg};
|
||||
use super::{ClientType, EcsCompPacket, PingMsg};
|
||||
use crate::{
|
||||
character::CharacterItem,
|
||||
comp,
|
||||
@ -24,12 +24,6 @@ pub enum ServerMsg {
|
||||
Init(ServerInit),
|
||||
/// Result to `ClientMsg::Register`. send ONCE
|
||||
RegisterAnswer(ServerRegisterAnswer),
|
||||
/// Msg only to send when client is on the character screen, e.g.
|
||||
/// `CharacterListUpdate`
|
||||
CharacterScreen(ServerCharacterScreen),
|
||||
/// Msg only to send when client is playing in game, e.g.
|
||||
/// `TerrainChunkUpdate`
|
||||
InGame(ServerInGame),
|
||||
///Msg that can be send ALWAYS as soon as client is registered, e.g. `Chat`
|
||||
General(ServerGeneral),
|
||||
Ping(PingMsg),
|
||||
@ -65,9 +59,10 @@ pub enum ServerInit {
|
||||
|
||||
pub type ServerRegisterAnswer = Result<(), RegisterError>;
|
||||
|
||||
//Messages only allowed while client in character screen
|
||||
/// Messages sent from the server to the client
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ServerCharacterScreen {
|
||||
pub enum ServerGeneral {
|
||||
//Character Screen related
|
||||
/// An error occurred while loading character data
|
||||
CharacterDataLoadError(String),
|
||||
/// A list of characters belonging to the a authenticated player was sent
|
||||
@ -75,23 +70,21 @@ pub enum ServerCharacterScreen {
|
||||
/// An error occurred while creating or deleting a character
|
||||
CharacterActionError(String),
|
||||
CharacterSuccess,
|
||||
}
|
||||
|
||||
//Messages only allowed while client is in game (with a character)
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ServerInGame {
|
||||
//Ingame related
|
||||
GroupUpdate(comp::group::ChangeNotification<sync::Uid>),
|
||||
// Indicate to the client that they are invited to join a group
|
||||
/// Indicate to the client that they are invited to join a group
|
||||
GroupInvite {
|
||||
inviter: sync::Uid,
|
||||
timeout: std::time::Duration,
|
||||
},
|
||||
// Indicate to the client that their sent invite was not invalid and is currently pending
|
||||
/// Indicate to the client that their sent invite was not invalid and is
|
||||
/// currently pending
|
||||
InvitePending(sync::Uid),
|
||||
// Note: this could potentially include all the failure cases such as inviting yourself in
|
||||
// which case the `InvitePending` message could be removed and the client could consider their
|
||||
// invite pending until they receive this message
|
||||
// Indicate to the client the result of their invite
|
||||
/// Note: this could potentially include all the failure cases such as
|
||||
/// inviting yourself in which case the `InvitePending` message could be
|
||||
/// removed and the client could consider their invite pending until
|
||||
/// they receive this message Indicate to the client the result of their
|
||||
/// invite
|
||||
InviteComplete {
|
||||
target: sync::Uid,
|
||||
answer: InviteAnswer,
|
||||
@ -108,11 +101,7 @@ pub enum ServerInGame {
|
||||
SetViewDistance(u32),
|
||||
Outcomes(Vec<Outcome>),
|
||||
Knockback(Vec3<f32>),
|
||||
}
|
||||
|
||||
/// Messages sent from the server to the client
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub enum ServerGeneral {
|
||||
// Always possible
|
||||
PlayerListUpdate(PlayerListUpdate),
|
||||
/// A message to go into the client chat box. The client is responsible for
|
||||
/// formatting the message and turning it into a speech bubble.
|
||||
@ -190,6 +179,61 @@ pub enum RegisterError {
|
||||
//TODO: InvalidAlias,
|
||||
}
|
||||
|
||||
impl ServerMsg {
|
||||
pub fn verify(
|
||||
&self,
|
||||
c_type: ClientType,
|
||||
registered: bool,
|
||||
in_game: Option<super::ClientInGame>,
|
||||
) -> bool {
|
||||
match self {
|
||||
ServerMsg::Info(_) | ServerMsg::Init(_) | ServerMsg::RegisterAnswer(_) => {
|
||||
!registered && in_game.is_none()
|
||||
},
|
||||
ServerMsg::General(g) => {
|
||||
registered
|
||||
&& match g {
|
||||
//Character Screen related
|
||||
ServerGeneral::CharacterDataLoadError(_)
|
||||
| ServerGeneral::CharacterListUpdate(_)
|
||||
| ServerGeneral::CharacterActionError(_) => {
|
||||
c_type != ClientType::ChatOnly && in_game.is_none()
|
||||
},
|
||||
ServerGeneral::CharacterSuccess => {
|
||||
c_type == ClientType::Game && in_game.is_none()
|
||||
},
|
||||
//Ingame related
|
||||
ServerGeneral::GroupUpdate(_)
|
||||
| ServerGeneral::GroupInvite { .. }
|
||||
| ServerGeneral::InvitePending(_)
|
||||
| ServerGeneral::InviteComplete { .. }
|
||||
| ServerGeneral::ExitInGameSuccess
|
||||
| ServerGeneral::InventoryUpdate(_, _)
|
||||
| ServerGeneral::TerrainChunkUpdate { .. }
|
||||
| ServerGeneral::TerrainBlockUpdates(_)
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
| ServerGeneral::Knockback(_) => {
|
||||
c_type == ClientType::Game && in_game.is_some()
|
||||
},
|
||||
// Always possible
|
||||
ServerGeneral::PlayerListUpdate(_)
|
||||
| ServerGeneral::ChatMsg(_)
|
||||
| ServerGeneral::SetPlayerEntity(_)
|
||||
| ServerGeneral::TimeOfDay(_)
|
||||
| ServerGeneral::EntitySync(_)
|
||||
| ServerGeneral::CompSync(_)
|
||||
| ServerGeneral::CreateEntity(_)
|
||||
| ServerGeneral::DeleteEntity(_)
|
||||
| ServerGeneral::Disconnect(_)
|
||||
| ServerGeneral::Notification(_) => true,
|
||||
}
|
||||
},
|
||||
ServerMsg::Ping(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuthClientError> for RegisterError {
|
||||
fn from(err: AuthClientError) -> Self { Self::AuthError(err.to_string()) }
|
||||
}
|
||||
@ -210,14 +254,6 @@ impl Into<ServerMsg> for ServerRegisterAnswer {
|
||||
fn into(self) -> ServerMsg { ServerMsg::RegisterAnswer(self) }
|
||||
}
|
||||
|
||||
impl Into<ServerMsg> for ServerCharacterScreen {
|
||||
fn into(self) -> ServerMsg { ServerMsg::CharacterScreen(self) }
|
||||
}
|
||||
|
||||
impl Into<ServerMsg> for ServerInGame {
|
||||
fn into(self) -> ServerMsg { ServerMsg::InGame(self) }
|
||||
}
|
||||
|
||||
impl Into<ServerMsg> for ServerGeneral {
|
||||
fn into(self) -> ServerMsg { ServerMsg::General(self) }
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::error::Error;
|
||||
use common::msg::{ClientIngame, ClientType, ServerMsg};
|
||||
use common::msg::{ClientInGame, ClientType, ServerGeneral, ServerMsg};
|
||||
use hashbrown::HashSet;
|
||||
use network::{Participant, Stream};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
@ -11,7 +11,7 @@ use vek::*;
|
||||
pub struct Client {
|
||||
pub registered: bool,
|
||||
pub client_type: ClientType,
|
||||
pub in_game: Option<ClientIngame>,
|
||||
pub in_game: Option<ClientInGame>,
|
||||
pub participant: Option<Participant>,
|
||||
pub general_stream: Stream,
|
||||
pub ping_stream: Stream,
|
||||
@ -59,16 +59,38 @@ impl Client {
|
||||
ServerMsg::RegisterAnswer(msg) => {
|
||||
Self::internal_send(&mut self.network_error, &mut self.register_stream, &msg)
|
||||
},
|
||||
ServerMsg::CharacterScreen(msg) => Self::internal_send(
|
||||
&mut self.network_error,
|
||||
&mut self.character_screen_stream,
|
||||
&msg,
|
||||
),
|
||||
ServerMsg::InGame(msg) => {
|
||||
Self::internal_send(&mut self.network_error, &mut self.in_game_stream, &msg)
|
||||
},
|
||||
ServerMsg::General(msg) => {
|
||||
Self::internal_send(&mut self.network_error, &mut self.general_stream, &msg)
|
||||
let stream = match &msg {
|
||||
//Character Screen related
|
||||
ServerGeneral::CharacterDataLoadError(_)
|
||||
| ServerGeneral::CharacterListUpdate(_)
|
||||
| ServerGeneral::CharacterActionError(_)
|
||||
| ServerGeneral::CharacterSuccess => &mut self.character_screen_stream,
|
||||
//Ingame related
|
||||
ServerGeneral::GroupUpdate(_)
|
||||
| ServerGeneral::GroupInvite { .. }
|
||||
| ServerGeneral::InvitePending(_)
|
||||
| ServerGeneral::InviteComplete { .. }
|
||||
| ServerGeneral::ExitInGameSuccess
|
||||
| ServerGeneral::InventoryUpdate(_, _)
|
||||
| ServerGeneral::TerrainChunkUpdate { .. }
|
||||
| ServerGeneral::TerrainBlockUpdates(_)
|
||||
| ServerGeneral::SetViewDistance(_)
|
||||
| ServerGeneral::Outcomes(_)
|
||||
| ServerGeneral::Knockback(_) => &mut self.in_game_stream,
|
||||
// Always possible
|
||||
ServerGeneral::PlayerListUpdate(_)
|
||||
| ServerGeneral::ChatMsg(_)
|
||||
| ServerGeneral::SetPlayerEntity(_)
|
||||
| ServerGeneral::TimeOfDay(_)
|
||||
| ServerGeneral::EntitySync(_)
|
||||
| ServerGeneral::CompSync(_)
|
||||
| ServerGeneral::CreateEntity(_)
|
||||
| ServerGeneral::DeleteEntity(_)
|
||||
| ServerGeneral::Disconnect(_)
|
||||
| ServerGeneral::Notification(_) => &mut self.general_stream,
|
||||
};
|
||||
Self::internal_send(&mut self.network_error, stream, &msg)
|
||||
},
|
||||
ServerMsg::Ping(msg) => {
|
||||
Self::internal_send(&mut self.network_error, &mut self.ping_stream, &msg)
|
||||
|
@ -12,7 +12,7 @@ use common::{
|
||||
cmd::{ChatCommand, CHAT_COMMANDS, CHAT_SHORTCUTS},
|
||||
comp::{self, ChatType, Item, LightEmitter, WaypointArea},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral, ServerInGame},
|
||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
||||
npc::{self, get_npc_name},
|
||||
state::TimeOfDay,
|
||||
sync::{Uid, WorldSyncExt},
|
||||
@ -669,7 +669,9 @@ fn handle_spawn(
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| {
|
||||
c.send_msg(ServerGeneral::GroupUpdate(g))
|
||||
});
|
||||
},
|
||||
);
|
||||
} else if let Some(group) = match alignment {
|
||||
|
@ -12,7 +12,7 @@ use common::{
|
||||
Player, Pos, Stats,
|
||||
},
|
||||
lottery::Lottery,
|
||||
msg::{PlayerListUpdate, ServerGeneral, ServerInGame},
|
||||
msg::{PlayerListUpdate, ServerGeneral},
|
||||
outcome::Outcome,
|
||||
state::BlockChange,
|
||||
sync::{Uid, UidAllocator, WorldSyncExt},
|
||||
@ -44,7 +44,7 @@ pub fn handle_knockback(server: &Server, entity: EcsEntity, impulse: Vec3<f32>)
|
||||
}
|
||||
let mut clients = state.ecs().write_storage::<Client>();
|
||||
if let Some(client) = clients.get_mut(entity) {
|
||||
client.send_msg(ServerInGame::Knockback(impulse));
|
||||
client.send_msg(ServerGeneral::Knockback(impulse));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use common::{
|
||||
group::{self, Group, GroupManager, Invite, PendingInvites},
|
||||
ChatType, GroupManip,
|
||||
},
|
||||
msg::{InviteAnswer, ServerInGame},
|
||||
msg::{InviteAnswer, ServerGeneral},
|
||||
sync,
|
||||
sync::WorldSyncExt,
|
||||
};
|
||||
@ -155,7 +155,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
(clients.get_mut(invitee), uids.get(entity).copied())
|
||||
{
|
||||
if send_invite() {
|
||||
client.send_msg(ServerInGame::GroupInvite {
|
||||
client.send_msg(ServerGeneral::GroupInvite {
|
||||
inviter,
|
||||
timeout: PRESENTED_INVITE_TIMEOUT_DUR,
|
||||
});
|
||||
@ -171,7 +171,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
// Notify inviter that the invite is pending
|
||||
if invite_sent {
|
||||
if let Some(client) = clients.get_mut(entity) {
|
||||
client.send_msg(ServerInGame::InvitePending(uid));
|
||||
client.send_msg(ServerGeneral::InvitePending(uid));
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -196,7 +196,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
if let (Some(client), Some(target)) =
|
||||
(clients.get_mut(inviter), uids.get(entity).copied())
|
||||
{
|
||||
client.send_msg(ServerInGame::InviteComplete {
|
||||
client.send_msg(ServerGeneral::InviteComplete {
|
||||
target,
|
||||
answer: InviteAnswer::Accepted,
|
||||
})
|
||||
@ -217,7 +217,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g)));
|
||||
},
|
||||
);
|
||||
}
|
||||
@ -244,7 +244,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
if let (Some(client), Some(target)) =
|
||||
(clients.get_mut(inviter), uids.get(entity).copied())
|
||||
{
|
||||
client.send_msg(ServerInGame::InviteComplete {
|
||||
client.send_msg(ServerGeneral::InviteComplete {
|
||||
target,
|
||||
answer: InviteAnswer::Declined,
|
||||
})
|
||||
@ -269,7 +269,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g)));
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -336,7 +336,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g)));
|
||||
},
|
||||
);
|
||||
|
||||
@ -410,7 +410,7 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g)));
|
||||
},
|
||||
);
|
||||
// Tell them they are the leader
|
||||
|
@ -5,7 +5,7 @@ use common::{
|
||||
slot::{self, Slot},
|
||||
Pos, MAX_PICKUP_RANGE_SQR,
|
||||
},
|
||||
msg::ServerInGame,
|
||||
msg::ServerGeneral,
|
||||
recipe::default_recipe_book,
|
||||
sync::{Uid, WorldSyncExt},
|
||||
vol::ReadVol,
|
||||
@ -281,7 +281,7 @@ pub fn handle_inventory(server: &mut Server, entity: EcsEntity, manip: comp::Inv
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| {
|
||||
c.send_msg(ServerInGame::GroupUpdate(g))
|
||||
c.send_msg(ServerGeneral::GroupUpdate(g))
|
||||
});
|
||||
},
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
use common::{
|
||||
comp,
|
||||
comp::{group, Player},
|
||||
msg::{PlayerListUpdate, ServerGeneral, ServerInGame},
|
||||
msg::{PlayerListUpdate, ServerGeneral},
|
||||
span,
|
||||
sync::{Uid, UidAllocator},
|
||||
};
|
||||
@ -34,7 +34,7 @@ pub fn handle_exit_ingame(server: &mut Server, entity: EcsEntity) {
|
||||
if let (Some(mut client), Some(uid), Some(player)) = (maybe_client, maybe_uid, maybe_player) {
|
||||
// Tell client its request was successful
|
||||
client.in_game = None;
|
||||
client.send_msg(ServerInGame::ExitInGameSuccess);
|
||||
client.send_msg(ServerGeneral::ExitInGameSuccess);
|
||||
|
||||
let entity_builder = state.ecs_mut().create_entity().with(client).with(player);
|
||||
|
||||
|
@ -47,8 +47,7 @@ use common::{
|
||||
comp::{self, ChatType},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{
|
||||
ClientType, DisconnectReason, ServerCharacterScreen, ServerGeneral, ServerInfo, ServerInit,
|
||||
ServerMsg, WorldMapMsg,
|
||||
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
|
||||
},
|
||||
outcome::Outcome,
|
||||
recipe::default_recipe_book,
|
||||
@ -527,11 +526,11 @@ impl Server {
|
||||
CharacterLoaderResponseType::CharacterList(result) => match result {
|
||||
Ok(character_list_data) => self.notify_client(
|
||||
query_result.entity,
|
||||
ServerCharacterScreen::CharacterListUpdate(character_list_data),
|
||||
ServerGeneral::CharacterListUpdate(character_list_data),
|
||||
),
|
||||
Err(error) => self.notify_client(
|
||||
query_result.entity,
|
||||
ServerCharacterScreen::CharacterActionError(error.to_string()),
|
||||
ServerGeneral::CharacterActionError(error.to_string()),
|
||||
),
|
||||
},
|
||||
CharacterLoaderResponseType::CharacterData(result) => {
|
||||
@ -546,7 +545,7 @@ impl Server {
|
||||
// to display
|
||||
self.notify_client(
|
||||
query_result.entity,
|
||||
ServerCharacterScreen::CharacterDataLoadError(error.to_string()),
|
||||
ServerGeneral::CharacterDataLoadError(error.to_string()),
|
||||
);
|
||||
|
||||
// Clean up the entity data on the server
|
||||
|
@ -5,10 +5,7 @@ use common::{
|
||||
character::CharacterId,
|
||||
comp,
|
||||
effect::Effect,
|
||||
msg::{
|
||||
CharacterInfo, ClientIngame, PlayerListUpdate, ServerCharacterScreen, ServerGeneral,
|
||||
ServerInGame, ServerMsg,
|
||||
},
|
||||
msg::{CharacterInfo, ClientInGame, PlayerListUpdate, ServerGeneral, ServerMsg},
|
||||
state::State,
|
||||
sync::{Uid, UidAllocator, WorldSyncExt},
|
||||
util::Dir,
|
||||
@ -63,7 +60,7 @@ pub trait StateExt {
|
||||
/// Iterates over registered clients and send each `ServerMsg`
|
||||
fn send_chat(&self, msg: comp::UnresolvedChatMsg);
|
||||
fn notify_registered_clients(&self, msg: ServerGeneral);
|
||||
fn notify_in_game_clients(&self, msg: ServerInGame);
|
||||
fn notify_in_game_clients(&self, msg: ServerGeneral);
|
||||
/// Delete an entity, recording the deletion in [`DeletedEntities`]
|
||||
fn delete_entity_recorded(
|
||||
&mut self,
|
||||
@ -220,8 +217,8 @@ impl StateExt for State {
|
||||
|
||||
// Tell the client its request was successful.
|
||||
if let Some(client) = self.ecs().write_storage::<Client>().get_mut(entity) {
|
||||
client.in_game = Some(ClientIngame::Character);
|
||||
client.send_msg(ServerCharacterScreen::CharacterSuccess)
|
||||
client.in_game = Some(ClientInGame::Character);
|
||||
client.send_msg(ServerGeneral::CharacterSuccess)
|
||||
}
|
||||
}
|
||||
|
||||
@ -368,7 +365,7 @@ impl StateExt for State {
|
||||
}
|
||||
|
||||
/// Sends the message to all clients playing in game
|
||||
fn notify_in_game_clients(&self, msg: ServerInGame) {
|
||||
fn notify_in_game_clients(&self, msg: ServerGeneral) {
|
||||
let msg: ServerMsg = msg.into();
|
||||
for client in (&mut self.ecs().write_storage::<Client>())
|
||||
.join()
|
||||
@ -401,7 +398,7 @@ impl StateExt for State {
|
||||
.try_map(|e| uids.get(e).copied())
|
||||
.map(|g| (g, c))
|
||||
})
|
||||
.map(|(g, c)| c.send_msg(ServerInGame::GroupUpdate(g)));
|
||||
.map(|(g, c)| c.send_msg(ServerGeneral::GroupUpdate(g)));
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
use common::{
|
||||
comp::{ForceUpdate, Inventory, InventoryUpdate, Last, Ori, Player, Pos, Vel},
|
||||
msg::{ServerGeneral, ServerInGame},
|
||||
msg::ServerGeneral,
|
||||
outcome::Outcome,
|
||||
region::{Event as RegionEvent, RegionMap},
|
||||
span,
|
||||
@ -320,7 +320,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// Sync inventories
|
||||
for (client, inventory, update) in (&mut clients, &inventories, &inventory_updates).join() {
|
||||
client.send_msg(ServerInGame::InventoryUpdate(
|
||||
client.send_msg(ServerGeneral::InventoryUpdate(
|
||||
inventory.clone(),
|
||||
update.event(),
|
||||
));
|
||||
@ -341,7 +341,7 @@ impl<'a> System<'a> for Sys {
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
if !outcomes.is_empty() {
|
||||
client.send_msg(ServerInGame::Outcomes(outcomes));
|
||||
client.send_msg(ServerGeneral::Outcomes(outcomes));
|
||||
}
|
||||
}
|
||||
outcomes.clear();
|
||||
|
@ -2,7 +2,7 @@ use super::SysTimer;
|
||||
use crate::client::Client;
|
||||
use common::{
|
||||
comp::group::{Invite, PendingInvites},
|
||||
msg::{InviteAnswer, ServerInGame},
|
||||
msg::{InviteAnswer, ServerGeneral},
|
||||
span,
|
||||
sync::Uid,
|
||||
};
|
||||
@ -54,7 +54,7 @@ impl<'a> System<'a> for Sys {
|
||||
if let (Some(client), Some(target)) =
|
||||
(clients.get_mut(*inviter), uids.get(invitee).copied())
|
||||
{
|
||||
client.send_msg(ServerInGame::InviteComplete {
|
||||
client.send_msg(ServerGeneral::InviteComplete {
|
||||
target,
|
||||
answer: InviteAnswer::TimedOut,
|
||||
})
|
||||
|
@ -15,10 +15,9 @@ use common::{
|
||||
},
|
||||
event::{EventBus, ServerEvent},
|
||||
msg::{
|
||||
validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientCharacterScreen,
|
||||
ClientGeneral, ClientInGame, ClientIngame, ClientRegister, DisconnectReason, PingMsg,
|
||||
PlayerInfo, PlayerListUpdate, RegisterError, ServerCharacterScreen, ServerGeneral,
|
||||
ServerInGame, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG,
|
||||
validate_chat_msg, CharacterInfo, ChatMsgValidationError, ClientGeneral, ClientInGame,
|
||||
ClientRegister, DisconnectReason, PingMsg, PlayerInfo, PlayerListUpdate, RegisterError,
|
||||
ServerGeneral, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG,
|
||||
},
|
||||
span,
|
||||
state::{BlockChange, Time},
|
||||
@ -79,6 +78,7 @@ impl Sys {
|
||||
.inc();
|
||||
server_emitter.emit(ServerEvent::ClientDisconnect(entity));
|
||||
},
|
||||
_ => unreachable!("not a client_general msg"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -100,24 +100,24 @@ impl Sys {
|
||||
players: &mut WriteStorage<'_, Player>,
|
||||
controllers: &mut WriteStorage<'_, Controller>,
|
||||
settings: &Read<'_, Settings>,
|
||||
msg: ClientInGame,
|
||||
msg: ClientGeneral,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
if client.in_game.is_none() {
|
||||
debug!(?entity, "client is not in_game, ignoring msg");
|
||||
trace!(?msg, "ignored msg content");
|
||||
if matches!(msg, ClientInGame::TerrainChunkRequest{ .. }) {
|
||||
if matches!(msg, ClientGeneral::TerrainChunkRequest{ .. }) {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
match msg {
|
||||
// Go back to registered state (char selection screen)
|
||||
ClientInGame::ExitInGame => {
|
||||
ClientGeneral::ExitInGame => {
|
||||
client.in_game = None;
|
||||
server_emitter.emit(ServerEvent::ExitIngame { entity });
|
||||
client.send_msg(ServerInGame::ExitInGameSuccess);
|
||||
client.send_msg(ServerGeneral::ExitInGameSuccess);
|
||||
},
|
||||
ClientInGame::SetViewDistance(view_distance) => {
|
||||
ClientGeneral::SetViewDistance(view_distance) => {
|
||||
players.get_mut(entity).map(|player| {
|
||||
player.view_distance = Some(
|
||||
settings
|
||||
@ -133,20 +133,20 @@ impl Sys {
|
||||
.map(|max| view_distance > max)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
client.send_msg(ServerInGame::SetViewDistance(
|
||||
client.send_msg(ServerGeneral::SetViewDistance(
|
||||
settings.max_view_distance.unwrap_or(0),
|
||||
));
|
||||
}
|
||||
},
|
||||
ClientInGame::ControllerInputs(inputs) => {
|
||||
if let Some(ClientIngame::Character) = client.in_game {
|
||||
ClientGeneral::ControllerInputs(inputs) => {
|
||||
if let Some(ClientInGame::Character) = client.in_game {
|
||||
if let Some(controller) = controllers.get_mut(entity) {
|
||||
controller.inputs.update_with_new(inputs);
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientInGame::ControlEvent(event) => {
|
||||
if let Some(ClientIngame::Character) = client.in_game {
|
||||
ClientGeneral::ControlEvent(event) => {
|
||||
if let Some(ClientInGame::Character) = client.in_game {
|
||||
// Skip respawn if client entity is alive
|
||||
if let ControlEvent::Respawn = event {
|
||||
if stats.get(entity).map_or(true, |s| !s.is_dead) {
|
||||
@ -159,15 +159,15 @@ impl Sys {
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientInGame::ControlAction(event) => {
|
||||
if let Some(ClientIngame::Character) = client.in_game {
|
||||
ClientGeneral::ControlAction(event) => {
|
||||
if let Some(ClientInGame::Character) = client.in_game {
|
||||
if let Some(controller) = controllers.get_mut(entity) {
|
||||
controller.actions.push(event);
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientInGame::PlayerPhysics { pos, vel, ori } => {
|
||||
if let Some(ClientIngame::Character) = client.in_game {
|
||||
ClientGeneral::PlayerPhysics { pos, vel, ori } => {
|
||||
if let Some(ClientInGame::Character) = client.in_game {
|
||||
if force_updates.get(entity).is_none()
|
||||
&& stats.get(entity).map_or(true, |s| !s.is_dead)
|
||||
{
|
||||
@ -177,17 +177,17 @@ impl Sys {
|
||||
}
|
||||
}
|
||||
},
|
||||
ClientInGame::BreakBlock(pos) => {
|
||||
ClientGeneral::BreakBlock(pos) => {
|
||||
if let Some(block) = can_build.get(entity).and_then(|_| terrain.get(pos).ok()) {
|
||||
block_changes.set(pos, block.into_vacant());
|
||||
}
|
||||
},
|
||||
ClientInGame::PlaceBlock(pos, block) => {
|
||||
ClientGeneral::PlaceBlock(pos, block) => {
|
||||
if can_build.get(entity).is_some() {
|
||||
block_changes.try_set(pos, block);
|
||||
}
|
||||
},
|
||||
ClientInGame::TerrainChunkRequest { key } => {
|
||||
ClientGeneral::TerrainChunkRequest { key } => {
|
||||
let in_vd = if let (Some(view_distance), Some(pos)) = (
|
||||
players.get(entity).and_then(|p| p.view_distance),
|
||||
positions.get(entity),
|
||||
@ -203,7 +203,7 @@ impl Sys {
|
||||
match terrain.get_key(key) {
|
||||
Some(chunk) => {
|
||||
network_metrics.chunks_served_from_memory.inc();
|
||||
client.send_msg(ServerInGame::TerrainChunkUpdate {
|
||||
client.send_msg(ServerGeneral::TerrainChunkUpdate {
|
||||
key,
|
||||
chunk: Ok(Box::new(chunk.clone())),
|
||||
})
|
||||
@ -217,21 +217,22 @@ impl Sys {
|
||||
network_metrics.chunks_request_dropped.inc();
|
||||
}
|
||||
},
|
||||
ClientInGame::UnlockSkill(skill) => {
|
||||
ClientGeneral::UnlockSkill(skill) => {
|
||||
stats
|
||||
.get_mut(entity)
|
||||
.map(|s| s.skill_set.unlock_skill(skill));
|
||||
},
|
||||
ClientInGame::RefundSkill(skill) => {
|
||||
ClientGeneral::RefundSkill(skill) => {
|
||||
stats
|
||||
.get_mut(entity)
|
||||
.map(|s| s.skill_set.refund_skill(skill));
|
||||
},
|
||||
ClientInGame::UnlockSkillGroup(skill_group_type) => {
|
||||
ClientGeneral::UnlockSkillGroup(skill_group_type) => {
|
||||
stats
|
||||
.get_mut(entity)
|
||||
.map(|s| s.skill_set.unlock_skill_group(skill_group_type));
|
||||
},
|
||||
_ => unreachable!("not a client_in_game msg"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -247,17 +248,15 @@ impl Sys {
|
||||
players: &mut WriteStorage<'_, Player>,
|
||||
editable_settings: &ReadExpect<'_, EditableSettings>,
|
||||
alias_validator: &ReadExpect<'_, AliasValidator>,
|
||||
msg: ClientCharacterScreen,
|
||||
msg: ClientGeneral,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
match msg {
|
||||
// Request spectator state
|
||||
ClientCharacterScreen::Spectate if client.registered => {
|
||||
client.in_game = Some(ClientIngame::Spectator)
|
||||
ClientGeneral::Spectate if client.registered => {
|
||||
client.in_game = Some(ClientInGame::Spectator)
|
||||
},
|
||||
ClientCharacterScreen::Spectate => {
|
||||
debug!("dropped Spectate msg from unregistered client")
|
||||
},
|
||||
ClientCharacterScreen::Character(character_id)
|
||||
ClientGeneral::Spectate => debug!("dropped Spectate msg from unregistered client"),
|
||||
ClientGeneral::Character(character_id)
|
||||
if client.registered && client.in_game.is_none() =>
|
||||
{
|
||||
if let Some(player) = players.get(entity) {
|
||||
@ -296,27 +295,25 @@ impl Sys {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client.send_msg(ServerCharacterScreen::CharacterDataLoadError(String::from(
|
||||
client.send_msg(ServerGeneral::CharacterDataLoadError(String::from(
|
||||
"Failed to fetch player entity",
|
||||
)))
|
||||
}
|
||||
}
|
||||
ClientCharacterScreen::Character(_) => {
|
||||
ClientGeneral::Character(_) => {
|
||||
let registered = client.registered;
|
||||
let in_game = client.in_game;
|
||||
debug!(?registered, ?in_game, "dropped Character msg from client");
|
||||
},
|
||||
ClientCharacterScreen::RequestCharacterList => {
|
||||
ClientGeneral::RequestCharacterList => {
|
||||
if let Some(player) = players.get(entity) {
|
||||
character_loader.load_character_list(entity, player.uuid().to_string())
|
||||
}
|
||||
},
|
||||
ClientCharacterScreen::CreateCharacter { alias, tool, body } => {
|
||||
ClientGeneral::CreateCharacter { alias, tool, body } => {
|
||||
if let Err(error) = alias_validator.validate(&alias) {
|
||||
debug!(?error, ?alias, "denied alias as it contained a banned word");
|
||||
client.send_msg(ServerCharacterScreen::CharacterActionError(
|
||||
error.to_string(),
|
||||
));
|
||||
client.send_msg(ServerGeneral::CharacterActionError(error.to_string()));
|
||||
} else if let Some(player) = players.get(entity) {
|
||||
character_creator::create_character(
|
||||
entity,
|
||||
@ -328,7 +325,7 @@ impl Sys {
|
||||
);
|
||||
}
|
||||
},
|
||||
ClientCharacterScreen::DeleteCharacter(character_id) => {
|
||||
ClientGeneral::DeleteCharacter(character_id) => {
|
||||
if let Some(player) = players.get(entity) {
|
||||
character_loader.delete_character(
|
||||
entity,
|
||||
@ -337,6 +334,7 @@ impl Sys {
|
||||
);
|
||||
}
|
||||
},
|
||||
_ => unreachable!("not a client_character_screen msg"),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -379,7 +377,7 @@ impl Sys {
|
||||
};
|
||||
|
||||
const INITIAL_VD: Option<u32> = Some(5); //will be changed after login
|
||||
let player = Player::new(username.clone(), None, INITIAL_VD, uuid);
|
||||
let player = Player::new(username, None, INITIAL_VD, uuid);
|
||||
let is_admin = editable_settings.admins.contains(&uuid);
|
||||
|
||||
if !player.is_valid() {
|
||||
|
@ -4,7 +4,7 @@ use common::{
|
||||
comp::{self, bird_medium, Alignment, Player, Pos},
|
||||
event::{EventBus, ServerEvent},
|
||||
generation::get_npc_name,
|
||||
msg::ServerInGame,
|
||||
msg::ServerGeneral,
|
||||
npc::NPC_NAMES,
|
||||
span,
|
||||
state::TerrainChanges,
|
||||
@ -63,7 +63,7 @@ impl<'a> System<'a> for Sys {
|
||||
Ok((chunk, supplement)) => (chunk, supplement),
|
||||
Err(Some(entity)) => {
|
||||
if let Some(client) = clients.get_mut(entity) {
|
||||
client.send_msg(ServerInGame::TerrainChunkUpdate {
|
||||
client.send_msg(ServerGeneral::TerrainChunkUpdate {
|
||||
key,
|
||||
chunk: Err(()),
|
||||
});
|
||||
@ -90,7 +90,7 @@ impl<'a> System<'a> for Sys {
|
||||
.magnitude_squared();
|
||||
|
||||
if adjusted_dist_sqr <= view_distance.pow(2) {
|
||||
client.send_msg(ServerInGame::TerrainChunkUpdate {
|
||||
client.send_msg(ServerGeneral::TerrainChunkUpdate {
|
||||
key,
|
||||
chunk: Ok(Box::new(chunk.clone())),
|
||||
});
|
||||
|
@ -2,7 +2,7 @@ use super::SysTimer;
|
||||
use crate::client::Client;
|
||||
use common::{
|
||||
comp::{Player, Pos},
|
||||
msg::ServerInGame,
|
||||
msg::ServerGeneral,
|
||||
span,
|
||||
state::TerrainChanges,
|
||||
terrain::TerrainGrid,
|
||||
@ -38,7 +38,7 @@ impl<'a> System<'a> for Sys {
|
||||
.map(|vd| super::terrain::chunk_in_vd(pos.0, *chunk_key, &terrain, vd))
|
||||
.unwrap_or(false)
|
||||
{
|
||||
client.send_msg(ServerInGame::TerrainChunkUpdate {
|
||||
client.send_msg(ServerGeneral::TerrainChunkUpdate {
|
||||
key: *chunk_key,
|
||||
chunk: Ok(Box::new(match terrain.get_key(*chunk_key) {
|
||||
Some(chunk) => chunk.clone(),
|
||||
@ -51,7 +51,7 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// TODO: Don't send all changed blocks to all clients
|
||||
// Sync changed blocks
|
||||
let msg = ServerInGame::TerrainBlockUpdates(terrain_changes.modified_blocks.clone());
|
||||
let msg = ServerGeneral::TerrainBlockUpdates(terrain_changes.modified_blocks.clone());
|
||||
for (player, client) in (&players, &mut clients).join() {
|
||||
if player.view_distance.is_some() {
|
||||
client.send_msg(msg.clone());
|
||||
|
Loading…
Reference in New Issue
Block a user