mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Component sync + UID system
Former-commit-id: 5ecddc0e1f9c1a15f99dd167b825178c972da062
This commit is contained in:
parent
ef333877ae
commit
2e613178a0
@ -14,8 +14,9 @@ use std::{
|
|||||||
};
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use threadpool;
|
use threadpool;
|
||||||
|
use specs::Builder;
|
||||||
use common::{
|
use common::{
|
||||||
comp::phys::Vel,
|
comp,
|
||||||
state::State,
|
state::State,
|
||||||
terrain::TerrainChunk,
|
terrain::TerrainChunk,
|
||||||
net::PostBox,
|
net::PostBox,
|
||||||
@ -96,6 +97,13 @@ impl Client {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn state_mut(&mut self) -> &mut State { &mut self.state }
|
pub fn state_mut(&mut self) -> &mut State { &mut self.state }
|
||||||
|
|
||||||
|
/// Get an entity from its UID, creating it if it does not exists
|
||||||
|
pub fn get_or_create_entity(&mut self, uid: u64) -> EcsEntity {
|
||||||
|
self.state.ecs_world_mut().create_entity()
|
||||||
|
.with(comp::Uid(uid))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the player entity
|
/// Get the player entity
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn player(&self) -> Option<EcsEntity> {
|
pub fn player(&self) -> Option<EcsEntity> {
|
||||||
@ -141,7 +149,7 @@ impl Client {
|
|||||||
const PLAYER_VELOCITY: f32 = 100.0;
|
const PLAYER_VELOCITY: f32 = 100.0;
|
||||||
|
|
||||||
// TODO: Set acceleration instead
|
// TODO: Set acceleration instead
|
||||||
self.state.write_component(p, Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
self.state.write_component(p, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tick the client's LocalState (step 3)
|
// Tick the client's LocalState (step 3)
|
||||||
@ -170,11 +178,20 @@ impl Client {
|
|||||||
self.last_ping = self.state.get_time();
|
self.last_ping = self.state.get_time();
|
||||||
|
|
||||||
for msg in new_msgs {
|
for msg in new_msgs {
|
||||||
|
println!("Received message");
|
||||||
match msg {
|
match msg {
|
||||||
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
|
|
||||||
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
ServerMsg::Shutdown => return Err(Error::ServerShutdown),
|
||||||
|
ServerMsg::Chat(msg) => frontend_events.push(Event::Chat(msg)),
|
||||||
|
ServerMsg::EntityPhysics { uid, pos, vel, dir } => {
|
||||||
|
let ecs_entity = self.get_or_create_entity(uid);
|
||||||
|
self.state.write_component(ecs_entity, pos);
|
||||||
|
self.state.write_component(ecs_entity, vel);
|
||||||
|
self.state.write_component(ecs_entity, dir);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if let Some(err) = self.postbox.status() {
|
||||||
|
return Err(err.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(frontend_events)
|
Ok(frontend_events)
|
||||||
|
@ -7,7 +7,7 @@ edition = "2018"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
specs = { version = "0.14", features = ["serde"] }
|
specs = { version = "0.14", features = ["serde"] }
|
||||||
shred = "0.7"
|
shred = "0.7"
|
||||||
vek = "0.9"
|
vek = { version = "0.9", features = ["serde"] }
|
||||||
dot_vox = "1.0"
|
dot_vox = "1.0"
|
||||||
threadpool = "1.7"
|
threadpool = "1.7"
|
||||||
mio = "0.6"
|
mio = "0.6"
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
pub mod phys;
|
pub mod phys;
|
||||||
pub mod uid;
|
pub mod uid;
|
||||||
|
|
||||||
// External
|
// Reexports
|
||||||
|
pub use uid::{Uid, UidAllocator};
|
||||||
|
|
||||||
use specs::World as EcsWorld;
|
use specs::World as EcsWorld;
|
||||||
|
|
||||||
pub fn register_local_components(ecs_world: &mut EcsWorld) {
|
pub fn register_local_components(ecs_world: &mut EcsWorld) {
|
||||||
ecs_world.register::<uid::Uid>();
|
ecs_world.register::<Uid>();
|
||||||
|
|
||||||
ecs_world.register::<phys::Pos>();
|
ecs_world.register::<phys::Pos>();
|
||||||
ecs_world.register::<phys::Vel>();
|
ecs_world.register::<phys::Vel>();
|
||||||
|
@ -4,7 +4,7 @@ use vek::*;
|
|||||||
|
|
||||||
// Pos
|
// Pos
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Pos(pub Vec3<f32>);
|
pub struct Pos(pub Vec3<f32>);
|
||||||
|
|
||||||
impl Component for Pos {
|
impl Component for Pos {
|
||||||
@ -13,7 +13,7 @@ impl Component for Pos {
|
|||||||
|
|
||||||
// Vel
|
// Vel
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Vel(pub Vec3<f32>);
|
pub struct Vel(pub Vec3<f32>);
|
||||||
|
|
||||||
impl Component for Vel {
|
impl Component for Vel {
|
||||||
@ -22,7 +22,7 @@ impl Component for Vel {
|
|||||||
|
|
||||||
// Dir
|
// Dir
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||||
pub struct Dir(pub Vec3<f32>);
|
pub struct Dir(pub Vec3<f32>);
|
||||||
|
|
||||||
impl Component for Dir {
|
impl Component for Dir {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
|
u64,
|
||||||
};
|
};
|
||||||
use specs::{
|
use specs::{
|
||||||
saveload::{Marker, MarkerAllocator},
|
saveload::{Marker, MarkerAllocator},
|
||||||
@ -13,9 +14,12 @@ use specs::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Uid {
|
pub struct Uid(pub u64);
|
||||||
id: u64,
|
|
||||||
seq: u64,
|
impl Into<u64> for Uid {
|
||||||
|
fn into(self) -> u64 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Uid {
|
impl Component for Uid {
|
||||||
@ -24,22 +28,30 @@ impl Component for Uid {
|
|||||||
|
|
||||||
impl Marker for Uid {
|
impl Marker for Uid {
|
||||||
type Identifier = u64;
|
type Identifier = u64;
|
||||||
type Allocator = UidNode;
|
type Allocator = UidAllocator;
|
||||||
|
|
||||||
fn id(&self) -> u64 { self.id }
|
fn id(&self) -> u64 { self.0 }
|
||||||
|
|
||||||
fn update(&mut self, update: Self) {
|
fn update(&mut self, update: Self) {
|
||||||
assert_eq!(self.id, update.id);
|
assert_eq!(self.0, update.0);
|
||||||
self.seq = update.seq;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct UidNode {
|
pub struct UidAllocator {
|
||||||
pub(crate) range: Range<u64>,
|
pub(crate) range: Range<u64>,
|
||||||
pub(crate) mapping: HashMap<u64, Entity>,
|
pub(crate) mapping: HashMap<u64, Entity>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MarkerAllocator<Uid> for UidNode {
|
impl UidAllocator {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
range: 0..u64::MAX,
|
||||||
|
mapping: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MarkerAllocator<Uid> for UidAllocator {
|
||||||
fn allocate(&mut self, entity: Entity, id: Option<u64>) -> Uid {
|
fn allocate(&mut self, entity: Entity, id: Option<u64>) -> Uid {
|
||||||
let id = id.unwrap_or_else(|| {
|
let id = id.unwrap_or_else(|| {
|
||||||
self.range.next().expect("
|
self.range.next().expect("
|
||||||
@ -49,7 +61,7 @@ impl MarkerAllocator<Uid> for UidNode {
|
|||||||
")
|
")
|
||||||
});
|
});
|
||||||
self.mapping.insert(id, entity);
|
self.mapping.insert(id, entity);
|
||||||
Uid { id, seq: 0 }
|
Uid(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn retrieve_entity_internal(&self, id: u64) -> Option<Entity> {
|
fn retrieve_entity_internal(&self, id: u64) -> Option<Entity> {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum ClientMsg {
|
pub enum ClientMsg {
|
||||||
Chat(String),
|
Chat(String),
|
||||||
Disconnect,
|
Disconnect,
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
#[derive(Debug, Serialize, Deserialize)]
|
use crate::comp::phys;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||||
pub enum ServerMsg {
|
pub enum ServerMsg {
|
||||||
Chat(String),
|
|
||||||
Shutdown,
|
Shutdown,
|
||||||
|
Chat(String),
|
||||||
|
EntityPhysics {
|
||||||
|
uid: u64,
|
||||||
|
pos: phys::Pos,
|
||||||
|
vel: phys::Vel,
|
||||||
|
dir: phys::Dir,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,17 @@ use std::time::Duration;
|
|||||||
|
|
||||||
// Library
|
// Library
|
||||||
use shred::{Fetch, FetchMut};
|
use shred::{Fetch, FetchMut};
|
||||||
use specs::{Builder, Component, DispatcherBuilder, Entity as EcsEntity, World as EcsWorld};
|
use specs::{
|
||||||
|
Builder,
|
||||||
|
Component,
|
||||||
|
DispatcherBuilder,
|
||||||
|
Entity as EcsEntity,
|
||||||
|
World as EcsWorld,
|
||||||
|
storage::{
|
||||||
|
Storage as EcsStorage,
|
||||||
|
MaskedStorage as EcsMaskedStorage,
|
||||||
|
},
|
||||||
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
// Crate
|
// Crate
|
||||||
@ -95,9 +105,19 @@ impl State {
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a component
|
/// Write a component attributed to a particular entity
|
||||||
pub fn write_component<C: Component>(&mut self, e: EcsEntity, c: C) {
|
pub fn write_component<C: Component>(&mut self, entity: EcsEntity, comp: C) {
|
||||||
let _ = self.ecs_world.write_storage().insert(e, c);
|
let _ = self.ecs_world.write_storage().insert(entity, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read a clone of a component attributed to a particular entity
|
||||||
|
pub fn read_component<C: Component + Clone>(&self, entity: EcsEntity) -> Option<C> {
|
||||||
|
self.ecs_world.read_storage::<C>().get(entity).cloned()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a read-only reference to the storage of a particular component type
|
||||||
|
pub fn read_storage<C: Component>(&self) -> EcsStorage<C, Fetch<EcsMaskedStorage<C>>> {
|
||||||
|
self.ecs_world.read_storage::<C>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a reference to the internal ECS world
|
/// Get a reference to the internal ECS world
|
||||||
@ -105,6 +125,11 @@ impl State {
|
|||||||
&self.ecs_world
|
&self.ecs_world
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a mutable reference to the internal ECS world
|
||||||
|
pub fn ecs_world_mut(&mut self) -> &mut EcsWorld {
|
||||||
|
&mut self.ecs_world
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a reference to the `Changes` structure of the state. This contains
|
/// Get a reference to the `Changes` structure of the state. This contains
|
||||||
/// information about state that has changed since the last game tick.
|
/// information about state that has changed since the last game tick.
|
||||||
pub fn changes(&self) -> &Changes {
|
pub fn changes(&self) -> &Changes {
|
||||||
|
@ -9,3 +9,4 @@ common = { package = "veloren-common", path = "../common" }
|
|||||||
world = { package = "veloren-world", path = "../world" }
|
world = { package = "veloren-world", path = "../world" }
|
||||||
|
|
||||||
specs = "0.14"
|
specs = "0.14"
|
||||||
|
vek = "0.9"
|
||||||
|
@ -3,9 +3,38 @@ use common::{
|
|||||||
msg::{ServerMsg, ClientMsg},
|
msg::{ServerMsg, ClientMsg},
|
||||||
net::PostBox,
|
net::PostBox,
|
||||||
};
|
};
|
||||||
|
use crate::Error;
|
||||||
|
|
||||||
pub struct Client {
|
pub struct Client {
|
||||||
pub ecs_entity: EcsEntity,
|
pub ecs_entity: EcsEntity,
|
||||||
pub postbox: PostBox<ServerMsg, ClientMsg>,
|
pub postbox: PostBox<ServerMsg, ClientMsg>,
|
||||||
pub last_ping: f64,
|
pub last_ping: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct Clients {
|
||||||
|
clients: Vec<Client>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clients {
|
||||||
|
pub fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
clients: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, client: Client) {
|
||||||
|
self.clients.push(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_if<F: FnMut(&mut Client) -> bool>(&mut self, f: F) {
|
||||||
|
self.clients.drain_filter(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn notify_all(&mut self, msg: ServerMsg) {
|
||||||
|
for client in &mut self.clients {
|
||||||
|
// Consume any errors, deal with them later
|
||||||
|
let _ = client.postbox.send(msg.clone());
|
||||||
|
println!("Sending message...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,14 +14,25 @@ use std::{
|
|||||||
time::Duration,
|
time::Duration,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
};
|
};
|
||||||
use specs::Entity as EcsEntity;
|
use specs::{
|
||||||
|
Entity as EcsEntity,
|
||||||
|
world::EntityBuilder as EcsEntityBuilder,
|
||||||
|
Builder,
|
||||||
|
join::Join,
|
||||||
|
saveload::MarkedBuilder,
|
||||||
|
};
|
||||||
|
use vek::*;
|
||||||
use common::{
|
use common::{
|
||||||
|
comp,
|
||||||
state::State,
|
state::State,
|
||||||
net::PostOffice,
|
net::PostOffice,
|
||||||
msg::{ServerMsg, ClientMsg},
|
msg::{ServerMsg, ClientMsg},
|
||||||
};
|
};
|
||||||
use world::World;
|
use world::World;
|
||||||
use crate::client::Client;
|
use crate::client::{
|
||||||
|
Client,
|
||||||
|
Clients,
|
||||||
|
};
|
||||||
|
|
||||||
const CLIENT_TIMEOUT: f64 = 5.0; // Seconds
|
const CLIENT_TIMEOUT: f64 = 5.0; // Seconds
|
||||||
|
|
||||||
@ -43,19 +54,23 @@ pub struct Server {
|
|||||||
world: World,
|
world: World,
|
||||||
|
|
||||||
postoffice: PostOffice<ServerMsg, ClientMsg>,
|
postoffice: PostOffice<ServerMsg, ClientMsg>,
|
||||||
clients: Vec<Client>,
|
clients: Clients,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Server {
|
impl Server {
|
||||||
/// Create a new `Server`.
|
/// Create a new `Server`.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
|
let mut state = State::new();
|
||||||
|
|
||||||
|
state.ecs_world_mut().add_resource(comp::UidAllocator::new());
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
state: State::new(),
|
state,
|
||||||
world: World::new(),
|
world: World::new(),
|
||||||
|
|
||||||
postoffice: PostOffice::new(SocketAddr::from(([0; 4], 59003)))?,
|
postoffice: PostOffice::new(SocketAddr::from(([0; 4], 59003)))?,
|
||||||
clients: Vec::new(),
|
clients: Clients::empty(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +81,20 @@ impl Server {
|
|||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn state_mut(&mut self) -> &mut State { &mut self.state }
|
pub fn state_mut(&mut self) -> &mut State { &mut self.state }
|
||||||
|
|
||||||
|
/// Build a new entity with a generated UID
|
||||||
|
pub fn build_entity(&mut self) -> EcsEntityBuilder {
|
||||||
|
self.state.ecs_world_mut().create_entity()
|
||||||
|
.marked::<comp::Uid>()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build a new player with a generated UID
|
||||||
|
pub fn build_player(&mut self) -> EcsEntityBuilder {
|
||||||
|
self.build_entity()
|
||||||
|
.with(comp::phys::Pos(Vec3::zero()))
|
||||||
|
.with(comp::phys::Vel(Vec3::zero()))
|
||||||
|
.with(comp::phys::Dir(Vec3::unit_y()))
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a reference to the server's world.
|
/// Get a reference to the server's world.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn world(&self) -> &World { &self.world }
|
pub fn world(&self) -> &World { &self.world }
|
||||||
@ -107,6 +136,9 @@ impl Server {
|
|||||||
// Tick the client's LocalState (step 3)
|
// Tick the client's LocalState (step 3)
|
||||||
self.state.tick(dt);
|
self.state.tick(dt);
|
||||||
|
|
||||||
|
// Synchronise clients with the new state of the world
|
||||||
|
self.sync_clients();
|
||||||
|
|
||||||
// Finish the tick, pass control back to the frontend (step 6)
|
// Finish the tick, pass control back to the frontend (step 6)
|
||||||
Ok(frontend_events)
|
Ok(frontend_events)
|
||||||
}
|
}
|
||||||
@ -123,14 +155,14 @@ impl Server {
|
|||||||
let mut frontend_events = Vec::new();
|
let mut frontend_events = Vec::new();
|
||||||
|
|
||||||
for postbox in self.postoffice.new_connections() {
|
for postbox in self.postoffice.new_connections() {
|
||||||
// TODO: Don't use this method
|
let ecs_entity = self.build_player()
|
||||||
let ecs_entity = self.state.new_test_player();
|
.build();
|
||||||
|
|
||||||
frontend_events.push(Event::ClientConnected {
|
frontend_events.push(Event::ClientConnected {
|
||||||
ecs_entity,
|
ecs_entity,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.clients.push(Client {
|
self.clients.add(Client {
|
||||||
ecs_entity,
|
ecs_entity,
|
||||||
postbox,
|
postbox,
|
||||||
last_ping: self.state.get_time(),
|
last_ping: self.state.get_time(),
|
||||||
@ -147,7 +179,7 @@ impl Server {
|
|||||||
let state = &mut self.state;
|
let state = &mut self.state;
|
||||||
let mut new_chat_msgs = Vec::new();
|
let mut new_chat_msgs = Vec::new();
|
||||||
|
|
||||||
self.clients.drain_filter(|client| {
|
self.clients.remove_if(|client| {
|
||||||
let mut disconnected = false;
|
let mut disconnected = false;
|
||||||
let new_msgs = client.postbox.new_messages();
|
let new_msgs = client.postbox.new_messages();
|
||||||
|
|
||||||
@ -163,8 +195,8 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if
|
} else if
|
||||||
state.get_time() - client.last_ping > CLIENT_TIMEOUT ||
|
state.get_time() - client.last_ping > CLIENT_TIMEOUT || // Timeout
|
||||||
client.postbox.status().is_some()
|
client.postbox.status().is_some() // Postbox eror
|
||||||
{
|
{
|
||||||
disconnected = true;
|
disconnected = true;
|
||||||
}
|
}
|
||||||
@ -182,9 +214,7 @@ impl Server {
|
|||||||
|
|
||||||
// Handle new chat messages
|
// Handle new chat messages
|
||||||
for (ecs_entity, msg) in new_chat_msgs {
|
for (ecs_entity, msg) in new_chat_msgs {
|
||||||
for client in &mut self.clients {
|
self.clients.notify_all(ServerMsg::Chat(msg.clone()));
|
||||||
let _ = client.postbox.send(ServerMsg::Chat(msg.clone()));
|
|
||||||
}
|
|
||||||
|
|
||||||
frontend_events.push(Event::Chat {
|
frontend_events.push(Event::Chat {
|
||||||
ecs_entity,
|
ecs_entity,
|
||||||
@ -194,4 +224,21 @@ impl Server {
|
|||||||
|
|
||||||
Ok(frontend_events)
|
Ok(frontend_events)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sync client states with the most up to date information
|
||||||
|
fn sync_clients(&mut self) {
|
||||||
|
for (&uid, &pos, &vel, &dir) in (
|
||||||
|
&self.state.ecs_world().read_storage::<comp::Uid>(),
|
||||||
|
&self.state.ecs_world().read_storage::<comp::phys::Pos>(),
|
||||||
|
&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 {
|
||||||
|
uid: uid.into(),
|
||||||
|
pos,
|
||||||
|
vel,
|
||||||
|
dir,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user