mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de840da0e5 | ||
|
|
c6980fb2b7 | ||
|
|
adcfe810f2 | ||
|
|
3802a97dc9 |
No files matched your search
@@ -17,7 +17,7 @@ pub mod pyjson;
|
||||
mod sounds;
|
||||
mod survival;
|
||||
|
||||
pub use sounds::{fonts, packs, panorama, sounds, BUILT_IN_PACKS};
|
||||
pub use sounds::{fonts, languages, packs, panorama, sounds, BUILT_IN_PACKS};
|
||||
|
||||
use pyjson::Value;
|
||||
use sha2::Digest;
|
||||
|
||||
@@ -20,6 +20,7 @@ Usage: horizon-prepare [--prepare] [--server-jar PATH] [--minecraft-dir PATH] [-
|
||||
horizon-prepare panorama [--minecraft-dir PATH] [--root PATH]
|
||||
horizon-prepare fonts [--minecraft-dir PATH] [--root PATH]
|
||||
horizon-prepare packs [--minecraft-dir PATH] [--root PATH]
|
||||
horizon-prepare languages [--minecraft-dir PATH] [--root PATH]
|
||||
|
||||
--prepare Import the pinned game files from your own copy first
|
||||
--server-jar PATH The pinned server jar you downloaded yourself
|
||||
@@ -36,7 +37,8 @@ The resources go to <root>/.local/horizon-client/<version>; pass that to horizon
|
||||
horizon-prepare panorama repairs the classic menu background in existing resources without Java.
|
||||
horizon-prepare fonts adds the GNU Unifont glyphs (characters the bitmap fonts lack) the same way.
|
||||
horizon-prepare packs adds the built-in Programmer Art and High Contrast resource packs the same way.
|
||||
Full preparation also imports all three after extracting the client JAR's placeholders.
|
||||
horizon-prepare languages adds the bundled languages and the language list the JAR lacks the same way.
|
||||
Full preparation also imports all four after extracting the client JAR's placeholders.
|
||||
|
||||
horizon-prepare sounds copies the pinned version's sounds (about 380 MB) from the official
|
||||
launcher's asset store into the same folder, checking every file. It is optional: without it the
|
||||
@@ -68,8 +70,12 @@ fn main() -> ExitCode {
|
||||
};
|
||||
let mut root = None;
|
||||
let mut args = std::env::args_os().skip(1).peekable();
|
||||
let assets =
|
||||
args.next_if(|a| matches!(a.to_str(), Some("sounds" | "panorama" | "fonts" | "packs")));
|
||||
let assets = args.next_if(|a| {
|
||||
matches!(
|
||||
a.to_str(),
|
||||
Some("sounds" | "panorama" | "fonts" | "packs" | "languages")
|
||||
)
|
||||
});
|
||||
while let Some(arg) = args.next() {
|
||||
let text = arg.to_string_lossy().into_owned();
|
||||
let (flag, inline) = match text.split_once('=') {
|
||||
@@ -138,6 +144,9 @@ fn main() -> ExitCode {
|
||||
Some("packs") => {
|
||||
horizon_prepare::packs(&options.root, options.minecraft_dir.as_deref(), &log)
|
||||
}
|
||||
Some("languages") => {
|
||||
horizon_prepare::languages(&options.root, options.minecraft_dir.as_deref(), &log)
|
||||
}
|
||||
_ => horizon_prepare::prepare(&options, &log),
|
||||
};
|
||||
match result {
|
||||
|
||||
@@ -112,6 +112,20 @@ pub fn fonts(root: &Path, minecraft: Option<&Path>, log: Log) -> Result<PathBuf,
|
||||
copy_assets(root, minecraft, log, is_font, "Font", &UNIFONT)
|
||||
}
|
||||
|
||||
/// Every bundled language and the language list, both of which only the asset index holds
|
||||
/// (the client JAR carries `en_us` alone): `pack.mcmeta`'s `language` section is what the
|
||||
/// language screen offers, `minecraft/lang/<code>.json` the strings each one draws (#1272).
|
||||
/// Also usable on already-prepared resources without Java.
|
||||
pub fn languages(root: &Path, minecraft: Option<&Path>, log: Log) -> Result<PathBuf, String> {
|
||||
copy_assets(root, minecraft, log, is_language, "Language", &LANGUAGES)
|
||||
}
|
||||
|
||||
const LANGUAGES: [&str; 1] = ["pack.mcmeta"];
|
||||
|
||||
fn is_language(name: &str) -> bool {
|
||||
name == "pack.mcmeta" || name.starts_with("minecraft/lang/")
|
||||
}
|
||||
|
||||
/// Full preparation can run from cached JARs without an official launcher install.
|
||||
pub(crate) fn optional_assets(root: &Path, minecraft: Option<&Path>, log: Log) {
|
||||
if let Err(error) = panorama(root, minecraft, log) {
|
||||
@@ -129,6 +143,11 @@ pub(crate) fn optional_assets(root: &Path, minecraft: Option<&Path>, log: Log) {
|
||||
"Programmer Art and High Contrast not imported: {error}; run horizon-prepare packs later"
|
||||
));
|
||||
}
|
||||
if let Err(error) = languages(root, minecraft, log) {
|
||||
log(&format!(
|
||||
"Languages not imported: {error}; run horizon-prepare languages later"
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
const PANORAMA: [&str; 7] = [
|
||||
@@ -278,6 +297,15 @@ mod tests {
|
||||
}
|
||||
|
||||
fn with_panorama(name: &str, panorama: &[&'static str]) -> Fixture {
|
||||
Self::with_extras(name, panorama, &[])
|
||||
}
|
||||
|
||||
/// The same store with extra index entries, for the files the index alone holds.
|
||||
fn with_extras(
|
||||
name: &str,
|
||||
panorama: &[&'static str],
|
||||
extras: &[(&'static str, &'static [u8])],
|
||||
) -> Fixture {
|
||||
let dir = std::env::temp_dir().join(format!(
|
||||
"horizon-prepare-sounds-{name}-{}",
|
||||
std::process::id()
|
||||
@@ -302,6 +330,9 @@ mod tests {
|
||||
// Distinct object bytes let the test catch swapped faces too.
|
||||
objects.push((name, name.as_bytes().to_vec()));
|
||||
}
|
||||
for &(name, data) in extras {
|
||||
objects.push((name, data.to_vec()));
|
||||
}
|
||||
let mut index = String::from("{\"objects\": {");
|
||||
for (i, (name, data)) in objects.iter().enumerate() {
|
||||
let hash = sha1_hex(data);
|
||||
@@ -391,6 +422,32 @@ mod tests {
|
||||
f.run().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn languages_come_from_the_asset_store() {
|
||||
// The client JAR carries `en_us` alone, so every other language and the list in
|
||||
// `pack.mcmeta` come from the index (#1272).
|
||||
let f = Fixture::with_extras(
|
||||
"languages",
|
||||
&[],
|
||||
&[("pack.mcmeta", b"{\"language\": {\"fr_fr\": {}}}")],
|
||||
);
|
||||
let lines = std::cell::RefCell::new(Vec::new());
|
||||
let target = languages(&f.root, Some(&f.minecraft), &|l| {
|
||||
lines.borrow_mut().push(l.to_string())
|
||||
})
|
||||
.unwrap();
|
||||
assert!(fs::read(target.join("assets/pack.mcmeta"))
|
||||
.unwrap()
|
||||
.starts_with(b"{\"language\""));
|
||||
assert_eq!(
|
||||
fs::read(target.join("assets/minecraft/lang/fr_fr.json")).unwrap(),
|
||||
b"{}"
|
||||
);
|
||||
// Each entry point copies its own set: the sounds stay where they belong.
|
||||
assert!(!target.join("assets/minecraft/sounds.json").exists());
|
||||
assert_eq!(*lines.borrow(), ["Language assets ready: 2 files, 0.0 MB"]);
|
||||
}
|
||||
|
||||
/// #1076: the launcher holds an index Mojang republished under the same id, so its SHA-1
|
||||
/// is not the one in the version JSON. A known one is used quietly, an unknown one with a
|
||||
/// line in the log; the sounds come through either way.
|
||||
@@ -539,7 +596,10 @@ mod tests {
|
||||
lines[1..],
|
||||
[
|
||||
"Font assets ready: 2 files, 0.0 MB",
|
||||
"Built-in pack assets ready: 2 files, 0.0 MB"
|
||||
"Built-in pack assets ready: 2 files, 0.0 MB",
|
||||
// This store has no `pack.mcmeta`, so the languages report it.
|
||||
"Languages not imported: pack.mcmeta is missing from the asset index; \
|
||||
run horizon-prepare languages later"
|
||||
]
|
||||
),
|
||||
_ => {
|
||||
@@ -549,9 +609,14 @@ mod tests {
|
||||
&& lines[2].ends_with("; run horizon-prepare packs later"),
|
||||
"{lines:?}"
|
||||
);
|
||||
assert!(
|
||||
lines[3].starts_with("Languages not imported: ")
|
||||
&& lines[3].ends_with("; run horizon-prepare languages later"),
|
||||
"{lines:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
assert_eq!(lines.len(), 3);
|
||||
assert_eq!(lines.len(), 4);
|
||||
for name in PANORAMA {
|
||||
assert_eq!(fs::read(target.join(name)).unwrap(), b"jar placeholder");
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user