Skip to content

Commit

Permalink
Merge pull request #370 from AnthonyTornetta/367-rework-pirate-spawns
Browse files Browse the repository at this point in the history
367 rework pirate spawns
  • Loading branch information
AnthonyTornetta authored Dec 18, 2024
2 parents 8aed9da + e8201d1 commit 7836e20
Show file tree
Hide file tree
Showing 26 changed files with 489 additions and 122 deletions.
1 change: 1 addition & 0 deletions cosmos_client/src/netty/gameplay/receiver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ pub(crate) fn client_sync_players(
structure_entity,
block: ev.block,
new_health: ev.new_health,
causer: ev.causer.and_then(|x| network_mapping.client_from_server(&x)),
})
}));
}
Expand Down
40 changes: 32 additions & 8 deletions cosmos_client/src/projectiles/lasers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Handles the creation of lasers
use bevy::prelude::*;
use bevy::{prelude::*, utils::HashMap};
use bevy_rapier3d::{plugin::RapierContextEntityLink, prelude::RapierContextSimulation};
use bevy_renet2::renet2::*;
use cosmos_core::{
Expand All @@ -10,7 +10,7 @@ use cosmos_core::{
system_sets::NetworkingSystemsSet, NettyChannelServer,
},
physics::location::CosmosBundleSet,
projectiles::laser::Laser,
projectiles::{causer::Causer, laser::Laser},
state::GameState,
};

Expand All @@ -22,7 +22,11 @@ use crate::structure::{
#[derive(Resource)]
struct LaserMesh(Handle<Mesh>);

#[derive(Resource, Default)]
struct LaserMaterials(HashMap<u32, Handle<StandardMaterial>>);

fn create_laser_mesh(mut meshes: ResMut<Assets<Mesh>>, mut commands: Commands) {
commands.init_resource::<LaserMaterials>();
commands.insert_resource(LaserMesh(meshes.add(Mesh::from(Cuboid::new(0.1, 0.1, 1.0)))));
}

Expand All @@ -37,6 +41,7 @@ fn lasers_netty(
mut ev_writer_missile_launcher_fired: EventWriter<MissileLauncherSystemFiredEvent>,
mut q_shield_render: Query<&mut ShieldRender>,
q_default_world: Query<Entity, With<RapierContextSimulation>>,
mut laser_materials: ResMut<LaserMaterials>,
) {
while let Some(message) = client.receive_message(NettyChannelServer::StructureSystems) {
let msg: ServerStructureSystemMessages = cosmos_encoder::deserialize(&message).unwrap();
Expand All @@ -49,13 +54,36 @@ fn lasers_netty(
firer_velocity,
strength,
mut no_hit,
causer,
} => {
if let Some(server_entity) = no_hit {
if let Some(client_entity) = network_mapping.client_from_server(&server_entity) {
no_hit = Some(client_entity);
}
}

let causer = causer.map(|c| network_mapping.client_from_server(&c.0)).and_then(|e| e.map(Causer));

fn color_hash(color: Srgba) -> u32 {
let (r, g, b, a) = (
(color.red * 255.0) as u8,
(color.green * 255.0) as u8,
(color.blue * 255.0) as u8,
(color.alpha * 255.0) as u8,
);

u32::from_be_bytes([r, g, b, a])
}
let color = color.unwrap_or(Color::WHITE);

let material = laser_materials.0.entry(color_hash(color.into())).or_insert_with(|| {
materials.add(StandardMaterial {
base_color: color,
unlit: true,
..Default::default()
})
});

Laser::spawn_custom_pbr(
location,
laser_velocity,
Expand All @@ -64,17 +92,13 @@ fn lasers_netty(
no_hit,
CosmosPbrBundle {
mesh: Mesh3d(laser_mesh.0.clone_weak()),
material: MeshMaterial3d(materials.add(StandardMaterial {
base_color: color.unwrap_or(Color::WHITE),
// emissive: color,
unlit: true,
..Default::default()
})),
material: MeshMaterial3d(material.clone_weak()),
..Default::default()
},
&time,
RapierContextEntityLink(q_default_world.single()),
&mut commands,
causer,
);
}
ServerStructureSystemMessages::LaserCannonSystemFired { ship_entity } => {
Expand Down
4 changes: 3 additions & 1 deletion cosmos_core/src/netty/server_laser_cannon_system_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use bevy::prelude::{Color, Component, Entity, Vec3};
use serde::{Deserialize, Serialize};

use crate::physics::location::Location;
use crate::{physics::location::Location, projectiles::causer::Causer};

#[derive(Debug, Serialize, Deserialize, Component)]
/// All the laser cannon system messages
Expand All @@ -22,6 +22,8 @@ pub enum ServerStructureSystemMessages {
strength: f32,
/// Which entity this laser shouldn't hit (None if it should hit all)
no_hit: Option<Entity>,
/// Who fired this laser
causer: Option<Causer>,
},
/// Sent whenever a laser cannon system is fired
LaserCannonSystemFired {
Expand Down
2 changes: 2 additions & 0 deletions cosmos_core/src/netty/server_reliable_messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ pub struct BlockHealthUpdate {
pub block: StructureBlock,
/// The block's new health
pub new_health: f32,
/// The entity that caused this change
pub causer: Option<Entity>,
}

#[derive(Debug, Serialize, Deserialize, Component)]
Expand Down
14 changes: 12 additions & 2 deletions cosmos_core/src/physics/stop_near_unloaded_chunks.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//! Freezes entities that are near unloaded chunks so they don't fly into unloaded areas.
use bevy::prelude::{App, Commands, Entity, GlobalTransform, PostUpdate, Query, With, Without};
use bevy::prelude::{App, Commands, Entity, GlobalTransform, Parent, PostUpdate, Query, With, Without};
use bevy_rapier3d::prelude::Collider;

use crate::{
ecs::NeedsDespawned,
physics::location::SECTOR_DIMENSIONS,
projectiles::laser::Laser,
structure::{
asteroid::Asteroid,
coordinates::{UnboundChunkCoordinate, UnboundCoordinateType},
Expand All @@ -23,7 +24,16 @@ const FREEZE_RADIUS: UnboundCoordinateType = 1;
const REASON: &str = "cosmos:stop_near_unloaded_chunks";

fn stop_near_unloaded_chunks(
mut query: Query<(Entity, &Location, Option<&mut DisableRigidBody>), (Without<Asteroid>, Without<Planet>, Without<NeedsDespawned>)>,
mut query: Query<
(Entity, &Location, Option<&mut DisableRigidBody>),
(
Without<Asteroid>,
Without<Planet>,
Without<NeedsDespawned>,
Without<Laser>,
Without<Parent>,
),
>,
structures: Query<(Entity, &Structure, &Location, &GlobalTransform)>,
has_collider: Query<(), With<Collider>>,
mut commands: Commands,
Expand Down
51 changes: 51 additions & 0 deletions cosmos_core/src/projectiles/causer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//! Used to identify the causer of this projectile.
//!
//! Typically used to determine damage source
use bevy::{
prelude::{App, Component, Entity},
reflect::Reflect,
};
use serde::{Deserialize, Serialize};

#[cfg(feature = "client")]
use crate::netty::sync::mapping::Mappable;
#[cfg(feature = "client")]
use crate::netty::sync::mapping::MappingError;

#[derive(Component, Debug, Reflect, Clone, Copy, Serialize, Deserialize)]
/// Identifies who fired this projectile.
pub struct Causer(pub Entity);

#[cfg(feature = "client")]
impl Mappable for Causer {
fn map(
self,
network_mapping: &crate::netty::sync::mapping::NetworkMapping,
) -> Result<Self, crate::netty::sync::mapping::MappingError<Self>>
where
Self: Sized,
{
network_mapping
.client_from_server(&self.0)
.map(|x| Ok(Self(x)))
.unwrap_or(Err(MappingError::MissingRecord(self)))
}

fn map_to_server(
self,
network_mapping: &crate::netty::sync::mapping::NetworkMapping,
) -> Result<Self, crate::netty::sync::mapping::MappingError<Self>>
where
Self: Sized,
{
network_mapping
.server_from_client(&self.0)
.map(|x| Ok(Self(x)))
.unwrap_or(Err(MappingError::MissingRecord(self)))
}
}

pub(super) fn register(app: &mut App) {
app.register_type::<Causer>();
}
20 changes: 19 additions & 1 deletion cosmos_core/src/projectiles/laser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ use crate::{
structure::chunk::ChunkEntity,
};

use super::causer::Causer;

/// How long a laser will stay alive for before despawning
pub const LASER_LIVE_TIME: Duration = Duration::from_secs(5);

Expand All @@ -44,6 +46,7 @@ pub struct LaserCollideEvent {
entity_hit: Entity,
local_position_hit: Vec3,
laser_strength: f32,
causer: Option<Causer>,
}

impl LaserCollideEvent {
Expand All @@ -63,6 +66,11 @@ impl LaserCollideEvent {
pub fn local_position_hit(&self) -> Vec3 {
self.local_position_hit
}

/// Returns the entity that caused this laser to be fired
pub fn causer(&self) -> Option<Causer> {
self.causer
}
}

#[derive(Component)]
Expand Down Expand Up @@ -106,6 +114,7 @@ impl Laser {
time: &Time,
context_entity_link: RapierContextEntityLink,
commands: &mut Commands,
causer: Option<Causer>,
) -> Entity {
pbr.rotation = Transform::from_xyz(0.0, 0.0, 0.0)
.looking_at(laser_velocity, Vec3::Y)
Expand Down Expand Up @@ -137,6 +146,10 @@ impl Laser {
NoSendEntity,
));

if let Some(causer) = causer {
ent_cmds.insert(causer);
}

if let Some(ent) = no_collide_entity {
ent_cmds.insert(NoCollide(ent));
}
Expand All @@ -157,6 +170,7 @@ impl Laser {
time: &Time,
context_entity_link: RapierContextEntityLink,
commands: &mut Commands,
causer: Option<Causer>,
) -> Entity {
Self::spawn_custom_pbr(
position,
Expand All @@ -168,6 +182,7 @@ impl Laser {
time,
context_entity_link,
commands,
causer,
)
}
}
Expand All @@ -182,6 +197,7 @@ fn send_laser_hit_events(
&mut Laser,
&Velocity,
Option<&WorldWithin>,
Option<&Causer>,
),
With<Laser>,
>,
Expand All @@ -193,7 +209,7 @@ fn send_laser_hit_events(
worlds: Query<(&Location, &RapierContextEntityLink, Entity), With<PlayerWorld>>,
q_rapier_context: WriteRapierContext,
) {
for (world, location, laser_entity, no_collide_entity, mut laser, velocity, world_within) in query.iter_mut() {
for (world, location, laser_entity, no_collide_entity, mut laser, velocity, world_within, causer) in query.iter_mut() {
if laser.active {
let last_pos = laser.last_position;
let delta_position = last_pos.relative_coords_to(location);
Expand Down Expand Up @@ -254,6 +270,7 @@ fn send_laser_hit_events(
entity_hit: entity,
local_position_hit: lph,
laser_strength: laser.strength,
causer: causer.copied(),
});
}
} else if let Ok(transform) = transform_query.get(entity) {
Expand All @@ -265,6 +282,7 @@ fn send_laser_hit_events(
entity_hit: entity,
local_position_hit: lph,
laser_strength: laser.strength,
causer: causer.copied(),
});
}

Expand Down
2 changes: 2 additions & 0 deletions cosmos_core/src/projectiles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
use bevy::prelude::App;

pub mod causer;
pub mod laser;
pub mod missile;

pub(super) fn register(app: &mut App) {
causer::register(app);
laser::register(app);
missile::register(app);
}
4 changes: 3 additions & 1 deletion cosmos_core/src/structure/base_structure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ impl BaseStructure {
}

/// Gets the block at these block coordinates
pub fn block_at<'a>(&'a self, coords: BlockCoordinate, blocks: &'a Registry<Block>) -> &'a Block {
pub fn block_at<'a>(&self, coords: BlockCoordinate, blocks: &'a Registry<Block>) -> &'a Block {
let id = self.block_id_at(coords);
blocks.from_numeric_id(id)
}
Expand Down Expand Up @@ -486,6 +486,7 @@ impl BaseStructure {
blocks: &Registry<Block>,
amount: f32,
event_writers: Option<(&mut EventWriter<BlockTakeDamageEvent>, &mut EventWriter<BlockDestroyedEvent>)>,
causer: Option<Entity>,
) -> Option<f32> {
if let Some(chunk) = self.mut_chunk_at_block_coordinates(coords) {
let health_left = chunk.block_take_damage(ChunkBlockCoordinate::for_block_coordinate(coords), amount, blocks);
Expand All @@ -498,6 +499,7 @@ impl BaseStructure {
structure_entity,
block,
new_health: health_left,
causer,
});
if health_left <= 0.0 {
destroyed_event_writer.send(BlockDestroyedEvent { structure_entity, block });
Expand Down
9 changes: 7 additions & 2 deletions cosmos_core/src/structure/block_health/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ pub struct BlockDestroyedEvent {
pub block: StructureBlock,
}

/// This event is sent when a block is destroyed
/// This event is sent when a block takes damage
#[derive(Debug, Event)]
pub struct BlockTakeDamageEvent {
/// The structure that had its block destroyed
/// The structure that had its block take damage
pub structure_entity: Entity,
/// The block that took damage
pub block: StructureBlock,
/// The block's new health
pub new_health: f32,
/// The entity that caused this damage if there is one
///
/// This is NOT the direct causer (such as a laser or missile), but rather the entity that caused the damage
/// (such as the ship that fired the laser).
pub causer: Option<Entity>,
}

pub(super) fn register(app: &mut App) {
Expand Down
3 changes: 2 additions & 1 deletion cosmos_core/src/structure/chunk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,9 @@ impl BlockStorer for Chunk {
fn set_block_at(&mut self, coords: ChunkBlockCoordinate, b: &Block, block_rotation: BlockRotation) {
let new_id = b.id();
let old_id = self.block_at(coords);
let old_rot = self.block_rotation(coords);

if new_id == old_id {
if new_id == old_id && block_rotation == old_rot {
return;
}

Expand Down
Loading

0 comments on commit 7836e20

Please sign in to comment.