Add modpack creation and compilation

This commit is contained in:
Daniel Hutzley
2021-12-05 12:20:59 -08:00
parent 5ffddd6c8a
commit fc076c2e54
5 changed files with 219 additions and 10 deletions

142
Cargo.lock generated
View File

@@ -75,12 +75,39 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
dependencies = [
"block-padding",
"byte-tools",
"byteorder",
"generic-array",
]
[[package]]
name = "block-padding"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
dependencies = [
"byte-tools",
]
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.8.0" version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byte-tools"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.4.3" version = "1.4.3"
@@ -181,6 +208,15 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "digest"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
dependencies = [
"generic-array",
]
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.29" version = "0.8.29"
@@ -190,6 +226,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "fake-simd"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
[[package]] [[package]]
name = "flate2" name = "flate2"
version = "1.0.22" version = "1.0.22"
@@ -328,6 +370,15 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "generic-array"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd"
dependencies = [
"typenum",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.3" version = "0.2.3"
@@ -504,6 +555,17 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "json5"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1"
dependencies = [
"pest",
"pest_derive",
"serde",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -534,6 +596,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "maplit"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]] [[package]]
name = "matches" name = "matches"
version = "0.1.9" version = "0.1.9"
@@ -646,6 +714,12 @@ version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "opaque-debug"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
[[package]] [[package]]
name = "openssl" name = "openssl"
version = "0.10.38" version = "0.10.38"
@@ -716,6 +790,49 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pest"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53"
dependencies = [
"ucd-trie",
]
[[package]]
name = "pest_derive"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0"
dependencies = [
"pest",
"pest_generator",
]
[[package]]
name = "pest_generator"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pest_meta"
version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d"
dependencies = [
"maplit",
"pest",
"sha-1",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.7" version = "0.2.7"
@@ -956,6 +1073,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sha-1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
dependencies = [
"block-buffer",
"digest",
"fake-simd",
"opaque-debug",
]
[[package]] [[package]]
name = "sha1" name = "sha1"
version = "0.6.0" version = "0.6.0"
@@ -1039,6 +1168,7 @@ dependencies = [
"daedalus", "daedalus",
"fs_extra", "fs_extra",
"futures", "futures",
"json5",
"lazy_static", "lazy_static",
"path-clean", "path-clean",
"regex", "regex",
@@ -1194,6 +1324,18 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "typenum"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec"
[[package]]
name = "ucd-trie"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c"
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.7" version = "0.3.7"

View File

@@ -15,6 +15,7 @@ daedalus = "0.1.6"
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
json5 = "0.4.1"
chrono = { version = "0.4", features = ["serde"] } chrono = { version = "0.4", features = ["serde"] }
uuid = { version = "0.8", features = ["serde", "v4"] } uuid = { version = "0.8", features = ["serde", "v4"] }
bytes = "1" bytes = "1"

View File

@@ -1,4 +1,5 @@
use daedalus::minecraft::{ArgumentType, VersionInfo}; use daedalus::minecraft::{ArgumentType, VersionInfo};
use serde::{Deserialize, Serialize};
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio}; use std::process::{Command, Stdio};
use thiserror::Error; use thiserror::Error;
@@ -65,7 +66,8 @@ pub async fn fetch_metadata() -> Result<
Ok((game?, forge?, fabric?)) Ok((game?, forge?, fabric?))
} }
#[derive(Debug, Eq, PartialEq, Clone, Copy)] #[derive(Debug, Eq, PartialEq, Clone, Copy, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum ModLoader { pub enum ModLoader {
Vanilla, Vanilla,
Forge, Forge,

View File

