diff --git a/cosmos_client/src/entities/player/mod.rs b/cosmos_client/src/entities/player/mod.rs index 0f52f2ab..fdb044e9 100644 --- a/cosmos_client/src/entities/player/mod.rs +++ b/cosmos_client/src/entities/player/mod.rs @@ -1,11 +1,48 @@ //! Contains systems and components for the player -use bevy::prelude::App; +use bevy::{color::palettes::css, prelude::*}; +use bevy_rapier3d::prelude::{ActiveEvents, CoefficientCombineRule, Collider, Friction, LockedAxes, ReadMassProperties, RigidBody}; +use cosmos_core::{entities::player::Player, netty::system_sets::NetworkingSystemsSet, persistence::LoadingDistance, state::GameState}; pub mod player_movement; pub mod render_distance; +fn on_add_player( + mut commands: Commands, + mut materials: ResMut>, + mut meshes: ResMut>, + q_player: Query<(Entity, &Player), Added>, +) { + for (ent, player) in q_player.iter() { + commands.entity(ent).insert(( + Mesh3d(meshes.add(Capsule3d::default())), + MeshMaterial3d(materials.add(StandardMaterial { + base_color: css::GREEN.into(), + ..Default::default() + })), + Collider::capsule_y(0.65, 0.25), + LockedAxes::ROTATION_LOCKED, + Name::new(format!("Player ({})", player.name())), + RigidBody::Dynamic, + Friction { + coefficient: 0.0, + combine_rule: CoefficientCombineRule::Min, + }, + LoadingDistance::new(1, 2), + ReadMassProperties::default(), + ActiveEvents::COLLISION_EVENTS, + )); + } +} + pub(super) fn register(app: &mut App) { + app.add_systems( + Update, + on_add_player + .in_set(NetworkingSystemsSet::Between) + .run_if(in_state(GameState::Playing).or(in_state(GameState::LoadingWorld))), + ); + render_distance::register(app); player_movement::register(app); } diff --git a/cosmos_client/src/netty/gameplay/receiver.rs b/cosmos_client/src/netty/gameplay/receiver.rs index 3b751969..53bcd548 100644 --- a/cosmos_client/src/netty/gameplay/receiver.rs +++ b/cosmos_client/src/netty/gameplay/receiver.rs @@ -10,10 +10,7 @@ use bevy_rapier3d::prelude::*; use bevy_renet2::renet2::{transport::NetcodeClientTransport, RenetClient}; use cosmos_core::{ block::Block, - ecs::{ - bundles::{BundleStartingRotation, CosmosPbrBundle}, - NeedsDespawned, - }, + ecs::{bundles::BundleStartingRotation, NeedsDespawned}, entities::player::{render_distance::RenderDistance, Player}, events::{ block_events::{BlockChangedEvent, BlockDataChangedEvent}, @@ -189,8 +186,7 @@ fn lerp_towards( /// TODO: super split this up pub(crate) fn client_sync_players( mut commands: Commands, - (mut meshes, mut client, transport, mut lobby, mut network_mapping): ( - ResMut>, + (mut client, transport, mut lobby, mut network_mapping): ( ResMut, Res, ResMut, @@ -391,7 +387,7 @@ pub(crate) fn client_sync_players( continue; }; - info!("Player {} ({}) connected!", name.as_str(), id); + info!("Player {} ({}) connected! {body:?}", name.as_str(), id); // The player entity may have already been created if some of their components were already synced. let mut entity_cmds = if let Some(player_entity) = network_mapping.client_from_server(&server_entity) { @@ -409,31 +405,12 @@ pub(crate) fn client_sync_players( } }; - error!("Player starting loc: {loc:?}"); - - // this will avoid any position mismatching - // loc.last_transform_loc = Some(loc.local); - entity_cmds.insert(( SetPosition::Location, - CosmosPbrBundle { - location: loc, - rotation: body.rotation.into(), - mesh: Mesh3d(meshes.add(Capsule3d::default())), - ..default() - }, - Collider::capsule_y(0.65, 0.25), - LockedAxes::ROTATION_LOCKED, - Name::new(format!("Player ({name})")), - RigidBody::Dynamic, - Friction { - coefficient: 0.0, - combine_rule: CoefficientCombineRule::Min, - }, + Transform::from_rotation(body.rotation.into()), + loc, body.create_velocity(), Player::new(name, id), - ReadMassProperties::default(), - ActiveEvents::COLLISION_EVENTS, ServerEntity(server_entity), )); diff --git a/cosmos_core/src/entities/player/mod.rs b/cosmos_core/src/entities/player/mod.rs index 5e3c0d38..a8fb1adf 100644 --- a/cosmos_core/src/entities/player/mod.rs +++ b/cosmos_core/src/entities/player/mod.rs @@ -5,8 +5,11 @@ pub mod render_distance; use bevy::prelude::{App, Component}; use bevy_renet2::renet2::ClientId; +use serde::{Deserialize, Serialize}; -#[derive(Component, Debug)] +use crate::netty::sync::{sync_component, IdentifiableComponent, SyncableComponent}; + +#[derive(Component, Debug, Serialize, Deserialize, PartialEq, Eq, Clone)] /// Represents a player pub struct Player { name: String, @@ -32,6 +35,20 @@ impl Player { } } +impl IdentifiableComponent for Player { + fn get_component_unlocalized_name() -> &'static str { + "cosmos:player" + } +} + +impl SyncableComponent for Player { + fn get_sync_type() -> crate::netty::sync::SyncType { + crate::netty::sync::SyncType::ServerAuthoritative + } +} + pub(super) fn register(app: &mut App) { + sync_component::(app); + creative::register(app); } diff --git a/cosmos_server/src/persistence/loading.rs b/cosmos_server/src/persistence/loading.rs index 9d97ac56..cd926fda 100644 --- a/cosmos_server/src/persistence/loading.rs +++ b/cosmos_server/src/persistence/loading.rs @@ -12,7 +12,7 @@ use std::fs; use bevy::{ ecs::schedule::{IntoSystemConfigs, IntoSystemSetConfigs, SystemSet}, hierarchy::BuildChildren, - log::{error, warn}, + log::{error, info, warn}, prelude::{App, Commands, Component, Entity, Quat, Query, Update, With, Without}, reflect::Reflect, };