From 30a38bc4ffe5d95dfa97578d8e368897da9e488b Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 26 Mar 2026 10:03:41 -0500 Subject: [PATCH] feat: constant cooling and heating from thrusters --- crates/unified/Cargo.toml | 2 +- .../assets/config/parts/hearty.part.toml | 12 +++++++++ .../assets/config/parts/housing.part.toml | 2 ++ crates/unified/src/client/parts.rs | 27 ++++++++++++++----- crates/unified/src/config/part.rs | 9 +++++++ crates/unified/src/ecs.rs | 11 ++++++++ crates/unified/src/ecs/thruster.rs | 6 +++-- crates/unified/src/server/heat/cooling.rs | 16 +++++++++++ crates/unified/src/server/heat/mod.rs | 1 + crates/unified/src/server/mod.rs | 3 +++ crates/unified/src/server/part.rs | 17 ++++++++++-- crates/unified/src/server/player/thrust.rs | 13 +++++---- crates/unified/src/shared_plugins.rs | 3 ++- 13 files changed, 104 insertions(+), 18 deletions(-) create mode 100644 crates/unified/src/server/heat/cooling.rs create mode 100644 crates/unified/src/server/heat/mod.rs diff --git a/crates/unified/Cargo.toml b/crates/unified/Cargo.toml index 1334e30b8541886649a205c7e3a9651d334d6e9c..a1f41a682df6456777154409bbf7fe27434a831f 100644 --- a/crates/unified/Cargo.toml +++ b/crates/unified/Cargo.toml @@ -104,4 +104,4 @@ server = ["aeronet_websocket/server", "aeronet_replicon/server"] client = [ "dep:leafwing-input-manager", "dep:good_lp" -] \ No newline at end of file +] diff --git a/crates/unified/assets/config/parts/hearty.part.toml b/crates/unified/assets/config/parts/hearty.part.toml index 960b49d2c423e2af339b6fa6f2ba6343128c770e..51c34700c03110a3ce9032c1708b7f7bf119c761 100644 --- a/crates/unified/assets/config/parts/hearty.part.toml +++ b/crates/unified/assets/config/parts/hearty.part.toml @@ -12,21 +12,29 @@ mass = 100 id = "bottom left" apply_force_at_local = [ -25.0, -25.0 ] thrust_vector = [ 0.0, 2500.0 ] +exhaust_temperature = 1000.0 +heat_constant = 0.1 [[thruster]] id = "bottom right" apply_force_at_local = [ 25.0, -25.0 ] thrust_vector = [ 0.0, 2500.0 ] +exhaust_temperature = 1000.0 +heat_constant = 0.1 [[thruster]] id = "top left" apply_force_at_local = [ -25.0, 25.0 ] thrust_vector = [ 0.0, -2500.0 ] +exhaust_temperature = 1000.0 +heat_constant = 0.1 [[thruster]] id = "top right" apply_force_at_local = [ 25.0, 25.0 ] thrust_vector = [ 0.0, -2500.0 ] +exhaust_temperature = 1000.0 +heat_constant = 0.1 [[joint]] id = "Top" @@ -49,5 +57,9 @@ id = "Left" target = { translation = [ -55.0, 0.0, 0.0 ], rotation = -270.0 } snap = { translation = [ -25.0, 0.0, 0.0 ], rotation = 0.0 } +[cooling] +cool_temperature = 273.0 +heat_cooling_constant = 1.0 + [crafting] can_craft = true diff --git a/crates/unified/assets/config/parts/housing.part.toml b/crates/unified/assets/config/parts/housing.part.toml index 2b2ad7c8ead3c15f0f0962d1bbabbde3fb099a58..20961b2b084d5d22de62577044168713a701d510 100644 --- a/crates/unified/assets/config/parts/housing.part.toml +++ b/crates/unified/assets/config/parts/housing.part.toml @@ -12,6 +12,8 @@ mass = 50 id = "main" apply_force_at_local = [ 0, 0 ] thrust_vector = [ 0.0, -20000.0 ] +exhaust_temperature = 1000.0 +heat_constant = 0.1 [[joint]] id = "Top" diff --git a/crates/unified/src/client/parts.rs b/crates/unified/src/client/parts.rs index 7733291833f6b6583c90a8a8c7c29fd2970f9767..350f6b721930d3030735590f97c44ae6dc1e5885 100644 --- a/crates/unified/src/client/parts.rs +++ b/crates/unified/src/client/parts.rs @@ -2,11 +2,12 @@ use std::f32::consts::PI; use crate::attachment::{Joint, JointOf, Joints, PartInShip, Peer, SnapOf, SnapOfJoint}; use crate::client::crafting::ui::open_crafting_ui; -use crate::ecs::Me; +use crate::ecs::{Me, Temperature}; use crate::client::colors::GREEN; use crate::ecs::{DragRequestEvent, Part, MAIN_LAYER}; use crate::client::input::CursorWorldCoordinates; use bevy::color::palettes::css::{ORANGE, PURPLE, RED, YELLOW}; +use bevy::ui::update; use crate::client::ship::attachment::AttachmentDebugRes; use crate::prelude::*; @@ -20,6 +21,7 @@ pub fn parts_plugin(app: &mut App) { handle_incoming_parts, handle_updated_parts, update_part_sprites, + handle_updated_temperature, ), ); app.add_observer(on_part_release); @@ -27,15 +29,16 @@ pub fn parts_plugin(app: &mut App) { fn handle_incoming_parts( mut commands: Commands, - new_parts: Query<(Entity, &Part, Option<&PartInShip>), Added>, + new_parts: Query<(Entity, &Part, &Temperature, Option<&PartInShip>), Added>, asset_server: Res, ) { - for (new_entity, new_part, is_connected) in new_parts.iter() { + for (new_entity, new_part, temperature, is_connected) in new_parts.iter() { let mut sprite = Sprite::from_image(asset_server.load(if is_connected.is_some() { &new_part.strong_config.part.sprite_connected } else { &new_part.strong_config.part.sprite_disconnected })); + sprite.color = Color::srgb(1.0 + ((temperature.0 - 300.0) / 700.0).max(0.0), 1.0, 1.0); sprite.custom_size = Some(Vec2::new( new_part.strong_config.physics.width, new_part.strong_config.physics.height, @@ -50,12 +53,19 @@ fn handle_incoming_parts( .observe(open_crafting_ui); } } +fn handle_updated_temperature( + mut updated_parts: Query<(&mut Sprite, &Temperature), (With, Changed)> +) { + for (mut sprite, temperature) in updated_parts.iter_mut() { + sprite.color = Color::srgb(1.0 + ((temperature.0 - 300.0) / 700.0).max(0.0), 1.0, 1.0); + } +} fn handle_updated_parts( mut commands: Commands, - updated_parts: Query<(Entity, &Part, Option<&PartInShip>), Changed>, + updated_parts: Query<(Entity, &Part, &Temperature, Option<&PartInShip>), Changed>, asset_server: Res, ) { - for (updated_entity, updated_part, is_connected) in updated_parts.iter() { + for (updated_entity, updated_part, temperature, is_connected) in updated_parts.iter() { let mut sprite = Sprite::from_image(asset_server.load(if is_connected.is_some() { &updated_part.strong_config.part.sprite_connected } else { @@ -65,6 +75,7 @@ fn handle_updated_parts( updated_part.strong_config.physics.width, updated_part.strong_config.physics.height, )); + sprite.color = Color::srgb(1.0 + ((temperature.0 - 300.0) / 700.0).max(0.0), 1.0, 1.0); commands .entity(updated_entity) @@ -76,12 +87,12 @@ fn handle_updated_parts( fn update_part_sprites( added: Query>, mut removed: RemovedComponents, - parts: Query<(&Part, Option<&PartInShip>)>, + parts: Query<(&Part, &Temperature, Option<&PartInShip>)>, asset_server: Res, mut commands: Commands, ) { for e in added.into_iter().chain(removed.read()) { - let Ok((part, connected_to)) = parts.get(e) else { + let Ok((part, temperature, connected_to)) = parts.get(e) else { continue; }; @@ -96,6 +107,8 @@ fn update_part_sprites( part.strong_config.physics.width, part.strong_config.physics.height, )); + sprite.color = Color::srgb(1.0 + ((temperature.0 - 300.0) / 700.0).max(0.0), 1.0, 1.0); + //sprite.color = Color::srgb(1.0, (700.0 - temperature.0) / 700.0, (700.0 - temperature.0) / 700.0); commands.entity(e).insert(sprite); } diff --git a/crates/unified/src/config/part.rs b/crates/unified/src/config/part.rs index da3181ece5fc8fd43c8f318489fa2e5a5b52ed74..cdd3bdc784721f52ee540fe6e6e75a0419f0598f 100644 --- a/crates/unified/src/config/part.rs +++ b/crates/unified/src/config/part.rs @@ -13,6 +13,7 @@ pub struct PartConfig { #[serde(default)] #[serde(rename = "joint")] pub joints: Vec, + pub cooling: Option, pub crafting: Option, } #[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)] @@ -39,6 +40,9 @@ pub struct ThrusterConfig { #[serde(default)] pub apply_force_at_local: Vec2, pub thrust_vector: Vec2, + + pub exhaust_temperature: f32, + pub heat_constant: f32, } #[derive(Deserialize, Serialize, Clone, Debug, TypePath, PartialEq, Copy)] pub struct JointOffset { @@ -55,6 +59,11 @@ impl From for Transform { } } #[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)] +pub struct CoolingConfig { + pub cool_temperature: f32, + pub heat_cooling_constant: f32, +} +#[derive(Deserialize, TypePath, Serialize, Clone, Debug, PartialEq)] pub struct CraftingConfig { pub can_craft: bool, } diff --git a/crates/unified/src/ecs.rs b/crates/unified/src/ecs.rs index 490d075b42621860d4025cabf08c770d1c854b16..fa1aa69f9a3c900a1d9e0d1378d1048788b0500e 100644 --- a/crates/unified/src/ecs.rs +++ b/crates/unified/src/ecs.rs @@ -113,3 +113,14 @@ pub struct Hi { pub struct CanCraft; #[derive(Component, Serialize, Deserialize, Debug)] pub struct CraftingUi; + +#[derive(Component, Serialize, Deserialize, Debug)] +#[require(Replicated)] +pub struct Temperature(pub f32); +#[derive(Component, Serialize, Deserialize, Debug)] +pub struct TemperatureSprite; +#[derive(Component, Serialize, Deserialize, Debug)] +pub struct Cooler { + pub cool_temperature: f32, + pub heat_cooling_constant: f32, +} diff --git a/crates/unified/src/ecs/thruster.rs b/crates/unified/src/ecs/thruster.rs index 8d6a7a33024149d57fa0588b6a0d0b23325c4ea4..47c8876b17153b510ec5712968d5408eaf2c58e5 100644 --- a/crates/unified/src/ecs/thruster.rs +++ b/crates/unified/src/ecs/thruster.rs @@ -34,7 +34,9 @@ pub struct ThrusterOfPart(#[entities] pub Entity); #[require(Replicated)] pub struct Thruster { pub id: ThrusterId, - pub thrust_vector: Vec2 + pub thrust_vector: Vec2, + pub exhaust_temperature: f32, + pub heat_constant: f32, } #[derive(Bundle)] @@ -43,4 +45,4 @@ pub struct ThrusterBundle { pub transform: Transform, pub child_of: ChildOf, pub thruster_of_part: ThrusterOfPart, -} \ No newline at end of file +} diff --git a/crates/unified/src/server/heat/cooling.rs b/crates/unified/src/server/heat/cooling.rs new file mode 100644 index 0000000000000000000000000000000000000000..a4d80356540f51937cefd4d0f15c788a7f411940 --- /dev/null +++ b/crates/unified/src/server/heat/cooling.rs @@ -0,0 +1,16 @@ +use crate::prelude::*; +use crate::ecs::{Cooler, Temperature}; + +pub fn heat_cooling_plugin(app: &mut App) { + app.add_systems(Update, cool_part); +} + +fn cool_part( + time: Res