Switch to replicon (#80)

This commit is contained in:
PROMETHIA-27
2025-12-08 19:22:17 -05:00
committed by GitHub
parent 7a5d2e6914
commit ff52258ad2
55 changed files with 1212 additions and 2951 deletions

View File

@@ -6,6 +6,7 @@ use crate::{
};
use avian3d::prelude::*;
use bevy::{light::NotShadowCaster, prelude::*};
use bevy_replicon::prelude::{SendMode, ServerTriggerExt, ToClients};
use bevy_sprite3d::Sprite3d;
#[derive(Component)]
@@ -44,7 +45,10 @@ fn on_trigger_arrow(
) {
let state = trigger.0;
commands.trigger(PlaySound::Crossbow);
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: PlaySound::Crossbow,
});
let rotation = if let Some(target) = state.target {
let t = query_transform

View File

@@ -6,12 +6,11 @@ use crate::{
physics_layers::GameLayer,
protocol::GltfSceneRoot,
tb_entities::EnemySpawn,
utils::{auto_rotate::AutoRotation, commands::CommandExt, global_observer},
utils::{auto_rotate::AutoRotation, global_observer},
};
use avian3d::prelude::*;
use bevy::prelude::*;
#[cfg(feature = "server")]
use lightyear::prelude::{NetworkTarget, Replicate};
use bevy_replicon::prelude::{Replicated, SendMode, ServerTriggerExt, ToClients};
use std::f32::consts::PI;
const MAX_SHOT_AGES: f32 = 15.;
@@ -60,7 +59,7 @@ fn on_trigger_missile(
let mut transform = Transform::from_translation(state.pos).with_rotation(rotation);
transform.translation += transform.forward().as_vec3() * 2.0;
let mut _projectile = commands.spawn((
commands.spawn((
Name::new("projectile-missile"),
CurverProjectile {
time: time.elapsed_secs(),
@@ -75,15 +74,13 @@ fn on_trigger_missile(
CollisionEventsEnabled,
Visibility::default(),
transform,
Replicated,
children![(
Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()),
AutoRotation(Quat::from_rotation_x(0.4) * Quat::from_rotation_z(0.3)),
GltfSceneRoot::Projectile(head.projectile.clone()),
),],
));
#[cfg(feature = "server")]
_projectile.insert(Replicate::to_clients(NetworkTarget::All));
}
fn enemy_hit(
@@ -169,10 +166,13 @@ fn shot_collision(
continue;
}
commands.trigger_server(BuildExplosionSprite {
pos: shot_pos,
pixels_per_meter: 128.,
time: 0.01,
commands.server_trigger(ToClients {
message: BuildExplosionSprite {
pos: shot_pos,
pixels_per_meter: 128.,
time: 0.01,
},
mode: SendMode::Broadcast,
});
}
}

View File

@@ -6,6 +6,7 @@ use crate::{
};
use avian3d::prelude::*;
use bevy::{light::NotShadowCaster, prelude::*};
use bevy_replicon::prelude::{SendMode, ServerTriggerExt, ToClients};
use bevy_sprite3d::Sprite3d;
#[derive(Component)]
@@ -91,7 +92,10 @@ fn on_trigger_gun(
) {
let state = trigger.0;
commands.trigger(PlaySound::Gun);
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: PlaySound::Gun,
});
let rotation = if let Some(t) = state
.target

View File

@@ -9,8 +9,7 @@ use crate::{
};
use avian3d::prelude::*;
use bevy::prelude::*;
#[cfg(feature = "server")]
use lightyear::prelude::{NetworkTarget, Replicate};
use bevy_replicon::prelude::Replicated;
use std::f32::consts::PI;
const MAX_SHOT_AGES: f32 = 15.;
@@ -61,7 +60,7 @@ fn on_trigger_missile(
let mut transform = Transform::from_translation(state.pos).with_rotation(rotation);
transform.translation += transform.forward().as_vec3() * 2.0;
let mut _projectile = commands.spawn((
commands.spawn((
Name::new("projectile-missile"),
MissileProjectile {
time: time.elapsed_secs(),
@@ -73,13 +72,16 @@ fn on_trigger_missile(
LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()),
),
Sensor,
RigidBody::Kinematic,
CollisionEventsEnabled,
Visibility::default(),
transform,
Replicated,
children![
(
Transform::from_rotation(Quat::from_rotation_x(PI / 2.).inverse()),
GltfSceneRoot::Projectile("missile".to_string()),
Replicated,
),
(
Trail::new(
@@ -99,8 +101,6 @@ fn on_trigger_missile(
)
],
));
#[cfg(feature = "server")]
_projectile.insert(Replicate::to_clients(NetworkTarget::All));
}
fn update(mut query: Query<&mut Transform, With<MissileProjectile>>) {

View File

@@ -10,21 +10,25 @@ use crate::{
loading_assets::GameAssets,
physics_layers::GameLayer,
protocol::PlaySound,
utils::{billboards::Billboard, sprite_3d_animation::AnimationTimer},
utils::{billboards::Billboard, explosions::Explosion, sprite_3d_animation::AnimationTimer},
};
#[cfg(feature = "server")]
use crate::{
aim::AimTarget, character::CharacterHierarchy, control::ControlState, head::ActiveHead,
heads::ActiveHeads, heads_database::HeadsDatabase, player::Player,
utils::explosions::Explosion,
aim::AimTarget,
character::CharacterHierarchy,
control::{ControlState, Inputs},
head::ActiveHead,
heads::ActiveHeads,
heads_database::HeadsDatabase,
player::Player,
protocol::ClientToController,
};
use bevy::{light::NotShadowCaster, prelude::*};
#[cfg(feature = "server")]
use bevy_replicon::prelude::FromClient;
use bevy_replicon::prelude::{ClientState, SendMode, ServerTriggerExt, ToClients};
use bevy_sprite3d::Sprite3d;
pub use healing::Healing;
#[cfg(feature = "server")]
use healing::HealingStateChanged;
#[cfg(feature = "server")]
use lightyear::prelude::input::native::ActionState;
use serde::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, PartialEq, Reflect, Default, Serialize, Deserialize)]
@@ -143,16 +147,16 @@ pub fn plugin(app: &mut App) {
.chain()
.run_if(in_state(GameState::Playing)),
);
#[cfg(feature = "server")]
app.add_systems(
FixedUpdate,
explode_projectiles.in_set(ExplodingProjectileSet::Explode),
explode_projectiles
.run_if(in_state(ClientState::Disconnected))
.in_set(ExplodingProjectileSet::Explode),
);
global_observer!(app, build_explosion_sprite);
}
#[cfg(feature = "server")]
fn explode_projectiles(mut commands: Commands, query: Query<(Entity, &ExplodingProjectile)>) {
for (shot_entity, projectile) in query.iter() {
if let Ok(mut entity) = commands.get_entity(shot_entity) {
@@ -161,7 +165,10 @@ fn explode_projectiles(mut commands: Commands, query: Query<(Entity, &ExplodingP
continue;
}
commands.trigger(projectile.sound.clone());
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: projectile.sound.clone(),
});
commands.trigger(Explosion {
damage: projectile.damage,
@@ -172,12 +179,13 @@ fn explode_projectiles(mut commands: Commands, query: Query<(Entity, &ExplodingP
//TODO: support different impact animations
if projectile.animation {
use crate::utils::commands::CommandExt;
commands.trigger_server(BuildExplosionSprite {
pos: projectile.position,
pixels_per_meter: projectile.anim_pixels_per_meter,
time: projectile.anim_time,
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: BuildExplosionSprite {
pos: projectile.position,
pixels_per_meter: projectile.anim_pixels_per_meter,
time: projectile.anim_time,
},
});
}
}
@@ -186,11 +194,15 @@ fn explode_projectiles(mut commands: Commands, query: Query<(Entity, &ExplodingP
#[cfg(feature = "server")]
fn on_trigger_state(
mut res: ResMut<TriggerStateRes>,
player: Query<(&ActiveHead, &ActionState<ControlState>), With<Player>>,
players: Query<&ActiveHead, With<Player>>,
clients: ClientToController,
mut controls: MessageReader<FromClient<ControlState>>,
headdb: Res<HeadsDatabase>,
time: Res<Time>,
) {
for (player_head, controls) in player.iter() {
for controls in controls.read() {
let player = clients.get_controller(controls.client_id);
let player_head = players.get(player).unwrap();
res.active = controls.trigger;
if controls.just_triggered {
let head_stats = headdb.head_stats(player_head.0);
@@ -203,7 +215,7 @@ fn on_trigger_state(
fn update(
mut res: ResMut<TriggerStateRes>,
mut commands: Commands,
player_query: Query<(Entity, &AimTarget, &ActionState<ControlState>), With<Player>>,
player_query: Query<(Entity, &AimTarget, &Inputs), With<Player>>,
mut active_heads: Single<&mut ActiveHeads, With<Player>>,
heads_db: Res<HeadsDatabase>,
time: Res<Time>,
@@ -215,11 +227,14 @@ fn update(
};
if !state.has_ammo() {
commands.trigger(PlaySound::Invalid);
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: PlaySound::Invalid,
});
return;
}
let Some((player, target, actions)) = player_query.iter().next() else {
let Some((player, target, inputs)) = player_query.iter().next() else {
return;
};
@@ -241,7 +256,7 @@ fn update(
res.next_trigger_timestamp = time.elapsed_secs() + (1. / head.aps);
let trigger_state = TriggerData {
dir: actions.look_dir,
dir: Dir3::try_from(inputs.look_dir).unwrap_or(Dir3::NEG_Z),
pos: projectile_origin,
target: target.0,
target_layer: GameLayer::Npc,
@@ -281,11 +296,15 @@ fn update_heal_ability(
use crate::abilities::healing::HealingState;
if res.active {
use crate::abilities::healing::HealingStateChanged;
commands.trigger(HealingStateChanged {
state: HealingState::Started,
entity: player,
});
} else {
use crate::abilities::healing::HealingStateChanged;
commands.trigger(HealingStateChanged {
state: HealingState::Stopped,
entity: player,

View File

@@ -9,8 +9,7 @@ use crate::{
use avian3d::prelude::*;
use bevy::prelude::*;
use bevy_ballistic::launch_velocity;
#[cfg(feature = "server")]
use lightyear::prelude::{NetworkTarget, Replicate};
use bevy_replicon::prelude::{Replicated, SendMode, ServerTriggerExt, ToClients};
use serde::{Deserialize, Serialize};
#[derive(Component, Serialize, Deserialize, PartialEq)]
@@ -36,7 +35,10 @@ fn on_trigger_thrown(
) {
let state = trigger.event().0;
commands.trigger(PlaySound::Throw);
commands.server_trigger(ToClients {
mode: SendMode::Broadcast,
message: PlaySound::Throw,
});
const SPEED: f32 = 35.;
@@ -57,32 +59,32 @@ fn on_trigger_thrown(
//TODO: projectile db?
let explosion_animation = !matches!(state.head, 8 | 16);
let mut projectile = commands.spawn((
Transform::from_translation(pos),
Name::new("projectile-thrown"),
ThrownProjectile {
impact_animation: explosion_animation,
damage: head.damage,
},
Collider::sphere(0.4),
CollisionLayers::new(
LayerMask(GameLayer::Projectile.to_bits()),
LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()),
),
RigidBody::Dynamic,
CollisionEventsEnabled,
Mass(0.01),
LinearVelocity(vel),
Visibility::default(),
Sensor,
));
projectile.with_child((
AutoRotation(Quat::from_rotation_x(0.4) * Quat::from_rotation_z(0.3)),
GltfSceneRoot::Projectile(head.projectile.clone()),
));
#[cfg(feature = "server")]
projectile.insert(Replicate::to_clients(NetworkTarget::All));
commands
.spawn((
Transform::from_translation(pos),
Name::new("projectile-thrown"),
ThrownProjectile {
impact_animation: explosion_animation,
damage: head.damage,
},
Collider::sphere(0.4),
CollisionLayers::new(
LayerMask(GameLayer::Projectile.to_bits()),
LayerMask(state.target_layer.to_bits() | GameLayer::Level.to_bits()),
),
RigidBody::Dynamic,
CollisionEventsEnabled,
Mass(0.01),
LinearVelocity(vel),
Visibility::default(),
Sensor,
Replicated,
))
.with_child((
AutoRotation(Quat::from_rotation_x(0.4) * Quat::from_rotation_z(0.3)),
GltfSceneRoot::Projectile(head.projectile.clone()),
Replicated,
));
}
fn shot_collision(