Skip to content

Commit

Permalink
Add in-game network messages (#717)
Browse files Browse the repository at this point in the history
  • Loading branch information
Indy2222 authored Sep 11, 2023
1 parent 6fa88d4 commit 53be917
Show file tree
Hide file tree
Showing 17 changed files with 399 additions and 158 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

9 changes: 9 additions & 0 deletions crates/messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ homepage.workspace = true
license.workspace = true
categories.workspace = true

[features]
bevy = ["dep:bevy"]

[dependencies]
# DE
de_types.workspace = true

# Other
bevy = { workspace = true, optional = true }
bincode.workspace = true
glam.workspace = true
thiserror.workspace = true
20 changes: 20 additions & 0 deletions crates/messages/src/players/entity.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[cfg(feature = "bevy")]
use bevy::ecs::entity::Entity;
use bincode::{Decode, Encode};

/// Bevy ECS Entity derived identification of an entity.
#[derive(Debug, Encode, Decode)]
pub struct EntityNet(u32);

impl EntityNet {
pub fn index(&self) -> u32 {
self.0
}
}

#[cfg(feature = "bevy")]
impl From<Entity> for EntityNet {
fn from(entity: Entity) -> Self {
Self(entity.index())
}
}
106 changes: 106 additions & 0 deletions crates/messages/src/players/geom.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#[cfg(feature = "bevy")]
use bevy::transform::components::Transform;
use bincode::{Decode, Encode};
#[cfg(feature = "bevy")]
use glam::Quat;
use glam::{Vec2, Vec3, Vec4};

#[derive(Debug, Encode, Decode)]
pub struct TransformNet {
translation: Vec3Net,
rotation: Vec4Net,
scale: Vec3Net,
}

#[cfg(feature = "bevy")]
impl From<Transform> for TransformNet {
fn from(transform: Transform) -> Self {
Self {
translation: transform.translation.into(),
rotation: Vec4Net {
x: transform.rotation.x,
y: transform.rotation.y,
z: transform.rotation.z,
w: transform.rotation.w,
},
scale: transform.scale.into(),
}
}
}

#[cfg(feature = "bevy")]
impl From<TransformNet> for Transform {
fn from(transform: TransformNet) -> Self {
Self {
translation: transform.translation.into(),
rotation: Quat::from_vec4(transform.rotation.into()),
scale: transform.scale.into(),
}
}
}

#[derive(Clone, Copy, Debug, Encode, Decode)]
pub struct Vec2Net {
x: f32,
y: f32,
}

impl From<Vec2> for Vec2Net {
fn from(vec: Vec2) -> Self {
Self { x: vec.x, y: vec.y }
}
}

impl From<Vec2Net> for Vec2 {
fn from(vec: Vec2Net) -> Self {
Self::new(vec.x, vec.y)
}
}

#[derive(Clone, Copy, Debug, Encode, Decode)]
pub struct Vec3Net {
x: f32,
y: f32,
z: f32,
}

impl From<Vec3> for Vec3Net {
fn from(vec: Vec3) -> Self {
Self {
x: vec.x,
y: vec.y,
z: vec.z,
}
}
}

impl From<Vec3Net> for Vec3 {
fn from(vec: Vec3Net) -> Self {
Self::new(vec.x, vec.y, vec.z)
}
}

#[derive(Clone, Copy, Debug, Encode, Decode)]
pub struct Vec4Net {
x: f32,
y: f32,
z: f32,
w: f32,
}

impl From<Vec4> for Vec4Net {
fn from(vec: Vec4) -> Self {
Self {
x: vec.x,
y: vec.y,
z: vec.z,
w: vec.w,
}
}
}

impl From<Vec4Net> for Vec4 {
fn from(vec: Vec4Net) -> Self {
Self::new(vec.x, vec.y, vec.z, vec.w)
}
}
35 changes: 35 additions & 0 deletions crates/messages/src/players/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use bincode::{Decode, Encode};
pub use chat::{ChatMessage, ChatMessageError, MAX_CHAT_LEN};
use de_types::{objects::ActiveObjectType, player::Player};
pub use entity::EntityNet;
pub use geom::{TransformNet, Vec2Net, Vec3Net, Vec4Net};
pub use path::{PathError, PathNet};

mod chat;
mod entity;
mod geom;
mod path;

/// Messages to be sent by a player/client or occasionally the game server to
/// other players.
Expand Down Expand Up @@ -42,7 +49,35 @@ impl<'a> BorrowedFromPlayers<'a> {

/// Message to be sent by a player/client or occasionally the game server to
/// the game server for the distribution to other game players.
///
/// All messages controlling an active entity / object must be local on the
/// sending computer.
#[derive(Debug, Encode, Decode)]
pub enum ToPlayers {
Chat(ChatMessage),
/// Spawn a new active object on the map.
Spawn {
entity: EntityNet,
player: Player,
object_type: ActiveObjectType,
transform: TransformNet,
},
/// Despawn an active object type.
Despawn {
entity: EntityNet,
},
/// Set path to be followed for an object. Any preexisting path will be
/// replaced by this one.
SetPath {
entity: EntityNet,
waypoints: PathNet,
},
/// Instantaneously transform an object.
///
/// This has no effect on scheduled path as it just moves the object which
/// then continues following the path.
Transform {
entity: EntityNet,
transform: TransformNet,
},
}
60 changes: 60 additions & 0 deletions crates/messages/src/players/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use std::mem::size_of;

use bincode::{Decode, Encode};
use de_types::path::Path;
use glam::Vec2;
use thiserror::Error;

use super::Vec2Net;

const MAX_PATH_SIZE: usize = 480;

#[derive(Debug, Encode, Decode)]
pub struct PathNet(Vec<Vec2Net>);

impl TryFrom<&Path> for PathNet {
type Error = PathError;

fn try_from(path: &Path) -> Result<Self, Self::Error> {
let waypoints = path.waypoints();

if waypoints.is_empty() {
return Err(PathError::Empty);
}

let size = waypoints.len() * size_of::<Vec2Net>();
if size > MAX_PATH_SIZE {
return Err(PathError::TooLarge {
size,
max_size: MAX_PATH_SIZE,
});
}

Ok(Self(waypoints.iter().map(|&p| p.into()).collect()))
}
}

impl From<&PathNet> for Path {
fn from(path: &PathNet) -> Self {
let mut waypoints: Vec<Vec2> = Vec::with_capacity(path.0.len());
let mut length = 0.;

for &point in &path.0 {
let point = point.into();
if let Some(prev) = waypoints.last() {
length += prev.distance(point);
}
waypoints.push(point);
}

Path::new(length, waypoints)
}
}

#[derive(Debug, Error)]
pub enum PathError {
#[error("The path is empty")]
Empty,
#[error("Too many path way-points: {size} bytes > {max_size} bytes")]
TooLarge { size: usize, max_size: usize },
}
6 changes: 2 additions & 4 deletions crates/pathing/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,10 @@

use std::rc::Rc;

use de_types::path::Path;
use parry2d::math::Point;

use crate::{
geometry::{which_side, Side},
path::Path,
};
use crate::geometry::{which_side, Side};

/// A linked list of points which keeps track of its length in meters.
pub(crate) struct PointChain {
Expand Down
2 changes: 1 addition & 1 deletion crates/pathing/src/dijkstra.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ use std::{cmp::Ordering, collections::BinaryHeap};

use ahash::AHashSet;
use bevy::utils::FloatOrd;
use de_types::path::Path;
use parry2d::{math::Point, na, query::PointQuery, shape::Segment};

use crate::{
funnel::Funnel,
geometry::{orient, which_side, Side},
graph::VisibilityGraph,
path::Path,
PathQueryProps,
};

Expand Down
2 changes: 1 addition & 1 deletion crates/pathing/src/finder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use ahash::AHashMap;
use bevy::prelude::{debug, info};
use de_map::size::MapBounds;
use de_types::path::Path;
use parry2d::{
math::Point,
na,
Expand All @@ -16,7 +17,6 @@ use crate::{
dijkstra::{find_path, PointContext},
exclusion::ExclusionArea,
graph::VisibilityGraph,
path::Path,
utils::HashableSegment,
PathTarget,
};
Expand Down
3 changes: 2 additions & 1 deletion crates/pathing/src/funnel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

use std::rc::Rc;

use de_types::path::Path;
use parry2d::{math::Point, shape::Segment};

use crate::{chain::PointChain, geometry::Side, path::Path};
use crate::{chain::PointChain, geometry::Side};

/// The funnel consists of a tail and left & right bounds.
///
Expand Down
Loading

0 comments on commit 53be917

Please sign in to comment.