Fixed client/server comms bug

Former-commit-id: fffc9cbf59784e7e2c9c2d9a60b8f2520b6f41fb
This commit is contained in:
Joshua Barretto 2019-03-04 22:05:37 +00:00
parent 257042ec6f
commit bb93f29522
7 changed files with 63 additions and 40 deletions

View File

@ -51,6 +51,7 @@ impl Client {
let mut postbox = PostBox::to_server(addr)?;
postbox.send(ClientMsg::Chat(String::from("Hello, world!")));
postbox.send(ClientMsg::Chat(String::from("World, hello!")));
Ok(Self {
thread_pool: threadpool::Builder::new()
@ -178,7 +179,6 @@ impl Client {
self.last_ping = self.state.get_time();
for msg in new_msgs {
println!("Received message");
match msg {
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),

View File

@ -2,6 +2,7 @@ use std::{
collections::HashMap,
ops::Range,
u64,
fmt,
};
use specs::{
saveload::{Marker, MarkerAllocator},
@ -22,6 +23,12 @@ impl Into<u64> for Uid {
}
}
impl fmt::Display for Uid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl Component for Uid {
type Storage = VecStorage<Self>;
}

View File

@ -9,6 +9,7 @@ use std::{
net::SocketAddr,
thread,
time::Duration,
sync::mpsc::TryRecvError,
};
// External
@ -119,21 +120,17 @@ where
// If an error occured, or previously occured, just give up
if let Some(_) = self.err {
return items.into_iter();
} else if let Err(err) = self.poll.poll(&mut events, Some(Duration::new(0, 0))) {
self.err = Some(err.into());
return items.into_iter();
}
for event in events {
match event.token() {
DATA_TOKEN => match self.recv.try_recv() {
Ok(Ok(item)) => items.push_back(item),
Err(err) => self.err = Some(err.into()),
Ok(Err(err)) => self.err = Some(err.into()),
},
_ => (),
loop {
match self.recv.try_recv() {
Ok(Ok(item)) => items.push_back(item),
Ok(Err(err)) => self.err = Some(err.into()),
Err(TryRecvError::Empty) => break,
Err(err) => self.err = Some(err.into()),
}
}
items.into_iter()
}
}
@ -167,7 +164,7 @@ fn postbox_thread<S, R>(
Err(ref e) if e.kind() == ErrorKind::WouldBlock => {}
Err(e) => {
recv_tx.send(Err(e.into())).unwrap();
}
},
},
DATA_TOKEN => {
let mut packet = bincode::serialize(&send_rx.try_recv().unwrap()).unwrap();
@ -204,9 +201,9 @@ fn postbox_thread<S, R>(
)
.collect::<Vec<u8>>()
.as_slice()) {
Ok(ok) => {
Ok(msg) => {
recv_tx
.send(Ok(ok))
.send(Ok(msg))
.unwrap();
recv_nextlen = 0;
}

View File

@ -1,7 +1,4 @@
// Standard
use std::time::Duration;
// Library
use shred::{Fetch, FetchMut};
use specs::{
Builder,
@ -13,11 +10,14 @@ use specs::{
Storage as EcsStorage,
MaskedStorage as EcsMaskedStorage,
},
saveload::MarkerAllocator,
};
use vek::*;
// Crate
use crate::{comp, sys, terrain::TerrainMap};
use crate::{
comp,
sys,
terrain::TerrainMap,
};
/// How much faster should an in-game day be compared to a real day?
// TODO: Don't hard-code this
@ -91,8 +91,16 @@ impl State {
}
/// Delete an entity from the state's ECS, if it exists
pub fn delete_entity(&mut self, entity: EcsEntity) {
let _ = self.ecs_world.delete_entity(entity);
pub fn delete_entity(&mut self, uid: comp::Uid) {
// Find the ECS entity from its UID
let ecs_entity = self.ecs_world
.read_resource::<comp::UidAllocator>()
.retrieve_entity_internal(uid.into());
// Delete the ECS entity, if it exists
if let Some(ecs_entity) = ecs_entity {
let _ = self.ecs_world.delete_entity(ecs_entity);
}
}
// TODO: Get rid of this

View File

@ -24,9 +24,9 @@ fn main() {
for event in events {
match event {
Event::ClientConnected { ecs_entity } => println!("Client connected!"),
Event::ClientDisconnected { ecs_entity } => println!("Client disconnected!"),
Event::Chat { msg, .. } => println!("[chat] {}", msg),
Event::ClientConnected { uid } => println!("Client {} connected!", uid),
Event::ClientDisconnected { uid } => println!("Client {} disconnected!", uid),
Event::Chat { uid, msg } => println!("[Client {}] {}", uid, msg),
}
}

View File

@ -1,12 +1,13 @@
use specs::Entity as EcsEntity;
use common::{
comp,
msg::{ServerMsg, ClientMsg},
net::PostBox,
};
use crate::Error;
pub struct Client {
pub ecs_entity: EcsEntity,
pub uid: comp::Uid,
pub postbox: PostBox<ServerMsg, ClientMsg>,
pub last_ping: f64,
}
@ -37,4 +38,14 @@ impl Clients {
println!("Sending message...");
}
}
pub fn notify_all_except(&mut self, uid: comp::Uid, msg: ServerMsg) {
for client in &mut self.clients {
if client.uid != uid {
// Consume any errors, deal with them later
let _ = client.postbox.send(msg.clone());
println!("Sending message...");
}
}
}
}

View File

@ -38,13 +38,13 @@ const CLIENT_TIMEOUT: f64 = 5.0; // Seconds
pub enum Event {
ClientConnected {
ecs_entity: EcsEntity,
uid: comp::Uid,
},
ClientDisconnected {
ecs_entity: EcsEntity,
uid: comp::Uid,
},
Chat {
ecs_entity: EcsEntity,
uid: comp::Uid,
msg: String,
},
}
@ -155,15 +155,15 @@ impl Server {
let mut frontend_events = Vec::new();
for postbox in self.postoffice.new_connections() {
let ecs_entity = self.build_player()
.build();
let ecs_entity = self.build_player().build();
let uid = self.state.read_component(ecs_entity).unwrap();
frontend_events.push(Event::ClientConnected {
ecs_entity,
uid,
});
self.clients.add(Client {
ecs_entity,
uid,
postbox,
last_ping: self.state.get_time(),
});
@ -190,7 +190,7 @@ impl Server {
// Process incoming messages
for msg in new_msgs {
match msg {
ClientMsg::Chat(msg) => new_chat_msgs.push((client.ecs_entity, msg)),
ClientMsg::Chat(msg) => new_chat_msgs.push((client.uid, msg)),
ClientMsg::Disconnect => disconnected = true,
}
}
@ -202,9 +202,9 @@ impl Server {
}
if disconnected {
state.delete_entity(client.ecs_entity);
state.delete_entity(client.uid);
frontend_events.push(Event::ClientDisconnected {
ecs_entity: client.ecs_entity,
uid: client.uid,
});
true
} else {
@ -213,11 +213,11 @@ impl Server {
});
// Handle new chat messages
for (ecs_entity, msg) in new_chat_msgs {
for (uid, msg) in new_chat_msgs {
self.clients.notify_all(ServerMsg::Chat(msg.clone()));
frontend_events.push(Event::Chat {
ecs_entity,
uid,
msg,
});
}
@ -233,7 +233,7 @@ impl Server {
&self.state.ecs_world().read_storage::<comp::phys::Vel>(),
&self.state.ecs_world().read_storage::<comp::phys::Dir>(),
).join() {
self.clients.notify_all(ServerMsg::EntityPhysics {
self.clients.notify_all_except(uid, ServerMsg::EntityPhysics {
uid: uid.into(),
pos,
vel,