Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
# Objective - Potion effects aren't supported by valence yet. - You can send a packet to tell the client about a potion effect, but the server still has no idea what they are <details> <summary>Example code</summary> ```rs pub fn add_potion_effect(mut clients: Query<&mut Client>, mut events: EventReader<SneakEvent>) { for event in events.iter() { if event.state == SneakState::Start { if let Ok(mut client) = clients.get_mut(event.client) { client.write_packet(&EntityStatusEffectS2c { entity_id: VarInt(0), effect_id: VarInt(22), amplifier: 0, duration: VarInt(600), flags: entity_status_effect_s2c::Flags::new() .with_show_particles(true) .with_show_icon(true), factor_codec: None, }); } } } } ``` </details> - Closes #401 - Also, when the potion effect expires, we need to tell the client that their potion effect is no longer. Right now, with sending a packet, the effect doesn't get removed when it goes down to 00:00. # Solution I want to add the necessary components and stuff to facilitate potion effects. > Note: I'm still somewhat new to rust and very new to bevy, so please lmk if I can improve anything or if I should do anything differently. Thanks! # To do: - [x] Extractor - [x] `ActiveStatusEffects` component to handle the actual status effect applied to the mc entity - [x] Add `ActiveStatusEffects` component to all entities. - [x] Make a plugin to handle potion effects - [x] Decrease tick count - [x] Remove effect (& tell client) when tick count is 0 - [x] Make the effects do stuff - [x] Particles - [x] Tell client - [x] Add tests - [x] Add example - [x] Add examples on how to implement potion effects (speed, instant health, etc.) - [x] Extract stuff to make it easier to implement potions. See #593 # Playground <details> <summary>Current playground</summary> ```rs use valence::client::despawn_disconnected_clients; use valence::entity::active_status_effects::{ActiveStatusEffect, ActiveStatusEffects}; use valence::entity::status_effects::StatusEffect; use valence::log::LogPlugin; use valence::network::ConnectionMode; use valence::prelude::*; #[allow(unused_imports)] use crate::extras::*; const SPAWN_Y: i32 = 64; pub fn build_app(app: &mut App) { app.insert_resource(NetworkSettings { connection_mode: ConnectionMode::Offline, ..Default::default() }) .add_plugins(DefaultPlugins.build().disable::<LogPlugin>()) .add_systems(Startup, setup) .add_systems(EventLoopUpdate, add_potion_effect) .add_systems(Update, (init_clients, despawn_disconnected_clients)) .run(); } fn setup( mut commands: Commands, server: Res<Server>, biomes: Res<BiomeRegistry>, dimensions: Res<DimensionTypeRegistry>, ) { let mut layer = LayerBundle::new(ident!("overworld"), &dimensions, &biomes, &server); for z in -5..5 { for x in -5..5 { layer.chunk.insert_chunk([x, z], UnloadedChunk::new()); } } for z in -25..25 { for x in -25..25 { layer .chunk .set_block([x, SPAWN_Y, z], BlockState::GRASS_BLOCK); } } commands.spawn(layer); } fn init_clients( mut clients: Query< ( &mut EntityLayerId, &mut VisibleChunkLayer, &mut VisibleEntityLayers, &mut Position, &mut GameMode, ), Added<Client>, >, layers: Query<Entity, (With<ChunkLayer>, With<EntityLayer>)>, ) { for ( mut layer_id, mut visible_chunk_layer, mut visible_entity_layers, mut pos, mut game_mode, ) in &mut clients { let layer = layers.single(); layer_id.0 = layer; visible_chunk_layer.0 = layer; visible_entity_layers.0.insert(layer); pos.set([0.0, SPAWN_Y as f64 + 1.0, 0.0]); *game_mode = GameMode::Survival; } } pub fn add_potion_effect( mut clients: Query<&mut ActiveStatusEffects>, mut events: EventReader<SneakEvent>, ) { for event in events.iter() { if event.state == SneakState::Start { if let Ok(mut status) = clients.get_mut(event.client) { status.add( ActiveStatusEffect::from_effect(StatusEffect::Wither) .with_amplifier(2) .with_duration(200), ); } } } } ``` </details> --------- Co-authored-by: Carson McManus <[email protected]>
- Loading branch information