Skip to content

Commit

Permalink
Correctly revert this time
Browse files Browse the repository at this point in the history
  • Loading branch information
Veritius committed Apr 17, 2024
1 parent 406b777 commit 0cb0dba
Show file tree
Hide file tree
Showing 24 changed files with 164 additions and 442 deletions.
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The following features are planned to be created as additional crates, as part o
## Usage
| Bevy | Stardust |
| ---- | -------- |
| 0.13 | 0.6 |
| 0.13 | 0.5 |
| 0.12 | 0.2 |
| 0.11 | 0.1 |

Expand All @@ -51,7 +51,8 @@ The following features are planned to be created as additional crates, as part o
// For the purpose of this example, we'll assume they magically appeared somehow.

use std::any::TypeId;
use bevy::{prelude::*, app::{ScheduleRunnerPlugin, MainSchedulePlugin}};
use bevy_ecs::prelude::*;
use bevy_app::{prelude::*, ScheduleRunnerPlugin, MainSchedulePlugin};
use bevy_stardust::prelude::*;

// Channels are accessed with types in the type system.
Expand Down Expand Up @@ -106,7 +107,7 @@ const MESSAGE: Bytes = Bytes::from_static("Hello, world!".as_bytes());
// Queueing messages just requires component access.
// This means you can use query filters to achieve better parallelism.
fn send_words_system(
registry: Res<ChannelRegistry>,
registry: ChannelRegistry,
mut query: Query<(Entity, &mut NetworkMessages<Outgoing>), With<NetworkPeer>>
) {
// The ChannelId must be retrieved from the registry.
Expand All @@ -127,12 +128,12 @@ fn send_words_system(
// The reading queue is a different component from the sending queue.
// This means you can read and send bytes in parallel, or in different systems.
fn read_words_system(
registry: Res<ChannelRegistry>,
registry: ChannelRegistry,
query: Query<(Entity, &NetworkMessages<Incoming>), With<NetworkPeer>>
) {
let channel = registry.channel_id(TypeId::of::<MyChannel>()).unwrap();
for (entity, incoming) in query.iter() {
let messages = incoming.get(channel);
let messages = incoming.channel_queue(channel);
for message in messages.iter() {
// Stardust only outputs bytes, so you need to convert to the desired type.
// Also, in real products, don't unwrap, write checks. Never trust user data.
Expand Down
6 changes: 2 additions & 4 deletions stardust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name="bevy_stardust"
version="0.6.0"
version="0.5.1"
edition="2021"
authors=["Veritius <veritiusgaming@gmail.com>"]
license="MIT OR Apache-2.0"
Expand All @@ -14,9 +14,7 @@ bytes = "1.5.0"
smallvec = "1.11.1"
gxhash = { version = "=3.0.0", optional = true } # 3.1 is broken, remove this bound when it's fixed

[dev-dependencies]
fastrand = "2"

[features]
default = ["reflect"]
reflect = []
hashing = ["reflect", "dep:gxhash"]
88 changes: 0 additions & 88 deletions stardust/examples/simple.rs

This file was deleted.

11 changes: 3 additions & 8 deletions stardust/src/channels/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,11 @@
//!
//! All settings are not definitive, but hints to transport layers as how to treat channels.
use bevy::reflect::Reflect;

#[cfg(feature="hashing")]
use {std::hash::Hasher, crate::hashing::StableHash};

/// Configuration for a channel.
#[derive(Debug, Clone, Hash, Reflect)]
#[reflect(Debug, Hash)]
#[derive(Debug, Clone)]
pub struct ChannelConfiguration {
/// Whether messages should be resent if they're missed.
pub reliable: ReliabilityGuarantee,
Expand Down Expand Up @@ -37,8 +34,7 @@ impl StableHash for &ChannelConfiguration {
}

/// The reliability guarantee of a channel.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect)]
#[reflect(Debug, PartialEq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ReliabilityGuarantee {
/// Messages are not guaranteed to arrive.
Unreliable,
Expand All @@ -58,8 +54,7 @@ impl StableHash for ReliabilityGuarantee {
}

/// The ordering guarantee of a channel.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect)]
#[reflect(Debug, PartialEq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OrderingGuarantee {
/// Messages will be available in the order they are received.
/// This is not necessarily the order they were sent. If that matters, use a different variant.
Expand Down
4 changes: 2 additions & 2 deletions stardust/src/channels/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use bevy::app::App;
use crate::channels::config::ChannelConfiguration;
use super::{id::Channel, ChannelRegistryMut};
use super::{id::Channel, SetupChannelRegistry};

mod sealed {
pub trait Sealed {}
Expand Down Expand Up @@ -33,7 +33,7 @@ impl ChannelSetupAppExt for App {
}

// Add to registry
let mut registry = self.world.resource_mut::<ChannelRegistryMut>();
let mut registry = self.world.resource_mut::<SetupChannelRegistry>();
registry.0.register_channel::<C>(config);
}
}
3 changes: 2 additions & 1 deletion stardust/src/channels/id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ impl<C: Channel> Default for ChannelMarker<C> {
///
/// Channel identifiers are generated by the `ChannelRegistry` and are unique to the `World` they originated from.
/// Attempting to use a `ChannelId` in another `World` will probably panic, or give you unintended results.
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Reflect)]
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[cfg_attr(feature="reflect", derive(bevy::reflect::Reflect))]
#[repr(transparent)]
pub struct ChannelId(u32);

Expand Down
18 changes: 17 additions & 1 deletion stardust/src/channels/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,20 @@ mod extension;
pub use config::*;
pub use id::*;
pub use registry::*;
pub use extension::ChannelSetupAppExt;
pub use extension::ChannelSetupAppExt;

use std::sync::Arc;
use bevy::prelude::*;

pub(super) fn channel_build(app: &mut App) {
// Create setup channel registry
app.insert_resource(registry::SetupChannelRegistry(Box::new(ChannelRegistryInner::new())));

}

pub(super) fn channel_finish(app: &mut App) {
// Remove SetupChannelRegistry and put the inner into an Arc inside ChannelRegistry
// This dramatically improves
let registry = app.world.remove_resource::<SetupChannelRegistry>().unwrap();
app.insert_resource(FinishedChannelRegistry(Arc::from(registry.0)));
}
76 changes: 68 additions & 8 deletions stardust/src/channels/registry.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! The channel registry.
use std::{any::TypeId, collections::BTreeMap, ops::{Deref, DerefMut}, sync::Arc};
use bevy::prelude::*;
use bevy::{ecs::{component::ComponentId, system::SystemParam}, prelude::*};
use crate::prelude::ChannelConfiguration;
use super::{id::{Channel, ChannelId}, ToChannelId};

/// Mutable access to the channel registry, only available during app setup.
#[derive(Resource)]
pub(crate) struct ChannelRegistryMut(pub(crate) Box<ChannelRegistryInner>);
pub(crate) struct SetupChannelRegistry(pub(crate) Box<ChannelRegistryInner>);

impl Deref for ChannelRegistryMut {
impl Deref for SetupChannelRegistry {
type Target = ChannelRegistryInner;

#[inline]
Expand All @@ -17,20 +18,22 @@ impl Deref for ChannelRegistryMut {
}
}

impl DerefMut for ChannelRegistryMut {
impl DerefMut for SetupChannelRegistry {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

/// Read-only access to the channel registry, only available after app setup.
/// Immutable access to the channel registry, only available after app setup.
///
/// This can be freely and cheaply cloned, and will point to the same inner channel registry.
/// In almost all cases, you should just use the [`ChannelRegistry`] systemparam.
/// However, this type can be cloned and will point to the same inner value.
/// This makes it useful for asynchronous programming, like in futures.
#[derive(Resource, Clone)]
pub struct ChannelRegistry(pub(crate) Arc<ChannelRegistryInner>);
pub struct FinishedChannelRegistry(pub(crate) Arc<ChannelRegistryInner>);

impl Deref for ChannelRegistry {
impl Deref for FinishedChannelRegistry {
type Target = ChannelRegistryInner;

#[inline]
Expand All @@ -39,6 +42,63 @@ impl Deref for ChannelRegistry {
}
}

/// Access to the configuration of registered channels, at any point.
///
/// If you're writing async code, you might want to look at [`FinishedChannelRegistry`].
pub struct ChannelRegistry<'a>(&'a ChannelRegistryInner);

unsafe impl<'a> SystemParam for ChannelRegistry<'a> {
type State = (ComponentId, ComponentId);
type Item<'w, 's> = ChannelRegistry<'w>;

fn init_state(world: &mut World, system_meta: &mut bevy::ecs::system::SystemMeta) -> Self::State {
// SAFETY: Since we can't register accesses, we do it through Res<T> which can
(
<Res<FinishedChannelRegistry> as SystemParam>::init_state(world, system_meta),
<Res<SetupChannelRegistry> as SystemParam>::init_state(world, system_meta),
)
}

unsafe fn get_param<'w, 's>(
state: &'s mut Self::State,
_system_meta: &bevy::ecs::system::SystemMeta,
world: bevy::ecs::world::unsafe_world_cell::UnsafeWorldCell<'w>,
_change_tick: bevy::ecs::component::Tick,
) -> Self::Item<'w, 's> {
if let Some(ptr) = world.get_resource_by_id(state.0) {
return ChannelRegistry(ptr.deref::<FinishedChannelRegistry>().0.as_ref());
}

if let Some(ptr) = world.get_resource_by_id(state.1) {
return ChannelRegistry(ptr.deref::<SetupChannelRegistry>().0.as_ref());
}

panic!("Neither SetupChannelRegistry or FinishedChannelRegistry were present when attempting to create ChannelRegistry")
}
}

impl ChannelRegistry<'_> {
/// Gets the id fom the `ToChannelId` implementation.
#[inline]
pub fn channel_id(&self, from: impl ToChannelId) -> Option<ChannelId> {
self.0.channel_id(from)
}

/// Gets the channel configuration for `id`.
#[inline]
pub fn channel_config(&self, id: impl ToChannelId) -> Option<&ChannelData> {
self.0.channel_config(id)
}
}

impl Deref for ChannelRegistry<'_> {
type Target = ChannelRegistryInner;

fn deref(&self) -> &Self::Target {
&self.0
}
}

/// Stores channel configuration data. Accessible through the [`ChannelRegistry`] system parameter.
pub struct ChannelRegistryInner {
pub(super) channel_type_ids: BTreeMap<TypeId, ChannelId>,
Expand Down
3 changes: 1 addition & 2 deletions stardust/src/connections/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use bevy::prelude::*;

/// Used to intentionally reduce the performance of peers for testing purposes.
/// If applied to a `NetworkPeer` entity, reduces performance for that peer specifically.
#[derive(Debug, Clone, Component, Reflect)]
#[reflect(Debug, Component)]
#[derive(Debug, Component)]
pub struct NetworkPerformanceReduction {
/// Chance to drop a packet when sending, if the transport is packet-based.
/// This chance is from `0.0` (never) to `1.0` (always), with `0.5` dropping 50% of the time.
Expand Down
9 changes: 7 additions & 2 deletions stardust/src/connections/groups.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ use smallvec::SmallVec;
/// A collection of network peers, used for organisational purposes.
///
/// This can be used for anything, such as teams of players, rooms for replication, or administrative permissions.
#[derive(Debug, Default, Component, Reflect)]
#[reflect(Debug, Component)]
#[derive(Debug, Component)]
pub struct NetworkGroup(pub(crate) SmallVec<[Entity; 8]>);

impl Default for NetworkGroup {
fn default() -> Self {
Self(SmallVec::default())
}
}

impl NetworkGroup {
/// Adds the peer to the network group.
/// Does nothing if the peer is already included.
Expand Down
Loading

0 comments on commit 0cb0dba

Please sign in to comment.