Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Potion Effects #401

Closed
CryptForge opened this issue Jun 26, 2023 · 0 comments · Fixed by #558
Closed

Potion Effects #401

CryptForge opened this issue Jun 26, 2023 · 0 comments · Fixed by #558
Labels
enhancement New feature or request

Comments

@CryptForge
Copy link

Describe the problem related to your feature request.

There is no way to give entities potion effects.

What solution would you like?

A way to give potion effects to an entity and track them.

What alternative(s) have you considered?

Sending the packets manually, but that didn't seem to work for whatever reason.

Additional context

The amplifier field in EntityStatusEffectS2c is of type u8 but it should be a signed byte.
Packet info

@CryptForge CryptForge added the enhancement New feature or request label Jun 26, 2023
This was referenced Oct 9, 2023
@dyc3 dyc3 closed this as completed in #558 Dec 29, 2023
dyc3 added a commit that referenced this issue Dec 29, 2023
# 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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant