Skip to content

Commit

Permalink
Absorption (#563)
Browse files Browse the repository at this point in the history
# Problem

See #557

Will be necessary to implement #556 and #558

# Objective

Implement absorption for ALL living entities.

# Solution

Make a special case for LivingEntity for Absorption since it's
untracked.

# Playground

<details>
<summary>Playground</summary>

```rs
use valence::client::despawn_disconnected_clients;
use valence::entity::living::Absorption;
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, toggle_absorption_on_sneak)
    .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 toggle_absorption_on_sneak(
    mut clients: Query<&mut Absorption>,
    mut events: EventReader<SneakEvent>,
) {
    for event in events.iter() {
        if event.state == SneakState::Start {
            if let Ok(mut absorption) = clients.get_mut(event.client) {
                absorption.0 = if absorption.0 == 0.0 { 4.0 } else { 0.0 };
            }
        }
    }
}
```
</details>

---------

Co-authored-by: Carson McManus <[email protected]>
  • Loading branch information
SelfMadeSystem and dyc3 authored Oct 13, 2023
1 parent dd8bded commit 498f7a5
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions crates/valence_entity/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,16 @@ fn build() -> anyhow::Result<TokenStream> {
bundle_init_fields.extend([quote! {
#snake_entity_name_ident: Default::default(),
}]);

if entity_name == "LivingEntity" {
bundle_fields.extend([quote! {
pub living_absorption: super::living::Absorption,
}]);

bundle_init_fields.extend([quote! {
living_absorption: Default::default(),
}]);
}
}
MarkerOrField::Field { entity_name, field } => {
let snake_field_name = field.name.to_snake_case();
Expand Down Expand Up @@ -498,6 +508,14 @@ fn build() -> anyhow::Result<TokenStream> {
pub struct #entity_name_ident;
}]);

if entity_name == "LivingEntity" {
module_body.extend([quote! {
#[doc = "Special untracked component for `LivingEntity` entities."]
#[derive(bevy_ecs::component::Component, Copy, Clone, Default, Debug)]
pub struct Absorption(pub f32);
}]);
}

modules.extend([quote! {
#[allow(clippy::module_inception)]
pub mod #stripped_snake_entity_name_ident {
Expand All @@ -506,6 +524,20 @@ fn build() -> anyhow::Result<TokenStream> {
}]);
}

systems.extend([quote! {
/// Special case for `living::Absorption`.
/// Updates the `AbsorptionAmount` component of the player entity.
fn update_living_and_player_absorption(
mut query: Query<(&living::Absorption, &mut player::AbsorptionAmount), Changed<living::Absorption>>
) {
for (living_absorption, mut player_absorption) in query.iter_mut() {
player_absorption.0 = living_absorption.0;
}
}
}]);

system_names.push(quote!(update_living_and_player_absorption));

#[derive(Deserialize, Debug)]
struct MiscEntityData {
entity_status: BTreeMap<String, u8>,
Expand Down

0 comments on commit 498f7a5

Please sign in to comment.