azalea_client/plugins/
block_update.rs

1use azalea_block::BlockState;
2use azalea_core::position::BlockPos;
3use bevy_app::{App, Plugin, Update};
4use bevy_ecs::prelude::*;
5
6use crate::{
7    chunks::handle_receive_chunk_event, interact::BlockStatePredictionHandler,
8    local_player::InstanceHolder,
9};
10
11pub struct BlockUpdatePlugin;
12impl Plugin for BlockUpdatePlugin {
13    fn build(&self, app: &mut App) {
14        app.add_systems(
15            Update,
16            // has to be after ReceiveChunkEvent is handled so if we get chunk+blockupdate in one
17            // Update then the block update actually gets applied
18            handle_block_update_event.after(handle_receive_chunk_event),
19        );
20    }
21}
22
23/// A component that holds the list of block updates that need to be handled.
24///
25/// This is updated by `read_packets` (in `PreUpdate`) and handled/cleared by
26/// [`handle_block_update_event`] (`Update`).
27///
28/// This is a component instead of an ECS event for performance reasons.
29#[derive(Component, Debug, Clone, Default)]
30pub struct QueuedServerBlockUpdates {
31    pub list: Vec<(BlockPos, BlockState)>,
32}
33
34pub fn handle_block_update_event(
35    mut query: Query<(
36        &mut QueuedServerBlockUpdates,
37        &InstanceHolder,
38        &mut BlockStatePredictionHandler,
39    )>,
40) {
41    for (mut queued, instance_holder, mut prediction_handler) in query.iter_mut() {
42        let world = instance_holder.instance.read();
43        for (pos, block_state) in queued.list.drain(..) {
44            if !prediction_handler.update_known_server_state(pos, block_state) {
45                world.chunks.set_block_state(pos, block_state);
46            }
47        }
48    }
49}