mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-07 11:06:11 -10:00
Merge pull request #9563 from xxaxio/feat/9547-sources-dawn-client
🤖 Agent: Dawn Client is only one more place to find the player's own 26.3 jar and assets (cache/minecraft under .dawn). The tests check that nothing is fetched from Mojang.
This commit is contained in:
2 files changed
+53
-9
No files matched your search
+20
-7
@@ -1,5 +1,6 @@
|
||||
//! Where the player's own Minecraft files are: the folder they chose, the official launcher's,
|
||||
//! or another launcher's (Prism Launcher, MultiMC, Modrinth App, ATLauncher, GDLauncher), #434.
|
||||
//! or another launcher's (Prism Launcher, MultiMC, Modrinth App, ATLauncher, GDLauncher, Dawn
|
||||
//! Client), #434.
|
||||
//! horizon-prepare reads the official launcher's layout and pins the version JSON's own sha1, so
|
||||
//! files found elsewhere are linked into that layout in the launcher's data folder, with the
|
||||
//! pinned version JSON from Mojang when the other launcher keeps its own rewrite of it.
|
||||
@@ -132,6 +133,7 @@ pub fn known_folders(os: Os, f: &Folders) -> Vec<(&'static str, PathBuf)> {
|
||||
"ATLauncher",
|
||||
flatpak("com.atlauncher.ATLauncher", "data/atlauncher"),
|
||||
),
|
||||
("Dawn Client", f.home.join(".dawn")),
|
||||
],
|
||||
Os::MacOs => vec![
|
||||
(OFFICIAL, f.data.join("minecraft")),
|
||||
@@ -139,12 +141,14 @@ pub fn known_folders(os: Os, f: &Folders) -> Vec<(&'static str, PathBuf)> {
|
||||
("MultiMC", f.data.join("MultiMC")),
|
||||
("Modrinth App", f.data.join("ModrinthApp")),
|
||||
("ATLauncher", f.data.join("ATLauncher")),
|
||||
("Dawn Client", f.data.join(".dawn")),
|
||||
],
|
||||
Os::Windows => vec![
|
||||
(OFFICIAL, f.data.join(".minecraft")),
|
||||
("Prism Launcher", f.data.join("PrismLauncher")),
|
||||
("Modrinth App", f.data.join("ModrinthApp")),
|
||||
("ATLauncher", f.data.join("ATLauncher")),
|
||||
("Dawn Client", f.data.join(".dawn")),
|
||||
],
|
||||
};
|
||||
// Names every system shares: the Modrinth App before its rename, GDLauncher and its
|
||||
@@ -246,6 +250,14 @@ fn instance_root(dir: &Path) -> Option<PathBuf> {
|
||||
.map(Path::to_path_buf)
|
||||
}
|
||||
|
||||
/// The Dawn Client root above `dir`: Dawn stores its shared official cache in `cache/minecraft/`
|
||||
/// directly below `.dawn/`.
|
||||
fn dawn_root(dir: &Path) -> Option<PathBuf> {
|
||||
dir.ancestors()
|
||||
.find(|a| a.file_name() == Some(std::ffi::OsStr::new(".dawn")))
|
||||
.map(Path::to_path_buf)
|
||||
}
|
||||
|
||||
/// The launcher whose tree `path` is inside, when its folder name is one Horizon knows, so the
|
||||
/// not-found message can name it (#693).
|
||||
fn launcher_of(path: &Path) -> Option<&'static str> {
|
||||
@@ -258,13 +270,14 @@ fn launcher_of(path: &Path) -> Option<&'static str> {
|
||||
"ModrinthApp" | "com.modrinth.theseus" => Some("the Modrinth App"),
|
||||
"atlauncher" | "ATLauncher" => Some("ATLauncher"),
|
||||
"gdlauncher_carbon" | "gdlauncher_next" => Some("GDLauncher"),
|
||||
".dawn" | "dawn" => Some("Dawn Client"),
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
/// The pinned version in one launcher folder, or what the folder lacks. The folder holding
|
||||
/// `libraries` is the folder itself or its `meta` (Modrinth App), `data` (GDLauncher) or
|
||||
/// `datastore` (GDLauncher Next).
|
||||
/// `datastore` (GDLauncher Next) or `cache/minecraft` (Dawn Client).
|
||||
pub fn find(dir: &Path, pins: &Pins) -> Result<Found, String> {
|
||||
if !dir.is_dir() {
|
||||
return Err("the folder doesn't exist".into());
|
||||
@@ -273,7 +286,7 @@ pub fn find(dir: &Path, pins: &Pins) -> Result<Found, String> {
|
||||
let mut other = None;
|
||||
let bases = [dir.to_path_buf()]
|
||||
.into_iter()
|
||||
.chain(["meta", "data", "datastore"].map(|sub| dir.join(sub)));
|
||||
.chain(["meta", "data", "datastore", "cache/minecraft"].map(|sub| dir.join(sub)));
|
||||
for base in bases {
|
||||
for jar in client_jars(&base, v) {
|
||||
let client = base.join(&jar);
|
||||
@@ -321,7 +334,7 @@ pub fn not_found(version: &str, checked: &[(PathBuf, String)], chosen: &Path) ->
|
||||
),
|
||||
None => format!(
|
||||
"\n • Play {version} once in the official Minecraft launcher, or in Prism Launcher, \
|
||||
MultiMC, the Modrinth App, ATLauncher or GDLauncher, then prepare again.\n \
|
||||
MultiMC, the Modrinth App, ATLauncher, GDLauncher or Dawn Client, then prepare again.\n \
|
||||
• Or choose the folder where your launcher keeps Minecraft {version} (Minecraft \
|
||||
folder › Choose… in the launcher, --minecraft on the command line)."
|
||||
),
|
||||
@@ -356,10 +369,10 @@ pub fn resolve(
|
||||
let mut checked = Vec::new();
|
||||
let mut found = None;
|
||||
// The chosen folder, the folders above it (an instance's own folder may be chosen), and,
|
||||
// when it is inside a Prism or MultiMC instance tree, the launcher root above `instances`
|
||||
// that holds their shared `libraries` (#693).
|
||||
// when it is inside a Prism or MultiMC instance tree or a Dawn Client folder, the launcher
|
||||
// root that holds their shared `libraries` (#693).
|
||||
let mut dirs: Vec<PathBuf> = chosen.ancestors().take(4).map(Path::to_path_buf).collect();
|
||||
if let Some(root) = instance_root(chosen) {
|
||||
if let Some(root) = instance_root(chosen).or_else(|| dawn_root(chosen)) {
|
||||
if !dirs.contains(&root) {
|
||||
dirs.push(root);
|
||||
}
|
||||
|
||||
@@ -289,6 +289,30 @@ fn the_modrinth_app_atlauncher_and_gdlauncher_are_found() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dawn_client_is_found_in_cache() {
|
||||
let s = Scratch::new("dawn");
|
||||
let dir = s.launcher(".dawn", "cache/minecraft", "versions/26.3/26.3.jar");
|
||||
s.write(".dawn/cache/minecraft/versions/26.3/26.3.json", MANIFEST);
|
||||
let linked = s.0.join("linked");
|
||||
let mojang = Mojang::new(b"");
|
||||
let got = resolve_with(&dir, &[], &linked, &mojang).unwrap();
|
||||
assert_eq!(got, dir.join("cache/minecraft"));
|
||||
assert!(mojang.urls.lock().unwrap().is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_dawn_sync_folder_finds_the_launcher_root() {
|
||||
let s = Scratch::new("dawn-tree");
|
||||
let dir = s.launcher(".dawn", "cache/minecraft", "versions/26.3/26.3.jar");
|
||||
s.write(".dawn/cache/minecraft/versions/26.3/26.3.json", MANIFEST);
|
||||
let chosen = dir.join("auto-sync/groups/default");
|
||||
fs::create_dir_all(&chosen).unwrap();
|
||||
let linked = s.0.join("linked");
|
||||
let got = resolve_with(&chosen, &[], &linked, &Mojang::new(b"")).unwrap();
|
||||
assert_eq!(got, dir.join("cache/minecraft"));
|
||||
}
|
||||
|
||||
/// A Modrinth App that only ever played a Fabric profile of 26.3 keeps the vanilla client jar
|
||||
/// under the loader's name (#1783); a profile of another version beside it is not taken.
|
||||
#[test]
|
||||
@@ -389,7 +413,9 @@ fn the_not_found_message_names_the_launcher_that_was_chosen() {
|
||||
fs::create_dir_all(&other).unwrap();
|
||||
let error = resolve_with(&other, &[], &s.0.join("linked"), &Mojang::new(MANIFEST)).unwrap_err();
|
||||
assert!(
|
||||
error.contains("Prism Launcher, MultiMC, the Modrinth App, ATLauncher or GDLauncher"),
|
||||
error.contains(
|
||||
"Prism Launcher, MultiMC, the Modrinth App, ATLauncher, GDLauncher or Dawn Client"
|
||||
),
|
||||
"{error}"
|
||||
);
|
||||
}
|
||||
@@ -480,7 +506,9 @@ fn nothing_found_lists_every_folder_and_what_it_lacks() {
|
||||
empty.display()
|
||||
);
|
||||
assert!(error.starts_with(&expected), "{error}");
|
||||
assert!(error.contains("Prism Launcher, MultiMC, the Modrinth App, ATLauncher or GDLauncher"));
|
||||
assert!(error.contains(
|
||||
"Prism Launcher, MultiMC, the Modrinth App, ATLauncher, GDLauncher or Dawn Client"
|
||||
));
|
||||
// A launcher that isn't installed isn't listed.
|
||||
assert!(!error.contains("atlauncher"));
|
||||
assert!(mojang.urls.lock().unwrap().is_empty());
|
||||
@@ -521,6 +549,7 @@ fn each_system_has_its_launcher_folders() {
|
||||
"ATLauncher: /home/r/.local/share/atlauncher",
|
||||
"GDLauncher: /home/r/.local/share/gdlauncher_carbon",
|
||||
"GDLauncher: /home/r/.config/gdlauncher_next",
|
||||
"Dawn Client: /home/r/.dawn",
|
||||
] {
|
||||
assert!(got.iter().any(|g| g == expected), "{expected} in {got:#?}");
|
||||
}
|
||||
@@ -538,6 +567,7 @@ fn each_system_has_its_launcher_folders() {
|
||||
assert!(
|
||||
got.contains(&"Prism Launcher: /Users/r/Library/Application Support/PrismLauncher".into())
|
||||
);
|
||||
assert!(got.contains(&"Dawn Client: /Users/r/Library/Application Support/.dawn".into()));
|
||||
let windows = Folders {
|
||||
home: "C:/Users/r".into(),
|
||||
data: "C:/Users/r/AppData/Roaming".into(),
|
||||
@@ -549,4 +579,5 @@ fn each_system_has_its_launcher_folders() {
|
||||
"the official launcher: C:/Users/r/AppData/Roaming/.minecraft"
|
||||
);
|
||||
assert!(got.contains(&"ATLauncher: C:/Users/r/AppData/Roaming/ATLauncher".into()));
|
||||
assert!(got.contains(&"Dawn Client: C:/Users/r/AppData/Roaming/.dawn".into()));
|
||||
}
|
||||
Reference in new issue
Block a user