Skip to content

Problems showing Chunks with mods like Sodium or Starlight enabled(Anvil Example) #481

Open
@FloGamerMC

Description

@FloGamerMC

Valence Version

e83c264

What You Did

I run and slightly modified version of the anvil_loading example. I changed the spawn not to be at 0 0, but it was not far from 0 0.

Playground
#![allow(clippy::type_complexity)]

use std::path::PathBuf;

use clap::Parser;
use valence::abilities::{FlyingSpeed, FovModifier, PlayerAbilitiesFlags};
use valence::message::SendMessage;
use valence::prelude::*;
use valence_anvil::{AnvilLevel, ChunkLoadEvent, ChunkLoadStatus};

const SPAWN_POS: DVec3 = DVec3::new(88.5, 87.5, -29.5);

#[derive(Parser, Resource)]
#[clap(author, version, about)]
struct Cli {
    /// The path to a Minecraft world save containing a `region` subdirectory.
    path: PathBuf,
}

pub fn main() {
    let cli = Cli::parse();

    if !cli.path.exists() {
        eprintln!(
            "Directory `{}` does not exist. Exiting.",
            cli.path.display()
        );
        return;
    }

    if !cli.path.is_dir() {
        eprintln!("`{}` is not a directory. Exiting.", cli.path.display());
        return;
    }

    App::new()
        .add_plugins(DefaultPlugins)
        .insert_resource(cli)
        .add_systems(Startup, setup)
        .add_systems(
            Update,
            (
                despawn_disconnected_clients,
                (init_clients, handle_chunk_loads).chain(),
                display_loaded_chunk_count,
            ),
        )
        .run();
}

fn setup(
    mut commands: Commands,
    dimensions: Res<DimensionTypeRegistry>,
    biomes: Res<BiomeRegistry>,
    server: Res<Server>,
    cli: Res<Cli>,
) {
    let layer = LayerBundle::new(ident!("overworld"), &dimensions, &biomes, &server);
    let mut level = AnvilLevel::new(&cli.path, &biomes);

    // Force a 16x16 area of chunks around the origin to be loaded at all times.
    // This is similar to "spawn chunks" in vanilla. This isn't necessary for the
    // example to function, but it's done to demonstrate that it's possible.
    for z in -8..8 {
        for x in -8..8 {
            let pos = ChunkPos::new(x, z);

            level.ignored_chunks.insert(pos);
            level.force_chunk_load(pos);
        }
    }

    commands.spawn((layer, level));
}

fn init_clients(
    mut clients: Query<
        (
            &mut EntityLayerId,
            &mut VisibleChunkLayer,
            &mut VisibleEntityLayers,
            &mut Position,
            &mut GameMode,
            &mut PlayerAbilitiesFlags,
            &mut FlyingSpeed,
            &mut FovModifier,
        ),
        Added<Client>,
    >,
    layers: Query<Entity, With<ChunkLayer>>,
) {
    for (
        mut layer_id,
        mut visible_chunk_layer,
        mut visible_entity_layers,
        mut pos,
        mut game_mode,
        mut abilities,
        mut flying_speed,
        mut fov_modifier,
    ) in &mut clients
    {
        let layer = layers.single();

        layer_id.0 = layer;
        visible_chunk_layer.0 = layer;
        visible_entity_layers.0.insert(layer);
        pos.set(SPAWN_POS);
        *game_mode = GameMode::Adventure;
        abilities.set_allow_flying(true);
        flying_speed.0 = 0.1;
        fov_modifier.0 = 0.05;
    }
}

fn handle_chunk_loads(
    mut events: EventReader<ChunkLoadEvent>,
    mut layers: Query<&mut ChunkLayer, With<AnvilLevel>>,
) {
    let mut layer = layers.single_mut();

    for event in events.iter() {
        match &event.status {
            ChunkLoadStatus::Success { .. } => {
                // The chunk was inserted into the world. Nothing for us to do.
            }
            ChunkLoadStatus::Empty => {
                // There's no chunk here so let's insert an empty chunk. If we were doing
                // terrain generation we would prepare that here.
                layer.insert_chunk(event.pos, UnloadedChunk::new());
            }
            ChunkLoadStatus::Failed(e) => {
                // Something went wrong.
                let errmsg = format!(
                    "failed to load chunk at ({}, {}): {e:#}",
                    event.pos.x, event.pos.z
                );

                eprintln!("{errmsg}");
                layer.send_chat_message(errmsg.color(Color::RED));

                layer.insert_chunk(event.pos, UnloadedChunk::new());
            }
        }
    }
}

// Display the number of loaded chunks in the action bar of all clients.
fn display_loaded_chunk_count(mut layers: Query<&mut ChunkLayer>, mut last_count: Local<usize>) {
    let mut layer = layers.single_mut();

    let cnt = layer.chunks().count();

    if *last_count != cnt {
        *last_count = cnt;
        layer.send_action_bar_message("Chunk Count: ".into_text() + cnt.color(Color::LIGHT_PURPLE));
    }
}

What Went Wrong

On clients with sodium or starlight or both installed, the chunks didn't shown up correctly and the client was long stuck at the "Loading terrain..." screen. I also tried this with different maps, so I can say for sure that this isn't a problem of this map.

I disused this problem on the discord server, a other user can reproduce this problem.

This Issue only occur on clients with sodium or starlight installed. On a vanilla client it works fine.

Additional Information

Link to the discord thread

My screenshot where you can see no chunks showing up
image

Screenshot of the other user in the discord thread
image

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriageBug has not been confirmed as real issue yet

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions