mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e93f0a460 | ||
|
|
4c877c4c49 | ||
|
|
ed5e93d659 | ||
|
|
916cca3b77 | ||
|
|
4a4cfcd68f |
No files matched your search
Generated
+1
@@ -1733,6 +1733,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"horizon-core",
|
||||
"libm",
|
||||
"log",
|
||||
"lz4_flex",
|
||||
"postcard",
|
||||
"serde",
|
||||
|
||||
@@ -49,7 +49,7 @@ pub mod hud_overlays;
|
||||
pub mod inventory_effects;
|
||||
pub mod java_text;
|
||||
pub mod jigsaw_block;
|
||||
pub mod json_folder;
|
||||
pub use horizon_world::json_folder;
|
||||
pub mod level_loading;
|
||||
pub mod light;
|
||||
pub mod lod;
|
||||
|
||||
@@ -111,9 +111,14 @@ impl Game<'_> {
|
||||
pub(super) struct SyncPreload(std::thread::JoinHandle<std::result::Result<SyncData, String>>);
|
||||
|
||||
/// Start reading the server's data beside the world's preparation; `None`
|
||||
/// when it is read already, or being read (`preload_world_data`).
|
||||
/// when it is read already, or being read: by `sync_data` (the lock is
|
||||
/// held), or soon by a world data preload still running, which ends with
|
||||
/// it. A second read would be thrown away by `adopt`.
|
||||
pub(super) fn preload_sync_data(root: &std::path::Path) -> Option<SyncPreload> {
|
||||
if !SYNC.try_lock().is_ok_and(|sync| sync.is_none()) {
|
||||
// PRELOAD before SYNC, never both: `preload_world_data` takes SYNC
|
||||
// under PRELOAD.
|
||||
if super::world_loading::preload_running() || !SYNC.try_lock().is_ok_and(|sync| sync.is_none())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
let root = root.to_owned();
|
||||
|
||||
@@ -388,6 +388,10 @@ pub(super) fn preload_world_data(
|
||||
// seed shares: about 140 ms off opening the world.
|
||||
let _ = data.prepare_decoration("minecraft:normal", "minecraft:overworld");
|
||||
}
|
||||
// The loot data's item tables and the server's data both
|
||||
// read the recipe folder: held here, it is read once.
|
||||
let _recipe_files =
|
||||
horizon_client::json_folder::read(&resources.join("data/minecraft/recipe"));
|
||||
// The preload is the game's own data; the world's packs'
|
||||
// tables are built when it opens (finish_open_world).
|
||||
let _ = horizon_client::structure_blocks::loot_data(
|
||||
@@ -459,6 +463,10 @@ pub(super) fn preload_launch_world(
|
||||
let preset = horizon_client::save::WorldGen::preset(&world_root);
|
||||
let _ = data.prepare_decoration(preset, "minecraft:overworld");
|
||||
}
|
||||
// As in `preload_world_data`: the loot data and the server's
|
||||
// data share one read of the recipe folder.
|
||||
let _recipe_files =
|
||||
horizon_client::json_folder::read(&resources.join("data/minecraft/recipe"));
|
||||
let _ = horizon_client::structure_blocks::loot_data(
|
||||
&resources,
|
||||
&horizon_world::loot::PackOverlay::NONE,
|
||||
@@ -475,6 +483,15 @@ pub(super) fn preload_launch_world(
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the "World data preload" thread is still running: it reads the
|
||||
/// server's data (`sync_data`) last, so nothing else needs to.
|
||||
pub(super) fn preload_running() -> bool {
|
||||
matches!(
|
||||
&*PRELOAD.lock().unwrap_or_else(|e| e.into_inner()),
|
||||
Preload::Started { thread, .. } if !thread.is_finished()
|
||||
)
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
@@ -208,6 +208,10 @@ impl SyncData {
|
||||
resources: &Path,
|
||||
overlay: &horizon_world::loot::PackOverlay,
|
||||
) -> Result<Self, String> {
|
||||
// The recipe book, the recipe sync and the advancements read the
|
||||
// recipe folder: held here, they share one read of it.
|
||||
let _recipe_files =
|
||||
horizon_world::json_folder::read(&resources.join("data/minecraft/recipe"));
|
||||
let builtin = Builtin::find(resources)
|
||||
.and_then(|p| Builtin::load(&p).ok())
|
||||
.ok_or("registries.json not found next to the resources")?;
|
||||
|
||||
@@ -52,17 +52,16 @@ fn ingredient(v: &Value) -> Option<Ingredient> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Every recipe file, by recipe id (the registry's order).
|
||||
pub(super) fn recipes(dir: &Path, prefix: &str, out: &mut BTreeMap<String, Value>) {
|
||||
for entry in std::fs::read_dir(dir).into_iter().flatten().flatten() {
|
||||
let path = entry.path();
|
||||
let name = entry.file_name().to_string_lossy().into_owned();
|
||||
if path.is_dir() {
|
||||
recipes(&path, &format!("{prefix}{name}/"), out);
|
||||
} else if let Some(stem) = name.strip_suffix(".json")
|
||||
&& let Ok(v) = serde_json::from_slice(&std::fs::read(&path).unwrap_or_default())
|
||||
{
|
||||
out.insert(format!("minecraft:{prefix}{stem}"), v);
|
||||
/// Every recipe file, by recipe id (the registry's order): read through
|
||||
/// `json_folder`, so a load holding the folder shares one read of it. A file
|
||||
/// that can't be read or doesn't parse is left out.
|
||||
pub(super) fn recipes(dir: &Path, out: &mut BTreeMap<String, Value>) {
|
||||
let Ok(folder) = horizon_world::json_folder::read(dir) else {
|
||||
return;
|
||||
};
|
||||
for file in &folder.files {
|
||||
if let Ok(v) = serde_json::from_slice(file.bytes().unwrap_or_default()) {
|
||||
out.insert(format!("minecraft:{}", file.name), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +93,7 @@ pub(super) fn network_recipes(
|
||||
overlay: &horizon_world::loot::PackOverlay,
|
||||
) -> (BTreeMap<String, Box<str>>, HashMap<String, i32>) {
|
||||
let mut all = BTreeMap::new();
|
||||
recipes(&resources.join("data/minecraft/recipe"), "", &mut all);
|
||||
recipes(&resources.join("data/minecraft/recipe"), &mut all);
|
||||
overlay_recipes(overlay, &mut all);
|
||||
// The data's recipe filters, as the server's own tables apply them
|
||||
// (#5910), once, before the ingredient normalization, so a swapped
|
||||
|
||||
@@ -8,6 +8,7 @@ description = "Horizon vanilla world data, NBT, regions and chunk storage"
|
||||
|
||||
[dependencies]
|
||||
libm = "=0.2.16"
|
||||
log = "0.4"
|
||||
serde_json = { version = "1.0.151", features = ["raw_value"] }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
sha2 = "0.10"
|
||||
|
||||
File renamed without changes.
@@ -77,6 +77,7 @@ pub mod item_use_catalog;
|
||||
pub mod item_use_lifecycle;
|
||||
pub mod item_use_start;
|
||||
pub mod java_hash_map;
|
||||
pub mod json_folder;
|
||||
pub mod lazy_json;
|
||||
pub mod level;
|
||||
pub mod liquid_collision;
|
||||
|
||||
@@ -635,20 +635,15 @@ fn load_dir(
|
||||
prefix: &str,
|
||||
out: &mut HashMap<String, Value>,
|
||||
) -> io::Result<()> {
|
||||
let Ok(entries) = fs::read_dir(dir) else {
|
||||
// Through `json_folder`: a load holding the folder (the recipes, read by
|
||||
// the item tables, the recipe book and the server's sync too) shares one
|
||||
// read of it.
|
||||
let Ok(folder) = crate::json_folder::read(dir) else {
|
||||
return Ok(());
|
||||
};
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
let Some(stem) = path.file_stem().and_then(|s| s.to_str()) else {
|
||||
continue;
|
||||
};
|
||||
if path.is_dir() {
|
||||
load_dir(&path, namespace, &format!("{prefix}{stem}/"), out)?;
|
||||
} else if path.extension().is_some_and(|e| e == "json") {
|
||||
let value = serde_json::from_slice(&fs::read(&path)?)?;
|
||||
out.insert(format!("{namespace}:{prefix}{stem}"), value);
|
||||
}
|
||||
for file in &folder.files {
|
||||
let value = serde_json::from_slice(file.bytes()?)?;
|
||||
out.insert(format!("{namespace}:{prefix}{}", file.name), value);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Generated
+1
@@ -2817,6 +2817,7 @@ dependencies = [
|
||||
"flate2",
|
||||
"horizon-core",
|
||||
"libm",
|
||||
"log",
|
||||
"lz4_flex",
|
||||
"postcard",
|
||||
"serde",
|
||||
|
||||
Reference in new issue
Block a user