@@ -4,18 +4,23 @@ use daedalus::download_file;
use fs_extra::dir::CopyOptions; use fs_extra::dir::CopyOptions;
use serde::Deserialize; use serde::Deserialize;
use std::{convert::TryFrom, env, io, path::Path}; use std::{convert::TryFrom, env, io, path::Path};
use tokio::fs; use tokio::{fs, try_join};
use uuid::Uuid; use uuid::Uuid;
use zip::ZipArchive; use zip::ZipArchive;
use self::{manifest::Manifest, pack::Modpack}; use self::{
manifest::Manifest,
pack::{Modpack, ModpackGame},
};
pub mod pack;
pub mod manifest; pub mod manifest;
pub mod modrinth_api; pub mod modrinth_api;
pub mod pack;
pub const COMPILED_PATH: &'static str = "compiled/";
pub const MANIFEST_PATH: &'static str = "index.json"; pub const MANIFEST_PATH: &'static str = "index.json";
pub const OVERRIDES_PATH: &'static str = "overrides/"; pub const OVERRIDES_PATH: &'static str = "overrides/";
pub const PACK_JSON5_PATH: &'static str = "modpack.json5";
#[derive(thiserror::Error, Debug)] #[derive(thiserror::Error, Debug)]
pub enum ModpackError { pub enum ModpackError {
@@ -43,6 +48,9 @@ pub enum ModpackError {
#[error("Error parsing json: {0}")] #[error("Error parsing json: {0}")]
JsonError(#[from] serde_json::Error), JsonError(#[from] serde_json::Error),
#[error("Error parsing json5: {0}")]
Json5Error(#[from] json5::Error),
#[error("Error joining futures: {0}")] #[error("Error joining futures: {0}")]
JoinError(#[from] tokio::task::JoinError), JoinError(#[from] tokio::task::JoinError),
@@ -50,7 +58,7 @@ pub enum ModpackError {
VersionError(String), VersionError(String),
#[error("Error downloading file: {0}")] #[error("Error downloading file: {0}")]
FetchError(#[from] reqwest::Error) FetchError(#[from] reqwest::Error),
} }
type ModpackResult<T> = Result<T, ModpackError>; type ModpackResult<T> = Result<T, ModpackError>;
@@ -121,3 +129,57 @@ pub async fn realise_modpack(
modpack.download_files(dest, side).await?; modpack.download_files(dest, side).await?;
Ok(()) Ok(())
} }
pub fn to_pack_json5(pack: &Modpack) -> ModpackResult<String> {
let json5 = json5::to_string(pack)?;
Ok(format!("// This modpack is managed using Theseus. It can be edited using either a Theseus-compatible launcher or manually.\n{}", json5))
}
lazy_static::lazy_static! {
static ref PACK_GITIGNORE: String = format!(r#"
{0}
"#, COMPILED_PATH);
}
pub async fn create_modpack(
name: &str,
game: ModpackGame,
summary: Option<&str>,
) -> ModpackResult<()> {
let output_dir = Path::new("./").join(name);
let pack = Modpack::new(game, "0.1.0", name, summary);
try_join!(
fs::create_dir(&output_dir),
fs::create_dir(output_dir.join(OVERRIDES_PATH)),
fs::write(output_dir.join(".gitignore"), PACK_GITIGNORE.as_str()),
fs::write(output_dir.join(PACK_JSON5_PATH), to_pack_json5(&pack)?),
)?;
Ok(())
}
pub async fn compile_modpack(dir: &Path) -> ModpackResult<()> {
let result_dir = dir.join(COMPILED_PATH);
let pack: Modpack = json5::from_str(&fs::read_to_string(dir.join(PACK_JSON5_PATH)).await?)?;
if dir.join(OVERRIDES_PATH).exists() {
fs_extra::dir::copy(
dir.join(OVERRIDES_PATH),
result_dir.join(OVERRIDES_PATH),
&CopyOptions::new(),
)?;
}
let manifest = Manifest::try_from(&pack)?;
try_join!(
fs::create_dir(&result_dir),
fs::write(
result_dir.join(MANIFEST_PATH),
serde_json::to_string(&manifest)?
),
)?;
Ok(())
}

View File

@@ -1,5 +1,6 @@
use daedalus::download_file_mirrors; use daedalus::download_file_mirrors;
use futures::future; use futures::future;
use serde::{Deserialize, Serialize};
use std::{ use std::{
collections::HashSet, collections::HashSet,
hash::Hash, hash::Hash,
@@ -13,7 +14,7 @@ use super::{
}; };
use crate::launcher::ModLoader; use crate::launcher::ModLoader;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct Modpack { pub struct Modpack {
pub game: ModpackGame, pub game: ModpackGame,
pub version: String, pub version: String,
@@ -96,14 +97,14 @@ impl Modpack {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub enum ModpackGame { pub enum ModpackGame {
// TODO: Currently, the launcher does not support specifying mod loader versions, so I just // TODO: Currently, the launcher does not support specifying mod loader versions, so I just
// store the loader here. // store the loader here.
Minecraft(String, ModLoader), Minecraft(String, ModLoader),
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct ModpackFile { pub struct ModpackFile {
pub path: PathBuf, pub path: PathBuf,
pub hashes: ModpackFileHashes, pub hashes: ModpackFileHashes,
@@ -145,7 +146,8 @@ impl ModpackFile {
} }
} }
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "snake_case")]
pub enum ModpackEnv { pub enum ModpackEnv {
ClientOnly, ClientOnly,
ServerOnly, ServerOnly,
@@ -168,7 +170,7 @@ impl ModpackEnv {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq)]
pub struct ModpackFileHashes { pub struct ModpackFileHashes {
pub sha1: String, pub sha1: String,
} }