Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add steamworks transport #89

Merged
merged 30 commits into from
Jul 18, 2023
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5f8c61d
First setup
TrustNoOneElse Jun 16, 2023
a813f5d
Added implementation of incoming events
TrustNoOneElse Jun 17, 2023
1a54af0
Fix typo
TrustNoOneElse Jun 17, 2023
8bbce98
Added host logic to the server
TrustNoOneElse Jun 18, 2023
2801c51
Fix bug where the server would only recognize one event at a time
TrustNoOneElse Jun 18, 2023
1d76f53
Removed specific host implementation
TrustNoOneElse Jun 18, 2023
8151355
Added to the bevy_renet project
TrustNoOneElse Jun 19, 2023
f47bef2
Added first example as good as it can be for now
TrustNoOneElse Jun 19, 2023
a15c9e3
Added bevy examples
TrustNoOneElse Jun 21, 2023
c1dc09c
Implementation callback for getting aware of the connection state for…
TrustNoOneElse Jul 10, 2023
06a7141
Cleanup
TrustNoOneElse Jul 10, 2023
e07a4e1
Add missing run callbacks
TrustNoOneElse Jul 10, 2023
7b29db6
Finalize
TrustNoOneElse Jul 10, 2023
cb1c0c4
Cleanup demo_bevy
TrustNoOneElse Jul 11, 2023
737554c
Removed unused import
TrustNoOneElse Jul 11, 2023
78bc54a
Update renet_steam_transport/src/transport/server.rs
TrustNoOneElse Jul 12, 2023
0c335bf
Commite suggested change for server.rs
TrustNoOneElse Jul 12, 2023
3fccb70
Merge branch 'steam-transport' of https://github.com/TrustNoOneElse/r…
TrustNoOneElse Jul 12, 2023
a57109c
Fix github commit error
TrustNoOneElse Jul 12, 2023
ce7196e
Added Reciever instead of Arc
TrustNoOneElse Jul 12, 2023
9dee346
Merge branch 'master' into steam
lucaspoffo Jul 16, 2023
5d308a8
RenetSteam: update with master and rework modules
lucaspoffo Jul 16, 2023
19f1405
DemoChat: update steam support
lucaspoffo Jul 16, 2023
b3a8506
Add echo example
lucaspoffo Jul 17, 2023
3fc1424
Use networking_sockets instead of callbacks
lucaspoffo Jul 17, 2023
4d310c5
Undo demo changes using steam
lucaspoffo Jul 18, 2023
8d98662
Rename renet_steam_transport to renet_steam
lucaspoffo Jul 18, 2023
69c5b9e
Return error when sendind packets for client
lucaspoffo Jul 18, 2023
b9275a6
Allow steamworks git while new version is unreleased
lucaspoffo Jul 18, 2023
7f7103a
Update comments
lucaspoffo Jul 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
[workspace]
members = ["renet", "demo_chat", "demo_bevy", "renetcode", "bevy_renet", "renet_visualizer"]
members = [
"renet",
"demo_chat",
"demo_bevy",
"renetcode",
"bevy_renet",
"renet_visualizer",
"renet_steam_transport",
]
resolver = "2"
21 changes: 17 additions & 4 deletions bevy_renet/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,26 @@ version = "0.0.8"
[features]
default = ["transport"]
transport = ["renet/transport"]
steam_transport = ["renet_steam_transport", "steamworks"]

[dependencies]
bevy = {version = "0.10.1", default-features = false}
renet = {path = "../renet", version = "0.0.12", features = ["bevy"]}


bevy = { version = "0.10.1", default-features = false }
renet = { path = "../renet", version = "0.0.12", features = ["bevy"] }
renet_steam_transport = { path = "../renet_steam_transport", version = "0.0.1", features = [
"bevy",
], optional = true }
steamworks = { git = "https://github.com/Noxime/steamworks-rs", rev = "2c77327", optional = true }

[dev-dependencies]
bevy = {version = "0.10.1", default-features = false, features = ["bevy_core_pipeline", "bevy_render", "bevy_asset", "bevy_pbr", "x11"]}
bevy = { version = "0.10.1", default-features = false, features = [
"bevy_core_pipeline",
"bevy_render",
"bevy_asset",
"bevy_pbr",
"x11",
] }
bincode = "1.3.1"
env_logger = "0.10.0"
serde = {version = "1.0", features = ["derive"]}
serde = { version = "1.0", features = ["derive"] }
6 changes: 6 additions & 0 deletions bevy_renet/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
pub use renet;

#[cfg(feature = "steam_transport")]
pub use renet_steam_transport;

use bevy::prelude::*;

use renet::{RenetClient, RenetServer, ServerEvent};

#[cfg(feature = "transport")]
pub mod transport;

#[cfg(feature = "steam_transport")]
pub mod steam_transport;

/// Set for networking systems.
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum RenetSet {
Expand Down
88 changes: 88 additions & 0 deletions bevy_renet/src/steam_transport.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use bevy::{
prelude::{resource_exists, App, Condition, CoreSet, IntoSystemConfig, IntoSystemSetConfig, Plugin, Res, ResMut, SystemSet},
time::Time,
};
use renet::{RenetClient, RenetServer};
use renet_steam_transport::transport::Transport;
use renet_steam_transport::transport::{client::SteamClientTransport, server::SteamServerTransport};
use steamworks::ClientManager;

use crate::RenetSet;

#[cfg(feature = "steam_transport")]
/// Set for networking systems.
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub enum TransportSet {
Client,
Server,
}
#[cfg(feature = "steam_transport")]
pub struct SteamServerPlugin;
#[cfg(feature = "steam_transport")]
pub struct SteamClientPlugin;

impl Plugin for SteamServerPlugin {
fn build(&self, app: &mut App) {
app.configure_set(
TransportSet::Server
.run_if(resource_exists::<SteamServerTransport<ClientManager>>().and_then(resource_exists::<RenetServer>()))
.after(RenetSet::Server),
);
app.add_system(Self::update_system.in_base_set(CoreSet::PreUpdate).in_set(TransportSet::Server));
app.add_system(Self::send_packets.in_base_set(CoreSet::PostUpdate).in_set(TransportSet::Server));
}
}

impl SteamServerPlugin {
pub fn update_system(mut transport: ResMut<SteamServerTransport<ClientManager>>, mut server: ResMut<RenetServer>, time: Res<Time>) {
transport.update(time.delta(), &mut server)
}

pub fn send_packets(mut transport: ResMut<SteamServerTransport<ClientManager>>, mut server: ResMut<RenetServer>) {
transport.send_packets(&mut server);
}
}

/// Configure the client transport to run only if the client is connected. Otherwise it will throw log errors in the connecting state
impl Plugin for SteamClientPlugin {
fn build(&self, app: &mut App) {
app.configure_set(
TransportSet::Client
.run_if(resource_exists::<SteamClientTransport>().and_then(resource_exists::<RenetClient>().and_then(client_connected)))
.after(RenetSet::Client),
);
app.add_system(Self::update_system.in_base_set(CoreSet::PreUpdate).in_set(TransportSet::Client));
app.add_system(Self::send_packets.in_base_set(CoreSet::PostUpdate).in_set(TransportSet::Client));
}
}

impl SteamClientPlugin {
pub fn update_system(mut transport: ResMut<SteamClientTransport>, mut client: ResMut<RenetClient>, time: Res<Time>) {
transport.update(time.delta(), &mut client)
}

pub fn send_packets(mut transport: ResMut<SteamClientTransport>, mut client: ResMut<RenetClient>) {
transport.send_packets(&mut client);
}
}

pub fn client_connected(transport: Option<Res<SteamClientTransport>>) -> bool {
match transport {
Some(transport) => transport.is_connected(),
None => false,
}
}

pub fn client_diconnected(transport: Option<Res<SteamClientTransport>>) -> bool {
match transport {
Some(transport) => transport.is_disconnected(),
None => true,
}
}

pub fn client_connecting(transport: Option<Res<SteamClientTransport>>) -> bool {
match transport {
Some(transport) => transport.is_connecting(),
None => false,
}
}
19 changes: 14 additions & 5 deletions demo_bevy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,21 @@ path = "src/bin/server.rs"

[dependencies]
bevy_rapier3d = "0.21.0"
bevy = { version = "0.10.0", default-features = false, features = ["bevy_core_pipeline", "bevy_asset", "bevy_render", "bevy_pbr", "x11"] }
bevy_renet = { path = "../bevy_renet" }
serde = { version = "1.0", features = [ "derive" ] }
bevy = { version = "0.10.0", default-features = false, features = [
"bevy_core_pipeline",
"bevy_asset",
"bevy_render",
"bevy_pbr",
"x11",
] }
bevy_renet = { path = "../bevy_renet", features = ["steam_transport"] }
serde = { version = "1.0", features = ["derive"] }
bincode = "1.3.1"


# Use version directly when egui is updated to 0.22
bevy_egui = { git = "https://github.com/mvlabat/bevy_egui.git", branch="dependabot/cargo/egui-0.22.0" }
bevy_egui = { git = "https://github.com/mvlabat/bevy_egui.git", branch = "dependabot/cargo/egui-0.22.0" }
renet_visualizer = { path = "../renet_visualizer", features = ["bevy"] }
smooth-bevy-cameras = "0.8.0"
fastrand = "2.0.0"
fastrand = "2.0.0"
steamworks = { git = "https://github.com/Noxime/steamworks-rs", rev = "2c77327" }
5 changes: 5 additions & 0 deletions demo_bevy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ Simple bevy application to demonstrates how you could replicate entities and sen

To run this demo you need first to run the server with `cargo run --bin server`, then you can execute the client with `cargo run --bin client`.
You can toogle [renet_visualizer](https://github.com/lucaspoffo/renet/tree/master/renet_visualizer) with `F1` in the client.

# Demo Bevy Steam

Same as above, but you need to need to add a steam_appid.txt (likely with 480 as content) to the target folder and also the [steam-SDK](https://github.com/Noxime/steamworks-rs/tree/master/steamworks-sys/lib/steam/redistributable_bin). And insead of server its steam_server, same for client is steam_client. You cannot start both of them at the same time, this is cause of Steam, you will need two different devices.
Also you need to set the const SteamId to which you want to connect in the steam_client. Your SteamId if its not known to you will be printed in the console.
140 changes: 4 additions & 136 deletions demo_bevy/src/bin/client.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
use std::{collections::HashMap, net::UdpSocket, time::SystemTime};
use std::{net::UdpSocket, time::SystemTime};

use bevy::{
diagnostic::{FrameTimeDiagnosticsPlugin, LogDiagnosticsPlugin},
prelude::{shape::Icosphere, *},
window::PrimaryWindow,
};
use bevy_egui::{EguiContexts, EguiPlugin};
use bevy_egui::EguiPlugin;
use bevy_renet::{
renet::{
transport::{ClientAuthentication, NetcodeClientTransport, NetcodeTransportError},
Expand All @@ -15,28 +14,10 @@ use bevy_renet::{
RenetClientPlugin,
};
use demo_bevy::{
connection_config, setup_level, ClientChannel, NetworkedEntities, PlayerCommand, PlayerInput, ServerChannel, ServerMessages,
PROTOCOL_ID,
client::*, connection_config, setup_level, NetworkedEntities, PlayerCommand, PlayerInput, ServerChannel, ServerMessages, PROTOCOL_ID,
};
use renet_visualizer::{RenetClientVisualizer, RenetVisualizerStyle};
use smooth_bevy_cameras::{LookTransform, LookTransformBundle, LookTransformPlugin, Smoother};

#[derive(Component)]
struct ControlledPlayer;

#[derive(Default, Resource)]
struct NetworkMapping(HashMap<Entity, Entity>);

#[derive(Debug)]
struct PlayerInfo {
client_entity: Entity,
server_entity: Entity,
}

#[derive(Debug, Default, Resource)]
struct ClientLobby {
players: HashMap<u64, PlayerInfo>,
}
use smooth_bevy_cameras::LookTransformPlugin;

fn new_renet_client() -> (RenetClient, NetcodeClientTransport) {
let client = RenetClient::new(connection_config());
Expand Down Expand Up @@ -98,55 +79,6 @@ fn panic_on_error_system(mut renet_error: EventReader<NetcodeTransportError>) {
}
}

fn update_visulizer_system(
mut egui_contexts: EguiContexts,
mut visualizer: ResMut<RenetClientVisualizer<200>>,
client: Res<RenetClient>,
mut show_visualizer: Local<bool>,
keyboard_input: Res<Input<KeyCode>>,
) {
visualizer.add_network_info(client.network_info());
if keyboard_input.just_pressed(KeyCode::F1) {
*show_visualizer = !*show_visualizer;
}
if *show_visualizer {
visualizer.show_window(egui_contexts.ctx_mut());
}
}

fn player_input(
keyboard_input: Res<Input<KeyCode>>,
mut player_input: ResMut<PlayerInput>,
mouse_button_input: Res<Input<MouseButton>>,
target_query: Query<&Transform, With<Target>>,
mut player_commands: EventWriter<PlayerCommand>,
) {
player_input.left = keyboard_input.pressed(KeyCode::A) || keyboard_input.pressed(KeyCode::Left);
player_input.right = keyboard_input.pressed(KeyCode::D) || keyboard_input.pressed(KeyCode::Right);
player_input.up = keyboard_input.pressed(KeyCode::W) || keyboard_input.pressed(KeyCode::Up);
player_input.down = keyboard_input.pressed(KeyCode::S) || keyboard_input.pressed(KeyCode::Down);

if mouse_button_input.just_pressed(MouseButton::Left) {
let target_transform = target_query.single();
player_commands.send(PlayerCommand::BasicAttack {
cast_at: target_transform.translation,
});
}
}

fn client_send_input(player_input: Res<PlayerInput>, mut client: ResMut<RenetClient>) {
let input_message = bincode::serialize(&*player_input).unwrap();

client.send_message(ClientChannel::Input, input_message);
}

fn client_send_player_commands(mut player_commands: EventReader<PlayerCommand>, mut client: ResMut<RenetClient>) {
for command in player_commands.iter() {
let command_message = bincode::serialize(command).unwrap();
client.send_message(ClientChannel::Command, command_message);
}
}

fn client_sync_players(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
Expand Down Expand Up @@ -229,67 +161,3 @@ fn client_sync_players(
}
}
}

#[derive(Component)]
struct Target;

fn update_target_system(
primary_window: Query<&Window, With<PrimaryWindow>>,
mut target_query: Query<&mut Transform, With<Target>>,
camera_query: Query<(&Camera, &GlobalTransform)>,
) {
let (camera, camera_transform) = camera_query.single();
let mut target_transform = target_query.single_mut();
if let Some(cursor_pos) = primary_window.single().cursor_position() {
if let Some(ray) = camera.viewport_to_world(camera_transform, cursor_pos) {
if let Some(distance) = ray.intersect_plane(Vec3::Y, Vec3::Y) {
target_transform.translation = ray.direction * distance + ray.origin;
}
}
}
}

fn setup_camera(mut commands: Commands) {
commands
.spawn(LookTransformBundle {
transform: LookTransform {
eye: Vec3::new(0.0, 8., 2.5),
target: Vec3::new(0.0, 0.5, 0.0),
up: Vec3::Y,
},
smoother: Smoother::new(0.9),
})
.insert(Camera3dBundle {
transform: Transform::from_xyz(0., 8.0, 2.5).looking_at(Vec3::new(0.0, 0.5, 0.0), Vec3::Y),
..default()
});
}

fn setup_target(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<StandardMaterial>>) {
commands
.spawn(PbrBundle {
mesh: meshes.add(
Mesh::try_from(Icosphere {
radius: 0.1,
subdivisions: 5,
})
.unwrap(),
),
material: materials.add(Color::rgb(1.0, 0.0, 0.0).into()),
transform: Transform::from_xyz(0.0, 0., 0.0),
..Default::default()
})
.insert(Target);
}

fn camera_follow(
mut camera_query: Query<&mut LookTransform, (With<Camera>, Without<ControlledPlayer>)>,
player_query: Query<&Transform, With<ControlledPlayer>>,
) {
let mut cam_transform = camera_query.single_mut();
if let Ok(player_transform) = player_query.get_single() {
cam_transform.eye.x = player_transform.translation.x;
cam_transform.eye.z = player_transform.translation.z + 2.5;
cam_transform.target = player_transform.translation;
}
}
Loading