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

Fix DisconnectClient disconnecting clients before kicking them with message #548

Merged
merged 2 commits into from
Oct 8, 2023
Merged

Fix DisconnectClient disconnecting clients before kicking them with message #548

merged 2 commits into from
Oct 8, 2023

Conversation

SelfMadeSystem
Copy link
Contributor

@SelfMadeSystem SelfMadeSystem commented Oct 8, 2023

Objective

There was a bug in the implementation of DisconnectClient where the client would be disconnected before receiving the kick message.

Solution

Replace entity.remove::<Client>(); with entity.insert(Despawned);. This way, the client will be removed at the end of the tick to give time for the packets to be sent.

Note: Removing that line altogether also works with a vanilla client, however, it is trivial for a custom client to ignore the packet, and thus having an "anti-kick" exploit.

Playground

use valence::client::{despawn_disconnected_clients, DisconnectClient};
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, kick_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::Creative;
    }
}

pub fn kick_on_sneak(
    mut commands: Commands,
    mut events: EventReader<SneakEvent>,
) {
    for event in events.iter() {
        if event.state == SneakState::Start {
            commands.add(DisconnectClient {
                client: event.client,
                reason: "You sneaked!".into(),
            });
        }
    }
}

@dyc3 dyc3 merged commit 4c77a5b into valence-rs:main Oct 8, 2023
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants