valence-rs/valence

Loading terrain takes exactly 30 seconds

EliiasG opened this issue · 2 comments

Valence Version

valence#1331a790

Overview

When changing the layer of a client to be a layer with a different dimension, the client says "loading terrain..." for what seems like exactly 30 seconds, no matter how many chunks are in the new layer.

At first i thought it might be built into the client, but i tested both in singleplayer and with a vanilla 1.20.1 server, and in both cases it loaded pretty much instantly.

My theory

I do not know much about how minecraft for valence works under the hood, but to me it seems like the 30 seconds might be a maximum time for if the server never says its done loading.

Example code (sneaking changes dimension)
use valence::prelude::*;

const SPAWN_Y: i32 = 50;

#[derive(Component)]
struct Overworld;

#[derive(Resource)]
struct Overworld(Entity);

#[derive(Resource)]
struct End(Entity);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(
            Update,
            (init_clients, despawn_disconnected_clients, change_on_sneak),
        )
        .run();
}

fn setup(
    mut commands: Commands,
    server: Res<Server>,
    dimensions: Res<DimensionTypeRegistry>,
    biomes: Res<BiomeRegistry>,
) {
    let mut overworld_layer = LayerBundle::new(ident!("overworld"), &dimensions, &biomes, &server);
    let mut end_layer = LayerBundle::new(ident!("the_end"), &dimensions, &biomes, &server);

    for z in -15..15 {
        for x in -15..15 {
            overworld_layer
                .chunk
                .insert_chunk([x, z], UnloadedChunk::new());
            end_layer.chunk.insert_chunk([x, z], UnloadedChunk::new());
        }
    }

    end_layer
        .chunk
        .set_block([0, SPAWN_Y, 0], BlockState::BEDROCK);
    overworld_layer
        .chunk
        .set_block([0, SPAWN_Y, 0], BlockState::BEDROCK);

    let overworld = commands.spawn((overworld_layer, OverworldId)).id();
    let end = commands.spawn(end_layer).id();
    commands.insert_resource(Overworld(overworld));
    commands.insert_resource(End(end));
}

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>, With<OverworldId>)>,
) {
    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;
    }
}

fn change_on_sneak(
    mut events: EventReader<SneakEvent>,
    mut clients: Query<(
        &mut EntityLayerId,
        &mut VisibleChunkLayer,
        &mut VisibleEntityLayers,
        &mut Position,
    )>,
    layers: Query<Has<OverworldId>>,
    overworld: Res<Overworld>,
    end: Res<End>,
) {
    for event in events.read() {
        if event.state != SneakState::Start {
            continue;
        }
        let (mut cur_layer, mut chunk_layer, mut entity_layers, mut pos) =
            clients.get_mut(event.client).unwrap();
        entity_layers.0.remove(&cur_layer.0);
        let new_layer = if layers.get(cur_layer.0).unwrap() {
            end.0
        } else {
            overworld.0
        };
        cur_layer.0 = new_layer;
        chunk_layer.0 = new_layer;
        entity_layers.0.insert(new_layer);
        pos.set([0.0, SPAWN_Y as f64 + 50.0, 0.0]);
    }
}

Also the flying speed (set with the FlyingSpeed component) of the Client seems to reset when changing layers, even if dimensions do not change