Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 committed Sep 22, 2023
1 parent f2c36b9 commit 52a397f
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/messages/src/players/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ pub enum ToPlayers {
/// replaced by this one.
SetPath {
entity: EntityNet,
waypoints: PathNet,
waypoints: Option<PathNet>,
},
/// Instantaneously transform an object.
///
Expand Down
2 changes: 1 addition & 1 deletion crates/multiplayer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub use crate::{
netstate::NetState,
playermsg::{
GameNetSet, NetEntities, NetEntityCommands, NetRecvDespawnActiveEvent, NetRecvHealthEvent,
NetRecvSpawnActiveEvent, NetRecvTransformEvent,
NetRecvSetPathEvent, NetRecvSpawnActiveEvent, NetRecvTransformEvent,
},
};
use crate::{netstate::NetStatePlugin, network::NetworkPlugin};
Expand Down
36 changes: 35 additions & 1 deletion crates/multiplayer/src/playermsg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bevy::{
};
use de_core::{gconfig::GameConfig, schedule::PreMovement, state::AppState};
use de_messages::{EntityNet, NetEntityIndex, ToPlayers};
use de_types::{objects::ActiveObjectType, player::Player};
use de_types::{objects::ActiveObjectType, path::Path, player::Player};

use crate::messages::{FromPlayersEvent, MessagesSet};

Expand All @@ -18,6 +18,7 @@ impl Plugin for PlayerMsgPlugin {
.add_event::<NetRecvDespawnActiveEvent>()
.add_event::<NetRecvHealthEvent>()
.add_event::<NetRecvTransformEvent>()
.add_event::<NetRecvSetPathEvent>()
.add_systems(OnEnter(AppState::InGame), setup)
.add_systems(OnExit(AppState::InGame), cleanup)
.add_systems(
Expand Down Expand Up @@ -145,6 +146,26 @@ impl NetRecvTransformEvent {
}
}

#[derive(Event)]
pub struct NetRecvSetPathEvent {
entity: Entity,
path: Option<Path>,
}

impl NetRecvSetPathEvent {
fn new(entity: Entity, path: Option<Path>) -> Self {
Self { entity, path }
}

pub fn entity(&self) -> Entity {
self.entity
}

pub fn path(&self) -> Option<&Path> {
self.path.as_ref()
}
}

#[derive(SystemParam)]
pub struct NetEntities<'w> {
config: Res<'w, GameConfig>,
Expand Down Expand Up @@ -323,12 +344,14 @@ fn cleanup(mut commands: Commands) {
commands.remove_resource::<EntityIdMapRes>();
}

#[allow(clippy::too_many_arguments)]
fn recv_messages(
mut commands: Commands,
mut net_commands: NetEntityCommands,
mut inputs: EventReader<FromPlayersEvent>,
mut spawn_events: EventWriter<NetRecvSpawnActiveEvent>,
mut despawn_events: EventWriter<NetRecvDespawnActiveEvent>,
mut path_events: EventWriter<NetRecvSetPathEvent>,
mut transform_events: EventWriter<NetRecvTransformEvent>,
mut health_events: EventWriter<NetRecvHealthEvent>,
) {
Expand All @@ -354,6 +377,17 @@ fn recv_messages(
let local = net_commands.deregister(*entity);
despawn_events.send(NetRecvDespawnActiveEvent::new(local));
}
ToPlayers::SetPath { entity, waypoints } => {
let Some(local) = net_commands.remote_local_id(*entity) else {
warn!("Received net path update of unrecognized entity: {entity:?}");
continue;
};

path_events.send(NetRecvSetPathEvent::new(
local,
waypoints.as_ref().map(|p| p.into()),
));
}
ToPlayers::Transform { entity, transform } => {
if let Some(local) = net_commands.remote_local_id(*entity) {
transform_events.send(NetRecvTransformEvent::new(local, transform.into()));
Expand Down
2 changes: 2 additions & 0 deletions crates/pathing/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ categories.workspace = true
# DE
de_core.workspace = true
de_map.workspace = true
de_messages.workspace = true
de_multiplayer.workspace = true
de_objects.workspace = true
de_types.workspace = true

Expand Down
3 changes: 3 additions & 0 deletions crates/pathing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ mod graph;
mod path;
mod pplugin;
mod query;
mod syncing;
mod triangulation;
mod utils;

Expand All @@ -24,6 +25,7 @@ pub use path::ScheduledPath;
use pplugin::PathingPlugin;
pub use pplugin::UpdateEntityPathEvent;
pub use query::{PathQueryProps, PathTarget};
use syncing::SyncingPlugin;

pub struct PathingPluginGroup;

Expand All @@ -32,5 +34,6 @@ impl PluginGroup for PathingPluginGroup {
PluginGroupBuilder::start::<Self>()
.add(FinderPlugin)
.add(PathingPlugin)
.add(SyncingPlugin)
}
}
60 changes: 48 additions & 12 deletions crates/pathing/src/pplugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ pub struct PathingPlugin;
impl Plugin for PathingPlugin {
fn build(&self, app: &mut App) {
app.add_event::<UpdateEntityPathEvent>()
.add_event::<PathFoundEvent>()
.add_systems(OnEnter(AppState::InGame), setup)
.add_systems(OnExit(AppState::InGame), cleanup)
.add_systems(
Expand All @@ -51,10 +52,7 @@ impl Plugin for PathingPlugin {
.in_set(PathingSet::UpdateRequestedPaths)
.after(PathingSet::UpdateExistingPaths),
check_path_results
// This is needed to avoid race condition in PathTarget
// removal which would happen if path was not-found before
// this system is run.
.before(PathingSet::UpdateRequestedPaths)
.in_set(PathingSet::PathResults)
// This system removes finished tasks from UpdatePathsState
// and inserts Scheduledpath components. When this happen,
// the tasks is no longer available however the component
Expand All @@ -64,6 +62,12 @@ impl Plugin for PathingPlugin {
// that a path is either already scheduled or being
// computed. Thus this system must run after it.
.after(PathingSet::UpdateExistingPaths),
update_path_components
.after(PathingSet::PathResults)
// This is needed to avoid race condition in PathTarget
// removal which would happen if path was not-found before
// this system is run.
.before(PathingSet::UpdateRequestedPaths),
)
.run_if(in_state(GameState::Playing)),
)
Expand All @@ -75,9 +79,10 @@ impl Plugin for PathingPlugin {
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, SystemSet)]
enum PathingSet {
pub(crate) enum PathingSet {
UpdateRequestedPaths,
UpdateExistingPaths,
PathResults,
}

/// This event triggers computation of shortest path to a target and
Expand All @@ -91,7 +96,8 @@ pub struct UpdateEntityPathEvent {
impl UpdateEntityPathEvent {
/// # Arguments
///
/// * `entity` - entity whose path should be updated / inserted.
/// * `entity` - entity whose path should be updated / inserted. This must
/// be a locally simulated entity.
///
/// * `target` - desired path target & path searching query configuration.
pub fn new(entity: Entity, target: PathTarget) -> Self {
Expand All @@ -107,6 +113,27 @@ impl UpdateEntityPathEvent {
}
}

/// This event is sent when a new path is found for a locally simulated entity.
#[derive(Event)]
pub(crate) struct PathFoundEvent {
entity: Entity,
path: Option<Path>,
}

impl PathFoundEvent {
fn new(entity: Entity, path: Option<Path>) -> Self {
Self { entity, path }
}

pub(crate) fn entity(&self) -> Entity {
self.entity
}

pub(crate) fn path(&self) -> Option<&Path> {
self.path.as_ref()
}
}

#[derive(Default, Resource)]
struct UpdatePathsState {
tasks: AHashMap<Entity, UpdatePathTask>,
Expand Down Expand Up @@ -214,23 +241,32 @@ fn update_requested_paths(
}

fn check_path_results(
mut commands: Commands,
mut state: ResMut<UpdatePathsState>,
targets: Query<&PathTarget>,
mut events: EventWriter<PathFoundEvent>,
) {
for (entity, path) in state.check_results() {
let mut entity_commands = commands.entity(entity);
match path {
events.send(PathFoundEvent::new(entity, path));
}
}

fn update_path_components(
mut commands: Commands,
targets: Query<&PathTarget>,
mut events: EventReader<PathFoundEvent>,
) {
for event in events.iter() {
let mut entity_commands = commands.entity(event.entity());
match event.path() {
Some(path) => {
entity_commands.insert(ScheduledPath::new(path));
entity_commands.insert(ScheduledPath::new(path.clone()));
}
None => {
entity_commands.remove::<ScheduledPath>();

// This must be here on top of target removal in
// remove_path_targets due to the possibility that
// `ScheduledPath` was never found.
if let Ok(target) = targets.get(entity) {
if let Ok(target) = targets.get(event.entity()) {
if !target.permanent() {
entity_commands.remove::<PathTarget>();
}
Expand Down
62 changes: 62 additions & 0 deletions crates/pathing/src/syncing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use bevy::prelude::*;
use de_core::{
gconfig::is_multiplayer,
schedule::{Movement, PreMovement},
state::AppState,
};
use de_messages::ToPlayers;
use de_multiplayer::{GameNetSet, NetEntities, NetRecvSetPathEvent, ToPlayersEvent};

use crate::{
pplugin::{PathFoundEvent, PathingSet},
ScheduledPath,
};

pub struct SyncingPlugin;

impl Plugin for SyncingPlugin {
fn build(&self, app: &mut App) {
app.add_systems(
PreMovement,
receive_paths
.run_if(on_event::<NetRecvSetPathEvent>())
.run_if(in_state(AppState::InGame))
.after(GameNetSet::Messages),
)
.add_systems(
Movement,
send_new_paths
.run_if(is_multiplayer)
.run_if(in_state(AppState::InGame))
.after(PathingSet::PathResults),
);
}
}

fn receive_paths(mut commands: Commands, mut events: EventReader<NetRecvSetPathEvent>) {
for event in events.iter() {
let mut entity_commands = commands.entity(event.entity());

match event.path() {
Some(path) => {
entity_commands.insert(ScheduledPath::new(path.clone()));
}
None => {
entity_commands.remove::<ScheduledPath>();
}
}
}
}

fn send_new_paths(
net_entities: NetEntities,
mut path_events: EventReader<PathFoundEvent>,
mut net_events: EventWriter<ToPlayersEvent>,
) {
for event in path_events.iter() {
net_events.send(ToPlayersEvent::new(ToPlayers::SetPath {
entity: net_entities.local_net_id(event.entity()),
waypoints: event.path().map(|p| p.try_into().unwrap()),
}));
}
}
1 change: 1 addition & 0 deletions crates/types/src/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use glam::Vec2;

/// A path on the map defined by a sequence of way points. Start and target
/// position are included.
#[derive(Clone)]
pub struct Path {
length: f32,
waypoints: Vec<Vec2>,
Expand Down

0 comments on commit 52a397f

Please sign in to comment.