This commit is contained in:
parent
fe967d70b9
commit
3dfeae14f7
13 changed files with 146 additions and 72 deletions
|
|
@ -1,17 +1,27 @@
|
|||
use bevy::prelude::*;
|
||||
use bevy::{
|
||||
ecs::{component::Mutable, query::QueryFilter},
|
||||
prelude::*,
|
||||
};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{
|
||||
packet::{InboundPacket, OutboundPacket, Packet},
|
||||
peer::PeerID,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
/// Entities wishing to be networked must have this in their bundle
|
||||
#[derive(Component, Debug)]
|
||||
pub struct EntityNetworkID(Uuid);
|
||||
|
||||
impl Default for EntityNetworkID {
|
||||
fn default() -> Self {
|
||||
Self(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Debug)]
|
||||
pub struct PeerOwned;
|
||||
|
||||
pub trait Networked: Component + NetworkEncodable + NetworkDecodable {}
|
||||
|
||||
impl<T> Networked for T where T: Component + NetworkEncodable + NetworkDecodable {}
|
||||
|
||||
pub trait NetworkEncodable {
|
||||
fn encode(&self) -> Vec<u8>;
|
||||
}
|
||||
|
|
@ -40,45 +50,87 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
fn incoming_network_entity<T: NetworkDecodable + Component>(
|
||||
/// Components wishing to be networked must implement this type
|
||||
pub trait Networked: Component<Mutability = Mutable> + NetworkEncodable + NetworkDecodable {
|
||||
type LocalFilter: QueryFilter;
|
||||
type RemoteFilter: QueryFilter;
|
||||
}
|
||||
|
||||
impl<T> Networked for T
|
||||
where
|
||||
T: Component<Mutability = Mutable> + NetworkEncodable + NetworkDecodable,
|
||||
{
|
||||
type LocalFilter = Without<PeerOwned>;
|
||||
type RemoteFilter = With<PeerOwned>;
|
||||
}
|
||||
|
||||
fn incoming_network_entity<
|
||||
T: NetworkDecodable + Component<Mutability = Mutable>,
|
||||
F: QueryFilter,
|
||||
>(
|
||||
mut inbound: MessageReader<InboundPacket>,
|
||||
mut components: Query<(&mut T, &EntityNetworkID), F>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for InboundPacket(packet) in inbound.read() {
|
||||
'packets: for InboundPacket(packet) in inbound.read() {
|
||||
if let Ok(component) = T::decode(packet.message.clone()) {
|
||||
commands.spawn((component, PeerOwned));
|
||||
for (mut existing_component, id) in &mut components {
|
||||
if id.0 == packet.entity {
|
||||
*existing_component = component;
|
||||
continue 'packets;
|
||||
}
|
||||
}
|
||||
commands.spawn((component, EntityNetworkID(packet.entity), PeerOwned));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn new_peer<T: NetworkEncodable + Component>(
|
||||
add: On<Add, PeerID>,
|
||||
components: Query<&T, Without<PeerOwned>>,
|
||||
components: Query<(&T, &EntityNetworkID), Without<PeerOwned>>,
|
||||
peers: Query<&PeerID>,
|
||||
mut outbound: MessageWriter<OutboundPacket>,
|
||||
) -> Result {
|
||||
let peer = peers.get(add.entity)?;
|
||||
for component in components {
|
||||
outbound.write(Packet::create(peer.id, component.encode()));
|
||||
for (component, id) in components {
|
||||
outbound.write(Packet::create(peer.id, id.0, component.encode()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_entity<T: NetworkEncodable + Component>(
|
||||
fn new_local_entity<T: NetworkEncodable + Component>(
|
||||
add: On<Add, T>,
|
||||
components: Query<&T, Without<PeerOwned>>,
|
||||
components: Query<(&T, &EntityNetworkID), Without<PeerOwned>>,
|
||||
peers: Query<&PeerID>,
|
||||
mut outbound: MessageWriter<OutboundPacket>,
|
||||
) {
|
||||
if let Ok(component) = components.get(add.entity) {
|
||||
if let Ok((component, id)) = components.get(add.entity) {
|
||||
for peer in peers {
|
||||
outbound.write(Packet::create(peer.id, component.encode()));
|
||||
outbound.write(Packet::create(peer.id, id.0, component.encode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn changed_local_entity<T: NetworkEncodable + Component, F: QueryFilter>(
|
||||
components: Query<(&T, &EntityNetworkID), (F, Changed<T>)>,
|
||||
peers: Query<&PeerID>,
|
||||
mut outbound: MessageWriter<OutboundPacket>,
|
||||
) {
|
||||
for (component, id) in components {
|
||||
for peer in peers {
|
||||
outbound.write(Packet::create(peer.id, id.0, component.encode()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn distribution_plugin<T: Networked>(app: &mut App) {
|
||||
app.add_systems(FixedUpdate, incoming_network_entity::<T>)
|
||||
.add_observer(new_peer::<T>)
|
||||
.add_observer(new_entity::<T>);
|
||||
app.add_systems(
|
||||
FixedUpdate,
|
||||
(
|
||||
changed_local_entity::<T, T::LocalFilter>,
|
||||
incoming_network_entity::<T, T::RemoteFilter>,
|
||||
),
|
||||
)
|
||||
.add_observer(new_peer::<T>)
|
||||
.add_observer(new_local_entity::<T>);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue