From b0c2cf12aa5f3f4a96c92804a90a753240f142f0 Mon Sep 17 00:00:00 2001 From: Anthony Tornetta Date: Thu, 26 Oct 2023 01:38:49 -0400 Subject: [PATCH] Symmetry functionally done --- cosmos_client/src/events/ship/create_ship.rs | 19 +- cosmos_client/src/input/inputs.rs | 4 + .../src/interactions/block_interactions.rs | 4 +- .../src/structure/ship/build_mode.rs | 12 +- .../src/netty/client_reliable_messages.rs | 3 + .../src/netty/server_reliable_messages.rs | 4 + cosmos_core/src/structure/ship/build_mode.rs | 7 + .../src/events/blocks/block_events.rs | 215 ++++++++++-------- cosmos_server/src/universe/planet_spawner.rs | 2 +- 9 files changed, 171 insertions(+), 99 deletions(-) diff --git a/cosmos_client/src/events/ship/create_ship.rs b/cosmos_client/src/events/ship/create_ship.rs index 6abf14965..baed6e065 100644 --- a/cosmos_client/src/events/ship/create_ship.rs +++ b/cosmos_client/src/events/ship/create_ship.rs @@ -1,11 +1,15 @@ //! Event & its processing for when a player wants to create a ship -use bevy::prelude::{in_state, App, Event, EventReader, EventWriter, IntoSystemConfigs, ResMut, Update}; +use bevy::prelude::{in_state, App, Event, EventReader, EventWriter, IntoSystemConfigs, Query, ResMut, Update, With}; use bevy_renet::renet::RenetClient; -use cosmos_core::netty::{client_reliable_messages::ClientReliableMessages, cosmos_encoder, NettyChannelClient}; +use cosmos_core::{ + netty::{client_reliable_messages::ClientReliableMessages, cosmos_encoder, NettyChannelClient}, + structure::ship::build_mode::BuildMode, +}; use crate::{ input::inputs::{CosmosInputs, InputChecker, InputHandler}, + netty::flags::LocalPlayer, state::game_state::GameState, }; @@ -15,7 +19,16 @@ pub struct CreateShipEvent { name: String, } -fn listener(input_handler: InputChecker, mut event_writer: EventWriter) { +fn listener( + in_build_mode: Query<(), (With, With)>, + input_handler: InputChecker, + mut event_writer: EventWriter, +) { + if in_build_mode.get_single().is_ok() { + // Don't create ships while in build mode + return; + } + if input_handler.check_just_pressed(CosmosInputs::CreateShip) { event_writer.send(CreateShipEvent { name: "Cool name".into() }); } diff --git a/cosmos_client/src/input/inputs.rs b/cosmos_client/src/input/inputs.rs index 32a8ac06b..5c319fbaf 100644 --- a/cosmos_client/src/input/inputs.rs +++ b/cosmos_client/src/input/inputs.rs @@ -103,9 +103,13 @@ pub enum CosmosInputs { /// Toggles the player between being in build mode and not on a ship ToggleBuildMode, + /// A toggle to clear the symmetry - when combined with a symmetry key the symmetry will be cleared ClearSymmetry, + /// Creates an X symmetry SymmetryX, + /// Creates a Y symmetry SymmetryY, + /// Creates a Z symmetry SymmetryZ, } diff --git a/cosmos_client/src/interactions/block_interactions.rs b/cosmos_client/src/interactions/block_interactions.rs index 6079a527d..d7e534057 100644 --- a/cosmos_client/src/interactions/block_interactions.rs +++ b/cosmos_client/src/interactions/block_interactions.rs @@ -28,8 +28,10 @@ pub enum InteractionType { Primary, } -#[derive(Component)] +#[derive(Component, Debug)] +/// Stores the block the player is last noted as looked at pub struct LookingAt { + /// The block the player is looking at pub looking_at_block: Option<(Entity, StructureBlock)>, } diff --git a/cosmos_client/src/structure/ship/build_mode.rs b/cosmos_client/src/structure/ship/build_mode.rs index 21318c579..0a96a1fc6 100644 --- a/cosmos_client/src/structure/ship/build_mode.rs +++ b/cosmos_client/src/structure/ship/build_mode.rs @@ -105,14 +105,22 @@ fn control_build_mode( } } -fn place_symmetries(mut client: ResMut, input_handler: InputChecker, query: Query<&LookingAt, With>) { +fn place_symmetries( + mut client: ResMut, + input_handler: InputChecker, + query: Query<&LookingAt, (With, With)>, +) { let Ok(looking_at) = query.get_single() else { return; }; let clearing = input_handler.check_pressed(CosmosInputs::ClearSymmetry); - let looking_at_block = &looking_at.looking_at_block.map(|x| x.1); + let looking_at_block = if !clearing { + looking_at.looking_at_block.map(|x| x.1) + } else { + None + }; if !clearing && looking_at_block.is_none() { return; diff --git a/cosmos_core/src/netty/client_reliable_messages.rs b/cosmos_core/src/netty/client_reliable_messages.rs index 05e43b190..0474c054e 100644 --- a/cosmos_core/src/netty/client_reliable_messages.rs +++ b/cosmos_core/src/netty/client_reliable_messages.rs @@ -97,8 +97,11 @@ pub enum ClientReliableMessages { /// /// Requires server confirmation via [`ServerReliableMessages::PlayerExitBuildMode`] or client will do nothing ExitBuildMode, + /// Sent by the player to update their symmetry SetSymmetry { + /// The axis they are changing axis: BuildAxis, + /// None if they want to remove it, otherwise the respective axis's coordinate coordinate: Option, }, } diff --git a/cosmos_core/src/netty/server_reliable_messages.rs b/cosmos_core/src/netty/server_reliable_messages.rs index 7c3b4ece8..c73447c74 100644 --- a/cosmos_core/src/netty/server_reliable_messages.rs +++ b/cosmos_core/src/netty/server_reliable_messages.rs @@ -155,7 +155,11 @@ pub enum ServerReliableMessages { /// The server's player entity that's exiting player_entity: Entity, }, + /// Updates the player's build mode. + /// + /// Only used to update symmetry axis. UpdateBuildMode { + /// The new build mode build_mode: BuildMode, }, } diff --git a/cosmos_core/src/structure/ship/build_mode.rs b/cosmos_core/src/structure/ship/build_mode.rs index 0fe31a33e..fa0bcc775 100644 --- a/cosmos_core/src/structure/ship/build_mode.rs +++ b/cosmos_core/src/structure/ship/build_mode.rs @@ -22,9 +22,13 @@ pub struct BuildMode { } #[derive(Debug, Clone, Copy, Serialize, Deserialize)] +/// Represents the X/Y/Z symmetry axis pub enum BuildAxis { + /// X axis X, + /// Y axis Y, + /// Z axis Z, } @@ -37,14 +41,17 @@ impl BuildMode { } } + /// Sets the symmetry for this axis pub fn set_symmetry(&mut self, axis: BuildAxis, coordinate: CoordinateType) { self.internal_set_symmetry(axis, Some(coordinate)); } + /// Removes the symmetry from this axis pub fn remove_symmetry(&mut self, axis: BuildAxis) { self.internal_set_symmetry(axis, None); } + /// Gets the symmetry for this axis - `None` if there is no symmetry present. pub fn get_symmetry(&self, axis: BuildAxis) -> Option { match axis { BuildAxis::X => self.symmetries.0, diff --git a/cosmos_server/src/events/blocks/block_events.rs b/cosmos_server/src/events/blocks/block_events.rs index fb8a18aad..8ddb4c2f8 100644 --- a/cosmos_server/src/events/blocks/block_events.rs +++ b/cosmos_server/src/events/blocks/block_events.rs @@ -69,39 +69,50 @@ fn handle_block_break_events( blocks: Res>, items: Res>, block_items: Res, // TODO: Replace this with drop table - mut inventory_query: Query<&mut Inventory>, + mut player_query: Query<(&mut Inventory, Option<&BuildMode>, Option<&Parent>)>, mut event_writer: EventWriter, ) { for ev in event_reader.iter() { - if let Ok(mut structure) = query.get_mut(ev.structure_entity) { - let block = ev.structure_block.block(&structure, &blocks); - - // Eventually seperate this into another event lsitener that some how interacts with this one - // Idk if bevy supports this yet without some hacky stuff? - if block.unlocalized_name() == "cosmos:ship_core" { - let mut itr = structure.all_blocks_iter(false); - - // ship core some other block - if itr.next().is_some() && itr.next().is_some() { - // Do not allow player to mine ship core if another block exists on the ship - return; + if let Ok((mut inventory, build_mode, parent)) = player_query.get_mut(ev.breaker) { + if let Ok(mut structure) = query.get_mut(ev.structure_entity) { + let mut structure_blocks = vec![(ev.structure_block.coords(), BlockFace::Top)]; + + if let (Some(build_mode), Some(parent)) = (build_mode, parent) { + structure_blocks = calculate_build_mode_blocks( + structure_blocks, + build_mode, + parent, + ev.structure_entity, + &mut inventory, + &structure, + ); } - } - let block_id = ev.structure_block.block_id(&structure); + for (coord, _) in structure_blocks { + let block = structure.block_at(coord, &blocks); + + // Eventually seperate this into another event lsitener that some how interacts with this one + // Idk if bevy supports this yet without some hacky stuff? + if block.unlocalized_name() == "cosmos:ship_core" { + let mut itr = structure.all_blocks_iter(false); - if block_id != AIR_BLOCK_ID { - if let Ok(mut inventory) = inventory_query.get_mut(ev.breaker) { - let block = blocks.from_numeric_id(block_id); + // ship core some other block + if itr.next().is_some() && itr.next().is_some() { + // Do not allow player to mine ship core if another block exists on the ship + return; + } + } - if let Some(item_id) = block_items.item_from_block(block) { - let item = items.from_numeric_id(item_id); + if block.id() != AIR_BLOCK_ID { + if let Some(item_id) = block_items.item_from_block(block) { + let item = items.from_numeric_id(item_id); - inventory.insert(item, 1); + inventory.insert(item, 1); + } + + structure.remove_block_at(coord, &blocks, Some(&mut event_writer)); } } - - structure.remove_block_at(ev.structure_block.coords(), &blocks, Some(&mut event_writer)); } } } @@ -109,14 +120,94 @@ fn handle_block_break_events( /// Ensure we're not double-placing any blocks, which could happen if you place on the symmetry line fn unique_push(vec: &mut Vec<(BlockCoordinate, BlockFace)>, item: (BlockCoordinate, BlockFace)) { - for item in vec.iter() { - if item.0 == item.0 { + for already_there in vec.iter() { + if already_there.0 == item.0 { return; } } + vec.push(item); } +fn calculate_build_mode_blocks<'a>( + mut structure_blocks: Vec<(BlockCoordinate, BlockFace)>, + build_mode: &BuildMode, + parent: &Parent, + structure_entity: Entity, + inventory: &mut Mut<'a, Inventory>, + structure: &Structure, +) -> Vec<(BlockCoordinate, BlockFace)> { + if parent.get() != structure_entity { + // Tried to place a block on a structure they're not in build mode on + + // Update player that they didn't place the block + inventory.set_changed(); + return vec![]; + } + + if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::X) { + let axis_coord = axis_coord as UnboundCoordinateType; + + let mut new_coords = vec![]; + + for (old_coords, block_up) in structure_blocks { + unique_push(&mut new_coords, (old_coords, block_up)); + + let new_x_coord = 2 * (axis_coord - old_coords.x as UnboundCoordinateType) + old_coords.x as UnboundCoordinateType; + if new_x_coord >= 0 { + let new_block_coords = BlockCoordinate::new(new_x_coord as CoordinateType, old_coords.y, old_coords.z); + if structure.is_within_blocks(new_block_coords) { + unique_push(&mut new_coords, (new_block_coords, block_up)); + } + } + } + + structure_blocks = new_coords; + } + + if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::Y) { + let axis_coord = axis_coord as UnboundCoordinateType; + + let mut new_coords = vec![]; + + for (old_coords, block_up) in structure_blocks { + unique_push(&mut new_coords, (old_coords, block_up)); + + let new_y_coord = 2 * (axis_coord - old_coords.y as UnboundCoordinateType) + old_coords.y as UnboundCoordinateType; + if new_y_coord >= 0 { + let new_block_coords = BlockCoordinate::new(old_coords.x, new_y_coord as CoordinateType, old_coords.z); + if structure.is_within_blocks(new_block_coords) { + unique_push(&mut new_coords, (new_block_coords, block_up)); + } + } + } + + structure_blocks = new_coords; + } + + if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::Z) { + let axis_coord = axis_coord as UnboundCoordinateType; + + let mut new_coords = vec![]; + + for (old_coords, block_up) in structure_blocks { + unique_push(&mut new_coords, (old_coords, block_up)); + + let new_z_coord = 2 * (axis_coord - old_coords.z as UnboundCoordinateType) + old_coords.z as UnboundCoordinateType; + if new_z_coord >= 0 { + let new_block_coords = BlockCoordinate::new(old_coords.x, old_coords.y, new_z_coord as CoordinateType); + if structure.is_within_blocks(new_block_coords) { + unique_push(&mut new_coords, (new_block_coords, block_up)); + } + } + } + + structure_blocks = new_coords; + } + + structure_blocks +} + fn handle_block_place_events( mut query: Query<&mut Structure>, mut event_reader: EventReader, @@ -137,76 +228,16 @@ fn handle_block_place_events( let mut structure_blocks = vec![(ev.structure_block.coords(), ev.block_up)]; if let (Some(build_mode), Some(parent)) = (build_mode, parent) { - if parent.get() != ev.structure_entity { - // Tried to place a block on a structure they're not in build mode on - - // Update player that they didn't place the block - inv.set_changed(); - continue; - } - - if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::X) { - let axis_coord = axis_coord as UnboundCoordinateType; - - let mut new_coords = vec![]; - - for (old_coords, block_up) in structure_blocks { - let new_x_coord = 2 * (axis_coord - old_coords.x as UnboundCoordinateType) + old_coords.x as UnboundCoordinateType; - if new_x_coord >= 0 { - let new_block_coords = BlockCoordinate::new(new_x_coord as CoordinateType, old_coords.y, old_coords.z); - if structure.is_within_blocks(new_block_coords) { - unique_push(&mut new_coords, (new_block_coords, block_up)); - } - } - - unique_push(&mut new_coords, (old_coords, block_up)); - } - - structure_blocks = new_coords; - } - - if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::Y) { - let axis_coord = axis_coord as UnboundCoordinateType; - - let mut new_coords = vec![]; - - for (old_coords, block_up) in structure_blocks { - let new_y_coord = 2 * (axis_coord - old_coords.y as UnboundCoordinateType) + old_coords.y as UnboundCoordinateType; - if new_y_coord >= 0 { - let new_block_coords = BlockCoordinate::new(old_coords.x, new_y_coord as CoordinateType, old_coords.z); - if structure.is_within_blocks(new_block_coords) { - unique_push(&mut new_coords, (new_block_coords, block_up)); - } - } - - unique_push(&mut new_coords, (old_coords, block_up)); - } - - structure_blocks = new_coords; - } - - if let Some(axis_coord) = build_mode.get_symmetry(BuildAxis::Z) { - let axis_coord = axis_coord as UnboundCoordinateType; - - let mut new_coords = vec![]; - - for (old_coords, block_up) in structure_blocks { - let new_z_coord = 2 * (axis_coord - old_coords.z as UnboundCoordinateType) + old_coords.z as UnboundCoordinateType; - if new_z_coord >= 0 { - let new_block_coords = BlockCoordinate::new(old_coords.x, old_coords.y, new_z_coord as CoordinateType); - if structure.is_within_blocks(new_block_coords) { - unique_push(&mut new_coords, (new_block_coords, block_up)); - } - } + structure_blocks = calculate_build_mode_blocks(structure_blocks, build_mode, parent, ev.structure_entity, &mut inv, &structure); + } - unique_push(&mut new_coords, (old_coords, block_up)); - } + println!("{structure_blocks:?}"); - structure_blocks = new_coords; + for (coords, block_up) in structure_blocks { + if structure.has_block_at(coords) { + continue; } - } - for (structure_block, block_up) in structure_blocks { let Some(is) = inv.itemstack_at(ev.inventory_slot) else { break; }; @@ -225,7 +256,7 @@ fn handle_block_place_events( let block = blocks.from_numeric_id(block_id); if inv.decrease_quantity_at(ev.inventory_slot, 1) == 0 { - structure.set_block_at(structure_block, block, block_up, &blocks, Some(&mut event_writer)); + structure.set_block_at(coords, block, block_up, &blocks, Some(&mut event_writer)); } else { break; } diff --git a/cosmos_server/src/universe/planet_spawner.rs b/cosmos_server/src/universe/planet_spawner.rs index 37f47f59f..fadbcac0d 100644 --- a/cosmos_server/src/universe/planet_spawner.rs +++ b/cosmos_server/src/universe/planet_spawner.rs @@ -133,7 +133,7 @@ fn spawn_planet( let is_origin = sector.x() == 25 && sector.y() == 25 && sector.z() == 25; - if is_origin || rng.gen_range(0..1000) == 9 { + if !is_origin && rng.gen_range(0..1000) == 9 { let location = Location::new(Vec3::ZERO, sector); let mut closest_star = None;