mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-08 17:19:10 -10:00
Merge pull request #5019 from rdbtCVS/perf/preload-world-at-launch
Preload the world data of a launch that names a world
This commit is contained in:
3 files changed
+87
-7
No files matched your search
@@ -16543,6 +16543,14 @@ fn synchronous_startup(options: &Options) -> bool {
|
||||
|| std::env::var_os("HORIZON_NET_REPORT").is_some()
|
||||
}
|
||||
|
||||
/// The local world a client's launch opens at once (`--world`,
|
||||
/// `--quickPlaySingleplayer`), whose generator data can load with the game's.
|
||||
fn launch_world(options: &Options) -> Option<&str> {
|
||||
(options.execution_role.is_client() && options.server.is_none() && !options.test_terrain)
|
||||
.then_some(options.world.as_deref())
|
||||
.flatten()
|
||||
}
|
||||
|
||||
/// A step of the resource load: on its own scoped thread, or, when the
|
||||
/// settings allow a single worker, run where it is joined.
|
||||
enum Step<'scope, T> {
|
||||
@@ -16701,9 +16709,12 @@ fn gameplay_tables(
|
||||
}
|
||||
|
||||
/// The synchronous launch loads both phases; an ordinary launch returns the
|
||||
/// core bundle while the rest worker keeps loading.
|
||||
/// core bundle while the rest worker keeps loading. `launch_world`: the world
|
||||
/// the launch opens, whose data is preloaded meanwhile.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn load_resources(
|
||||
mut root: PathBuf,
|
||||
launch_world: Option<&str>,
|
||||
vanilla_root: &std::path::Path,
|
||||
settings: &Settings,
|
||||
started: Instant,
|
||||
@@ -16793,6 +16804,9 @@ fn load_resources(
|
||||
let assets = Arc::new(assets);
|
||||
let render = Arc::new(render);
|
||||
let biomes = Arc::new(biomes);
|
||||
if let Some(folder) = launch_world {
|
||||
world_loading::preload_launch_world(folder, &root, assets.registry, biomes.clone());
|
||||
}
|
||||
let tables = Arc::new(MeshTables::new(&assets, &render, &facts, visibility)?);
|
||||
let pack = PackResources::assemble(
|
||||
&root,
|
||||
@@ -17898,6 +17912,7 @@ pub fn run() -> Result<()> {
|
||||
);
|
||||
let loaded = load_resources(
|
||||
options.resources.clone(),
|
||||
launch_world(&options),
|
||||
&vanilla_root,
|
||||
&early_settings,
|
||||
started,
|
||||
|
||||
@@ -241,6 +241,7 @@ pub(super) fn spawn_loader(
|
||||
let settings = settings.clone();
|
||||
let vanilla_root = vanilla_root.to_path_buf();
|
||||
let dev_mods = options.dev_mods.clone();
|
||||
let world = launch_world(options).map(str::to_owned);
|
||||
let progress = progress.clone();
|
||||
let handle = std::thread::Builder::new()
|
||||
.name("resource-loader".into())
|
||||
@@ -254,6 +255,7 @@ pub(super) fn spawn_loader(
|
||||
let root = mods::content_root(&root, &settings.mods.enabled, &dev_mods);
|
||||
let result = load_resources(
|
||||
root,
|
||||
world.as_deref(),
|
||||
&vanilla_root,
|
||||
&settings,
|
||||
started,
|
||||
|
||||
@@ -325,6 +325,58 @@ pub(super) fn preload_world_data(
|
||||
}
|
||||
}
|
||||
|
||||
/// A launch that names a world (`--world`, `--quickPlaySingleplayer`): the
|
||||
/// same preload, started as soon as the block registry and the biomes are
|
||||
/// loaded, so it overlaps the rest of the startup instead of the world's
|
||||
/// opening. Read for the world's own data packs and preset, the bundle and
|
||||
/// decoration `make_streaming` asks for; a world they don't fit (one its
|
||||
/// upgrade rewrites) reads its own when it opens.
|
||||
pub(super) fn preload_launch_world(
|
||||
folder: &str,
|
||||
resources: &std::path::Path,
|
||||
registry: &'static horizon_world::registry::BlockRegistry,
|
||||
biomes: Arc<horizon_client::biome::Biomes>,
|
||||
) {
|
||||
let mut preload = PRELOAD.lock().unwrap_or_else(|e| e.into_inner());
|
||||
if !matches!(*preload, Preload::Idle) {
|
||||
return;
|
||||
}
|
||||
let Ok(dir) = std::env::current_dir() else {
|
||||
return;
|
||||
};
|
||||
let world_root = dir.join("saves").join(folder);
|
||||
let resources = resources.to_owned();
|
||||
let spawned = std::thread::Builder::new()
|
||||
.name("World data preload".into())
|
||||
.spawn(move || {
|
||||
// Not behind the server: the world's opening waits for it.
|
||||
let started = std::time::Instant::now();
|
||||
// Errors are left for the world opening to report.
|
||||
let (overrides, _) = worldgen_overrides_of(&world_root, &biomes);
|
||||
if let Ok(data) = horizon_client::vanillagen::shared_data_with(
|
||||
&resources.join("worldgen"),
|
||||
&overrides,
|
||||
registry,
|
||||
) {
|
||||
let preset = horizon_client::save::WorldGen::preset(&world_root);
|
||||
let _ = data.prepare_decoration(preset, "minecraft:overworld");
|
||||
}
|
||||
let _ = horizon_client::structure_blocks::loot_data(
|
||||
&resources,
|
||||
&horizon_world::loot::PackOverlay::NONE,
|
||||
);
|
||||
let _ = super::lan::sync_data(&resources, &horizon_world::loot::PackOverlay::NONE);
|
||||
log::info!(
|
||||
"Horizon: world data preloaded for the launch's world in {} ms",
|
||||
started.elapsed().as_millis()
|
||||
);
|
||||
});
|
||||
match spawned {
|
||||
Ok(thread) => *preload = Preload::Started { thread, left: None },
|
||||
Err(e) => log::warn!("Horizon: world data preload: {e}"),
|
||||
}
|
||||
}
|
||||
|
||||
/// A world opens: what `preload_world_data` read is the world's from now on.
|
||||
pub(super) fn world_data_used() {
|
||||
*PRELOAD.lock().unwrap_or_else(|e| e.into_inner()) = Preload::Used;
|
||||
@@ -360,18 +412,29 @@ fn world_worldgen_overrides(
|
||||
world_root: &std::path::Path,
|
||||
biomes: &horizon_client::biome::Biomes,
|
||||
) -> horizon_world::worldgen::overrides::WorldgenOverrides {
|
||||
let (overrides, warnings) = worldgen_overrides_of(world_root, biomes);
|
||||
for warning in warnings {
|
||||
log::warn!("Horizon: data pack worldgen: {warning}");
|
||||
}
|
||||
overrides
|
||||
}
|
||||
|
||||
/// The worldgen entries of the world's enabled data packs, and what the
|
||||
/// generator leaves out of them.
|
||||
fn worldgen_overrides_of(
|
||||
world_root: &std::path::Path,
|
||||
biomes: &horizon_client::biome::Biomes,
|
||||
) -> (
|
||||
horizon_world::worldgen::overrides::WorldgenOverrides,
|
||||
Vec<String>,
|
||||
) {
|
||||
let packs = horizon_client::datapack::discover(world_root);
|
||||
let enabled = horizon_client::datapack::enabled_ids(world_root, &packs);
|
||||
let enabled: Vec<_> = enabled
|
||||
.iter()
|
||||
.filter_map(|id| packs.iter().find(|p| &p.id == id))
|
||||
.collect();
|
||||
let (overrides, warnings) =
|
||||
horizon_client::datapack::worldgen_overrides(&enabled, |b| biomes.contains(b));
|
||||
for warning in warnings {
|
||||
log::warn!("Horizon: data pack worldgen: {warning}");
|
||||
}
|
||||
overrides
|
||||
horizon_client::datapack::worldgen_overrides(&enabled, |b| biomes.contains(b))
|
||||
}
|
||||
|
||||
/// The shapes of the world's levels: their dimension types, the world's
|
||||
|
||||
Reference in new issue
Block a user