Compare commits
12 Commits
use-remade
...
use-renet-
| Author | SHA1 | Date | |
|---|---|---|---|
| a620f18a55 | |||
| 38f7f5c30a | |||
| e9f53c11e9 | |||
| 12c3cdc87b | |||
| 930753170f | |||
| 2c20b1efea | |||
| 1a632e729e | |||
| 22674822cc | |||
| 0f5a21995a | |||
| 7ea9046414 | |||
| 4fb37e27c5 | |||
|
|
f6fa9ce1e4 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,4 +5,3 @@ build/steamos/hedz_reloaded
|
||||
build/steamos/.env
|
||||
build/macos/src/HEDZReloaded.app/Contents/MacOS
|
||||
build/macos/src/Applications
|
||||
server.log
|
||||
13
Cargo.lock
generated
13
Cargo.lock
generated
@@ -1519,6 +1519,7 @@ dependencies = [
|
||||
"bevy_time",
|
||||
"renet",
|
||||
"renet_netcode",
|
||||
"renet_steam",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -5564,6 +5565,18 @@ dependencies = [
|
||||
"renetcode",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "renet_steam"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f6018afe469d3d2d49fab8fd1cecc46c588ac61498cad879d5781c44b277421"
|
||||
dependencies = [
|
||||
"bevy_ecs",
|
||||
"log",
|
||||
"renet",
|
||||
"steamworks",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "renetcode"
|
||||
version = "1.0.0"
|
||||
|
||||
@@ -61,7 +61,8 @@ bevy_pkv = { version = "0.14", default-features = false, features = [
|
||||
"redb",
|
||||
] }
|
||||
bevy_replicon = "0.37.1"
|
||||
bevy_replicon_renet = "0.13.0"
|
||||
# TODO: i dont think we need this in dedicated server mode
|
||||
bevy_replicon_renet = { version = "0.13.0", features = ["renet_steam"] }
|
||||
bevy_sprite3d = "7.0.0"
|
||||
bevy_trenchbroom = { version = "0.10", default-features = false, features = [
|
||||
"physics-integration",
|
||||
@@ -76,6 +77,7 @@ rand = "=0.8.5"
|
||||
ron = "0.8"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
shared = { path = "crates/shared" }
|
||||
# TODO: i dont think we need this in dedicated server mode
|
||||
steamworks = "0.12"
|
||||
|
||||
[profile.dev.package."*"]
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -20,7 +20,7 @@ client = [
|
||||
"bevy_replicon_renet/client",
|
||||
"bevy_trenchbroom/client",
|
||||
]
|
||||
dbg = ["avian3d/debug-plugin", "dep:bevy-inspector-egui"]
|
||||
dbg = ["avian3d/debug-plugin", "bevy/debug", "dep:bevy-inspector-egui"]
|
||||
|
||||
[dependencies]
|
||||
avian3d = { workspace = true }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
GameState,
|
||||
config::NetworkingConfig,
|
||||
config::NetConfig,
|
||||
protocol::{
|
||||
ClientEnteredPlaying, TbMapEntityId, TbMapEntityMapping, messages::DespawnTbMapEntity,
|
||||
},
|
||||
@@ -17,14 +17,10 @@ use bevy_replicon::{
|
||||
};
|
||||
use bevy_replicon_renet::{
|
||||
RenetChannelsExt,
|
||||
netcode::{ClientAuthentication, NetcodeClientTransport, NetcodeError},
|
||||
renet::{ConnectionConfig, RenetClient},
|
||||
};
|
||||
use bevy_steamworks::Client;
|
||||
use bevy_trenchbroom::geometry::Brushes;
|
||||
use std::{
|
||||
net::{Ipv4Addr, UdpSocket},
|
||||
time::SystemTime,
|
||||
};
|
||||
|
||||
pub mod audio;
|
||||
pub mod backpack;
|
||||
@@ -55,7 +51,7 @@ pub fn plugin(app: &mut App) {
|
||||
|
||||
app.add_systems(
|
||||
OnEnter(GameState::Connecting),
|
||||
connect_to_server.run_if(|config: Res<NetworkingConfig>| config.server.is_some()),
|
||||
connect_to_server.run_if(|config: Res<NetConfig>| config.is_client()),
|
||||
);
|
||||
app.add_systems(Update, despawn_absent_map_entities);
|
||||
app.add_systems(
|
||||
@@ -89,8 +85,9 @@ fn on_disconnect() {
|
||||
|
||||
fn connect_to_server(
|
||||
mut commands: Commands,
|
||||
config: Res<NetworkingConfig>,
|
||||
config: Res<NetConfig>,
|
||||
channels: Res<RepliconChannels>,
|
||||
steam_client: Option<Res<Client>>,
|
||||
) -> Result {
|
||||
let server_channels_config = channels.server_configs();
|
||||
let client_channels_config = channels.client_configs();
|
||||
@@ -102,32 +99,47 @@ fn connect_to_server(
|
||||
});
|
||||
|
||||
commands.insert_resource(client);
|
||||
commands.insert_resource(client_transport(&config)?);
|
||||
|
||||
if let NetConfig::SteamClient(host_steam_id) = &*config {
|
||||
let Some(steam_client) = steam_client else {
|
||||
return Err("Steam client not found".into());
|
||||
};
|
||||
|
||||
info!("connecting to steam host: {host_steam_id:?}");
|
||||
let transport = bevy_replicon_renet::steam::SteamClientTransport::new(
|
||||
(**steam_client).clone(),
|
||||
host_steam_id,
|
||||
)?;
|
||||
|
||||
commands.insert_resource(transport);
|
||||
} else if let NetConfig::NetcodeClient(host_addr) = &*config {
|
||||
use std::time::SystemTime;
|
||||
|
||||
info!("connecting to netcode host: {host_addr:?}");
|
||||
|
||||
let current_time = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap();
|
||||
let client_id = current_time.as_millis() as u64;
|
||||
let socket = std::net::UdpSocket::bind((std::net::Ipv4Addr::UNSPECIFIED, 0))?;
|
||||
let authentication = bevy_replicon_renet::netcode::ClientAuthentication::Unsecure {
|
||||
client_id,
|
||||
protocol_id: 0,
|
||||
server_addr: host_addr.clone(),
|
||||
user_data: None,
|
||||
};
|
||||
let transport = bevy_replicon_renet::netcode::NetcodeClientTransport::new(
|
||||
current_time,
|
||||
authentication,
|
||||
socket,
|
||||
)?;
|
||||
|
||||
commands.insert_resource(transport);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn client_transport(config: &NetworkingConfig) -> Result<NetcodeClientTransport, NetcodeError> {
|
||||
let current_time = SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.unwrap();
|
||||
let client_id = current_time.as_millis() as u64;
|
||||
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, 0))?;
|
||||
let server_addr = config
|
||||
.server
|
||||
.flatten()
|
||||
.unwrap_or_else(|| "127.0.0.1:31111".parse().unwrap());
|
||||
let authentication = ClientAuthentication::Unsecure {
|
||||
client_id,
|
||||
protocol_id: 0,
|
||||
server_addr,
|
||||
user_data: None,
|
||||
};
|
||||
|
||||
info!("attempting connection to {server_addr}");
|
||||
NetcodeClientTransport::new(current_time, authentication, socket)
|
||||
}
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
fn migrate_remote_entities(
|
||||
query: Query<(Entity, &TbMapEntityId), (Added<TbMapEntityId>, With<ConfirmHistory>)>,
|
||||
|
||||
@@ -4,10 +4,11 @@ use bevy_pkv::prelude::*;
|
||||
use crate::{client::audio::SoundSettings, utils::Debounce};
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
#[cfg(not(feature = "dbg"))]
|
||||
app.insert_resource(PkvStore::new("Rustunit", "HEDZ"));
|
||||
|
||||
app.add_systems(Update, persist_settings);
|
||||
app.add_systems(Startup, load_settings);
|
||||
app.add_systems(Update, persist_settings.run_if(resource_exists::<PkvStore>));
|
||||
app.add_systems(Startup, load_settings.run_if(resource_exists::<PkvStore>));
|
||||
}
|
||||
|
||||
fn persist_settings(
|
||||
|
||||
@@ -61,6 +61,14 @@ fn test_steam_system(steam_client: Res<Client>) {
|
||||
},
|
||||
);
|
||||
|
||||
let id = steam_client.user().steam_id();
|
||||
|
||||
info!("Steam ID: {:?}", id);
|
||||
|
||||
steam_client
|
||||
.friends()
|
||||
.set_rich_presence("connect", Some(id.raw().to_string().as_str()));
|
||||
|
||||
for friend in steam_client.friends().get_friends(FriendFlags::IMMEDIATE) {
|
||||
info!(
|
||||
"Steam Friend: {:?} - {}({:?})",
|
||||
|
||||
@@ -1,25 +1,92 @@
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use bevy::prelude::*;
|
||||
use clap::Parser;
|
||||
use std::net::SocketAddr;
|
||||
use steamworks::SteamId;
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
let config = NetworkingConfig::parse();
|
||||
|
||||
let config: NetConfig = config.into();
|
||||
|
||||
info!("net config: {:?}", config);
|
||||
|
||||
app.insert_resource(config);
|
||||
}
|
||||
|
||||
#[derive(Resource, Parser, Debug)]
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct NetworkingConfig {
|
||||
/// The IP/port to connect to.
|
||||
/// If `None`, host a local server.
|
||||
/// If Some(None), connect to the default server (`127.0.0.1:31111`)
|
||||
/// Otherwise, connect to the given server.
|
||||
/// Does nothing on the server.
|
||||
struct NetworkingConfig {
|
||||
/// Steam id of the host to connect to
|
||||
#[arg(long)]
|
||||
pub server: Option<Option<SocketAddr>>,
|
||||
/// Whether or not to open a port when opening the client, for other clients
|
||||
/// to connect. Does nothing if `server` is set.
|
||||
pub steam_host_id: Option<String>,
|
||||
|
||||
/// Act as steam host
|
||||
#[arg(long)]
|
||||
pub host: bool,
|
||||
pub steam_host: bool,
|
||||
|
||||
/// Act as host using netcode, so we have to define our port
|
||||
#[arg(long)]
|
||||
pub netcode_host: Option<Option<u16>>,
|
||||
|
||||
/// Host address we connect to as a client
|
||||
#[arg(long)]
|
||||
pub netcode_client: Option<Option<String>>,
|
||||
}
|
||||
|
||||
#[derive(Resource, Debug)]
|
||||
pub enum NetConfig {
|
||||
Singleplayer,
|
||||
SteamHost,
|
||||
NetcodeHost { port: u16 },
|
||||
SteamClient(SteamId),
|
||||
NetcodeClient(SocketAddr),
|
||||
}
|
||||
|
||||
impl NetConfig {
|
||||
pub fn is_client(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
NetConfig::SteamClient(_) | NetConfig::NetcodeClient(_)
|
||||
)
|
||||
}
|
||||
|
||||
pub fn is_host(&self) -> bool {
|
||||
matches!(self, NetConfig::SteamHost | NetConfig::NetcodeHost { .. })
|
||||
}
|
||||
|
||||
pub fn is_singleplayer(&self) -> bool {
|
||||
!self.is_client() && !self.is_host()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<NetworkingConfig> for NetConfig {
|
||||
fn from(config: NetworkingConfig) -> Self {
|
||||
match (
|
||||
config.steam_host,
|
||||
config.steam_host_id,
|
||||
config.netcode_host,
|
||||
config.netcode_client,
|
||||
) {
|
||||
(false, None, None, None) => Self::Singleplayer,
|
||||
(true, None, None, None) => Self::SteamHost,
|
||||
(false, Some(id), None, None) => Self::SteamClient(parse_steam_id(id)),
|
||||
(false, None, Some(port), None) => Self::NetcodeHost {
|
||||
port: port.unwrap_or(31111),
|
||||
},
|
||||
(false, None, None, Some(addr)) => Self::NetcodeClient(parse_addr(addr)),
|
||||
_ => panic!("Invalid configuration"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_addr(addr: Option<String>) -> SocketAddr {
|
||||
addr.map(|addr| addr.parse().ok())
|
||||
.flatten()
|
||||
.unwrap_or_else(|| "127.0.0.1:31111".parse().unwrap())
|
||||
}
|
||||
|
||||
fn parse_steam_id(id: String) -> SteamId {
|
||||
let id: u64 = id.parse().unwrap();
|
||||
SteamId::from_raw(id)
|
||||
}
|
||||
|
||||
@@ -34,9 +34,9 @@ pub mod utils;
|
||||
pub mod water;
|
||||
|
||||
use crate::{
|
||||
config::NetworkingConfig,
|
||||
config::NetConfig,
|
||||
heads_database::{HeadDatabaseAsset, HeadsDatabase},
|
||||
protocol::{PlayerId, messages::AssignClientPlayer},
|
||||
protocol::{PlayerIdCounter, messages::AssignClientPlayer},
|
||||
tb_entities::SpawnPoint,
|
||||
};
|
||||
use avian3d::{PhysicsPlugins, prelude::TransformInterpolation};
|
||||
@@ -47,6 +47,7 @@ use bevy_common_assets::ron::RonAssetPlugin;
|
||||
use bevy_replicon::{RepliconPlugins, prelude::ClientId};
|
||||
use bevy_replicon_renet::RepliconRenetPlugins;
|
||||
use bevy_sprite3d::Sprite3dPlugin;
|
||||
use bevy_steamworks::SteamworksEvent;
|
||||
use bevy_trenchbroom::{
|
||||
TrenchBroomPlugins, config::TrenchBroomConfig, prelude::TrenchBroomPhysicsPlugin,
|
||||
};
|
||||
@@ -148,21 +149,21 @@ pub fn plugin(app: &mut App) {
|
||||
if cfg!(feature = "client") {
|
||||
app.add_systems(
|
||||
OnEnter(GameState::Waiting),
|
||||
start_solo_client
|
||||
.run_if(|config: Res<NetworkingConfig>| config.server.is_none() && !config.host),
|
||||
start_solo_client.run_if(|config: Res<NetConfig>| config.is_singleplayer()),
|
||||
);
|
||||
app.add_systems(
|
||||
OnEnter(GameState::Waiting),
|
||||
start_listen_server
|
||||
.run_if(|config: Res<NetworkingConfig>| config.server.is_none() && config.host),
|
||||
start_listen_server.run_if(|config: Res<NetConfig>| config.is_host()),
|
||||
);
|
||||
app.add_systems(
|
||||
OnEnter(GameState::Waiting),
|
||||
start_client.run_if(|config: Res<NetworkingConfig>| config.server.is_some()),
|
||||
start_client.run_if(|config: Res<NetConfig>| config.is_client()),
|
||||
);
|
||||
} else {
|
||||
app.add_systems(OnEnter(GameState::Waiting), start_dedicated_server);
|
||||
}
|
||||
|
||||
app.add_systems(Update, log_steam_events);
|
||||
}
|
||||
|
||||
#[derive(Resource, Reflect, Debug)]
|
||||
@@ -192,18 +193,33 @@ pub enum GameState {
|
||||
Playing,
|
||||
}
|
||||
|
||||
fn log_steam_events(events: Option<MessageReader<SteamworksEvent>>) {
|
||||
let Some(mut events) = events else {
|
||||
return;
|
||||
};
|
||||
|
||||
for event in events.read() {
|
||||
let SteamworksEvent::CallbackResult(result) = event;
|
||||
info!("steam: {:?}", result);
|
||||
}
|
||||
}
|
||||
|
||||
fn start_solo_client(
|
||||
commands: Commands,
|
||||
mut next: ResMut<NextState<GameState>>,
|
||||
query: Query<&Transform, With<SpawnPoint>>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
mut assign_player_id: MessageWriter<AssignClientPlayer>,
|
||||
mut ids: ResMut<PlayerIdCounter>,
|
||||
) {
|
||||
next.set(GameState::Playing);
|
||||
|
||||
player::spawn(commands, ClientId::Server, query, heads_db);
|
||||
ids.reset();
|
||||
let id = ids.alloc();
|
||||
|
||||
assign_player_id.write(AssignClientPlayer(PlayerId { id: 0 }));
|
||||
player::spawn(commands, ClientId::Server, id, query, heads_db);
|
||||
|
||||
assign_player_id.write(AssignClientPlayer(id));
|
||||
}
|
||||
|
||||
fn start_listen_server(
|
||||
@@ -212,12 +228,16 @@ fn start_listen_server(
|
||||
query: Query<&Transform, With<SpawnPoint>>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
mut assign_player_id: MessageWriter<AssignClientPlayer>,
|
||||
mut ids: ResMut<PlayerIdCounter>,
|
||||
) {
|
||||
next.set(GameState::Hosting);
|
||||
|
||||
player::spawn(commands, ClientId::Server, query, heads_db);
|
||||
ids.reset();
|
||||
let id = ids.alloc();
|
||||
|
||||
assign_player_id.write(AssignClientPlayer(PlayerId { id: 0 }));
|
||||
player::spawn(commands, ClientId::Server, id, query, heads_db);
|
||||
|
||||
assign_player_id.write(AssignClientPlayer(id));
|
||||
}
|
||||
|
||||
fn start_client(mut next: ResMut<NextState<GameState>>) {
|
||||
|
||||
@@ -65,6 +65,7 @@ pub fn plugin(app: &mut App) {
|
||||
pub fn spawn(
|
||||
mut commands: Commands,
|
||||
owner: ClientId,
|
||||
id: PlayerId,
|
||||
query: Query<&Transform, With<SpawnPoint>>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
) -> Option<Entity> {
|
||||
@@ -91,7 +92,7 @@ pub fn spawn(
|
||||
transform,
|
||||
Visibility::default(),
|
||||
PlayerCharacterController,
|
||||
PlayerId { id: 0 },
|
||||
id,
|
||||
),
|
||||
Backpack::default(),
|
||||
BackpackUiState::default(),
|
||||
|
||||
@@ -76,6 +76,23 @@ impl From<NetworkedCollider> for Collider {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct PlayerIdCounter {
|
||||
next: u8,
|
||||
}
|
||||
|
||||
impl PlayerIdCounter {
|
||||
pub fn reset(&mut self) {
|
||||
self.next = 0;
|
||||
}
|
||||
|
||||
pub fn alloc(&mut self) -> PlayerId {
|
||||
let id = PlayerId { id: self.next };
|
||||
self.next += 1;
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
/// An ID, unique per player, inserted on the character controller. The `PlayerIdMap` maintains a mapping of ID -> controller entity
|
||||
/// on the server
|
||||
#[derive(Clone, Copy, Component, Hash, Reflect, Serialize, Deserialize, PartialEq, Eq)]
|
||||
|
||||
@@ -74,6 +74,7 @@ pub fn plugin(app: &mut App) {
|
||||
app.register_type::<TbMapIdCounter>();
|
||||
app.register_type::<TbMapEntityMapping>();
|
||||
|
||||
app.init_resource::<PlayerIdCounter>();
|
||||
app.init_resource::<PlayerIdMap>();
|
||||
app.init_resource::<TbMapIdCounter>();
|
||||
app.init_resource::<TbMapEntityMapping>();
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
use crate::{
|
||||
GameState, global_observer,
|
||||
GameState,
|
||||
config::NetConfig,
|
||||
global_observer,
|
||||
heads_database::HeadsDatabase,
|
||||
player::ClientPlayerId,
|
||||
protocol::{ClientEnteredPlaying, PlayerId, SetGameTick, messages::AssignClientPlayer},
|
||||
protocol::{ClientEnteredPlaying, PlayerIdCounter, SetGameTick, messages::AssignClientPlayer},
|
||||
tb_entities::SpawnPoint,
|
||||
tick::GameTick,
|
||||
};
|
||||
@@ -16,12 +18,8 @@ use bevy_replicon::{
|
||||
};
|
||||
use bevy_replicon_renet::{
|
||||
RenetChannelsExt,
|
||||
netcode::{NetcodeServerTransport, ServerAuthentication},
|
||||
renet::{ConnectionConfig, RenetServer},
|
||||
};
|
||||
use std::{
|
||||
net::{Ipv4Addr, UdpSocket},
|
||||
time::SystemTime,
|
||||
steam::SteamServerTransport,
|
||||
};
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
@@ -38,12 +36,14 @@ pub fn plugin(app: &mut App) {
|
||||
fn on_client_playing(
|
||||
trigger: On<FromClient<ClientEnteredPlaying>>,
|
||||
commands: Commands,
|
||||
clients: Query<&ClientPlayerId>,
|
||||
query: Query<&Transform, With<SpawnPoint>>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
) -> Result {
|
||||
info!("client has entered playing gamestate");
|
||||
|
||||
crate::player::spawn(commands, trigger.client_id, query, heads_db)
|
||||
let id = clients.get(trigger.client_id.entity().unwrap()).unwrap();
|
||||
crate::player::spawn(commands, trigger.client_id, id.0, query, heads_db)
|
||||
.ok_or("failed to spawn player")?;
|
||||
|
||||
Ok(())
|
||||
@@ -57,6 +57,8 @@ fn open_renet_server(
|
||||
mut commands: Commands,
|
||||
channels: Res<RepliconChannels>,
|
||||
mut next: ResMut<NextState<GameState>>,
|
||||
steam_client: Option<Res<bevy_steamworks::Client>>,
|
||||
config: Res<NetConfig>,
|
||||
) -> Result<(), BevyError> {
|
||||
info!("opening server");
|
||||
|
||||
@@ -69,22 +71,48 @@ fn open_renet_server(
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
|
||||
let port = 31111;
|
||||
let socket = UdpSocket::bind((Ipv4Addr::UNSPECIFIED, port))?;
|
||||
let server_config = bevy_replicon_renet::netcode::ServerConfig {
|
||||
current_time,
|
||||
max_clients: 1,
|
||||
protocol_id: 0,
|
||||
authentication: ServerAuthentication::Unsecure,
|
||||
public_addresses: Default::default(),
|
||||
};
|
||||
let transport = NetcodeServerTransport::new(server_config, socket)?;
|
||||
if let NetConfig::SteamHost = *config {
|
||||
let Some(steam_client) = steam_client else {
|
||||
return Err("Steam client not found".into());
|
||||
};
|
||||
|
||||
commands.insert_resource(server);
|
||||
commands.insert_resource(transport);
|
||||
let steam_config = bevy_replicon_renet::steam::SteamServerConfig {
|
||||
access_permission: bevy_replicon_renet::steam::AccessPermission::FriendsOnly,
|
||||
max_clients: 16,
|
||||
};
|
||||
|
||||
info!("hosting a server on port {port}");
|
||||
let client = (**steam_client).clone();
|
||||
let transport = SteamServerTransport::new(client, steam_config)?;
|
||||
|
||||
commands.queue(|w: &mut World| {
|
||||
w.insert_resource(server);
|
||||
w.insert_non_send_resource(transport);
|
||||
});
|
||||
|
||||
info!("hosting server: steam");
|
||||
} else if let NetConfig::NetcodeHost { port } = *config {
|
||||
use std::time::SystemTime;
|
||||
|
||||
let current_time = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?;
|
||||
let socket = std::net::UdpSocket::bind((std::net::Ipv4Addr::UNSPECIFIED, port))?;
|
||||
|
||||
let server_config = bevy_replicon_renet::netcode::ServerConfig {
|
||||
current_time,
|
||||
max_clients: 8,
|
||||
protocol_id: 0,
|
||||
authentication: bevy_replicon_renet::netcode::ServerAuthentication::Unsecure,
|
||||
public_addresses: Default::default(),
|
||||
};
|
||||
let transport =
|
||||
bevy_replicon_renet::netcode::NetcodeServerTransport::new(server_config, socket)?;
|
||||
|
||||
commands.insert_resource(server);
|
||||
commands.insert_resource(transport);
|
||||
|
||||
info!("hosting server: netcode on port {port}");
|
||||
} else {
|
||||
return Err("Invalid configuration, choose either steam or netcode".into());
|
||||
}
|
||||
|
||||
next.set(GameState::Playing);
|
||||
|
||||
@@ -100,16 +128,17 @@ fn on_connected(
|
||||
game_tick: Res<GameTick>,
|
||||
mut commands: Commands,
|
||||
mut assign_id: MessageWriter<ToClients<AssignClientPlayer>>,
|
||||
mut ids: ResMut<PlayerIdCounter>,
|
||||
) {
|
||||
let client = trigger.event_target();
|
||||
info!("{client} connected to server!");
|
||||
|
||||
let id = ClientPlayerId(PlayerId { id: 0 });
|
||||
commands.entity(client).insert(id);
|
||||
let id = ids.alloc();
|
||||
commands.entity(client).insert(ClientPlayerId(id));
|
||||
|
||||
assign_id.write(ToClients {
|
||||
mode: SendMode::Direct(ClientId::Client(trigger.entity)),
|
||||
message: AssignClientPlayer(id.0),
|
||||
message: AssignClientPlayer(id),
|
||||
});
|
||||
|
||||
commands.server_trigger(ToClients {
|
||||
|
||||
4
justfile
4
justfile
@@ -13,7 +13,7 @@ run *args:
|
||||
RUST_BACKTRACE=1 cargo r {{ client_args }} -- {{ args }}
|
||||
|
||||
server:
|
||||
RUST_BACKTRACE=1 cargo r {{ server_args }}
|
||||
RUST_BACKTRACE=1 cargo r {{ server_args }} -- --netcode-host
|
||||
|
||||
dbg *args:
|
||||
RUST_BACKTRACE=1 cargo r {{ client_args }} --features dbg -- {{ args }}
|
||||
@@ -22,7 +22,7 @@ dbg-server:
|
||||
RUST_BACKTRACE=1 cargo r {{ server_args }} --features dbg
|
||||
|
||||
sort:
|
||||
cargo sort --check --workspace
|
||||
cargo sort --workspace
|
||||
|
||||
check:
|
||||
cargo sort --check --workspace
|
||||
|
||||
Reference in New Issue
Block a user