diff --git a/Cargo.lock b/Cargo.lock index 20e2246..c03fd91 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,7 +451,9 @@ dependencies = [ "bitflags", "chrono", "env_logger", + "libloading", "log", + "mar", "reqwest", "serde", "serde_json", @@ -893,6 +895,16 @@ version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +[[package]] +name = "libloading" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libredox" version = "0.1.3" diff --git a/denji/examples/install-server.rs b/denji/examples/install-server.rs index 2142af0..dc6fd56 100644 --- a/denji/examples/install-server.rs +++ b/denji/examples/install-server.rs @@ -10,6 +10,7 @@ use std::fs::create_dir; use std::path::PathBuf; use std::sync::mpsc::channel; // use std::sync::Arc; +use std::env::consts; use std::thread::spawn; // use std::time::Duration; @@ -89,7 +90,11 @@ impl ServerParameters for ForgeServer { } fn run_args(&self) -> String { - format!("java -jar libraries/net/minecraftforge/forge/{0}/forge-{0}-server.jar @usr_jvm_args.txt nogui \"$@\"", self.artifact_version()) + format!( + "java @user_jvm_args.txt @libraries/net/minecraftforge/forge/{}/{}_args.txt nogui \"$@\"", + self.artifact_version(), + consts::FAMILY + ) } } diff --git a/denji/src/shell.rs b/denji/src/shell.rs index 562d9ec..42c5b13 100644 --- a/denji/src/shell.rs +++ b/denji/src/shell.rs @@ -74,7 +74,7 @@ pub enum DenjiError { #[error("http error:{0}")] Http(#[from] reqwest::Error), - #[error("installer returned code {0}")] + #[error("Installer returned code {0}")] Installer(i32), #[error("while writing run script: {0}")] diff --git a/dms-backend/src/worker.rs b/dms-backend/src/worker.rs index 3ac99bc..6b4dbc8 100644 --- a/dms-backend/src/worker.rs +++ b/dms-backend/src/worker.rs @@ -56,33 +56,33 @@ async fn build_server( "Building server {} for {} {}", params.name, params.server, params.server_version ); - let (tx, rx) = std::sync::mpsc::channel::(); - - info!("Spawning read thread"); - std::thread::spawn(move || loop { - match rx.recv_timeout(std::time::Duration::from_secs(90)) { - Ok(line) => info!("{}", line), - Err(std::sync::mpsc::RecvTimeoutError::Timeout) => { - error!("Timeout reached while awaiting message"); - } - Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => break, - } - }); - - let server_build = denji::MinecraftServer::new( - params.server.parse::().unwrap(), - ¶ms.server_version, - ¶ms.server_version, - "target/servers/dummy/", - ); - - tokio::task::spawn(async move { - if let Err(e) = server_build.build_server(tx).await { - error!("An error occurred while building the server: {:?}", e); - } - }) - .await - .expect("expected this task to not return any errors"); + // let (tx, rx) = std::sync::mpsc::channel::(); + + // info!("Spawning read thread"); + // std::thread::spawn(move || loop { + // match rx.recv_timeout(std::time::Duration::from_secs(90)) { + // Ok(line) => info!("{}", line), + // Err(std::sync::mpsc::RecvTimeoutError::Timeout) => { + // error!("Timeout reached while awaiting message"); + // } + // Err(std::sync::mpsc::RecvTimeoutError::Disconnected) => break, + // } + // }); + + // let server_build = denji::MinecraftServer::new( + // params.server.parse::().unwrap(), + // ¶ms.server_version, + // ¶ms.server_version, + // "target/servers/dummy/", + // ); + + // tokio::task::spawn(async move { + // if let Err(e) = server_build.build_server(tx).await { + // error!("An error occurred while building the server: {:?}", e); + // } + // }) + // .await + // .expect("expected this task to not return any errors"); // context.servers.push(MinecraftServer); diff --git a/elytra/Cargo.toml b/elytra/Cargo.toml index 5eafce8..0c09727 100644 --- a/elytra/Cargo.toml +++ b/elytra/Cargo.toml @@ -4,10 +4,9 @@ version = "0.1.0" edition = "2021" [dependencies] -serde.workspace = true -thiserror.workspace = true -log.workspace = true -tokio.workspace = true +serde = { workspace = true, optional = true } +thiserror = { workspace = true, optional = true } +log = { workspace = true, optional = true } reqwest = { workspace = true, optional = true } zip = { workspace = true, optional = true } @@ -16,18 +15,30 @@ chrono = { version = "0.4.38", default-features = false, features = [ "std", "serde", ], optional = true } +libloading = { version = "0.8.6", optional = true } +mar = { path = "../mar", default-features = false, optional = true } [features] -default = ["providers-modrinth", "utils-modpack", "utils-mod"] +default = ["providers-modrinth", "manifest"] providers-base = ["dep:reqwest"] providers-hangar = ["providers-base", "dep:bitflags", "dep:chrono"] providers-modrinth = ["providers-base"] -utils-base = ["dep:zip"] -utils-modpack = ["utils-base"] -utils-mod = ["utils-base"] +utils-base = [] +utils-modpack = ["utils-base", "dep:zip"] +utils-mod = ["utils-base", "dep:zip"] +utils-plugin = [ + "utils-base", + "dep:libloading", + "dep:thiserror", + "dep:log", + "plugin", +] + +manifest = ["dep:serde", "dep:log", "dep:thiserror"] +plugin = ["mar/type-maven-artifact"] [lints] workspace = true @@ -37,3 +48,4 @@ env_logger = "0.11.5" toml = "0.8.19" serde_urlencoded = "0.7.1" serde_json.workspace = true +tokio.workspace = true diff --git a/elytra/src/lib.rs b/elytra/src/lib.rs index 79e5a98..373715c 100644 --- a/elytra/src/lib.rs +++ b/elytra/src/lib.rs @@ -1,7 +1,17 @@ +#[cfg(feature = "manifest")] pub mod errors; +#[cfg(feature = "manifest")] pub mod manifest; +#[cfg(feature = "plugin")] +pub mod plugin; +#[cfg(feature = "plugin")] +pub use plugin::*; + #[cfg(feature = "providers-base")] pub mod providers; + #[cfg(feature = "utils-base")] pub mod utils; +#[cfg(feature = "utils-base")] +pub use utils::*; diff --git a/elytra/src/plugin/mod.rs b/elytra/src/plugin/mod.rs new file mode 100644 index 0000000..4ac4e08 --- /dev/null +++ b/elytra/src/plugin/mod.rs @@ -0,0 +1,3 @@ +mod provider; + +pub use provider::ServerProvider; diff --git a/elytra/src/plugin/provider.rs b/elytra/src/plugin/provider.rs new file mode 100644 index 0000000..d8cabfc --- /dev/null +++ b/elytra/src/plugin/provider.rs @@ -0,0 +1,6 @@ +pub trait ServerProvider { + fn id(&self) -> &str; + fn name(&self) -> &str; + fn version(&self) -> &str; + fn execute(&self); +} diff --git a/elytra/src/utils/mod.rs b/elytra/src/utils/mod.rs index c9137e8..f95ba33 100644 --- a/elytra/src/utils/mod.rs +++ b/elytra/src/utils/mod.rs @@ -2,3 +2,6 @@ pub mod modpack; // ModPackParse #[cfg(feature = "utils-mod")] pub mod parse; + +#[cfg(feature = "utils-plugin")] +pub mod plugin; diff --git a/elytra/src/utils/plugin/mod.rs b/elytra/src/utils/plugin/mod.rs new file mode 100644 index 0000000..22b5ae5 --- /dev/null +++ b/elytra/src/utils/plugin/mod.rs @@ -0,0 +1,44 @@ +use std::ffi::OsStr; + +use libloading::{Library, Symbol}; +use log::{debug, info}; +use thiserror::Error; + +use crate::plugin::ServerProvider; + +type PluginInit = fn() -> Box; + +#[derive(Debug, Error)] +pub enum PluginError { + #[error("while loading plugin: {0}")] + Load(#[from] libloading::Error), +} + +#[repr(transparent)] +pub struct Plugin { + plugin: Box, +} + +impl Drop for Plugin { + fn drop(&mut self) { + info!( + "Unloading plugin {} v{}", + self.plugin.id(), + self.plugin.version() + ); + } +} + +impl Plugin { + pub fn load>(path: P) -> Result { + debug!("Loading library {}", path.as_ref().to_string_lossy()); + let plugin = unsafe { Library::new(path.as_ref()) }?; + debug!("Loading init symbol"); + let plugin_init: Symbol = unsafe { plugin.get(b"init") }?; + + info!("Initializing plugin: {}", path.as_ref().to_string_lossy()); + let plugin = plugin_init(); + + Ok(Self { plugin }) + } +} diff --git a/mar/src/lib.rs b/mar/src/lib.rs index 5d48a2b..ca67991 100644 --- a/mar/src/lib.rs +++ b/mar/src/lib.rs @@ -5,5 +5,8 @@ pub mod types; #[cfg(feature = "all")] pub use repository::*; -#[cfg(any(feature = "types", feature = "type-maven-artifact"))] +#[cfg(all(feature = "types", feature = "type-maven-artifact"))] pub use types::MavenArtifactBuilder; + +#[cfg(all(not(feature = "types"), feature = "type-maven-artifact"))] +pub use types::MavenArtifact; diff --git a/mar/src/types.rs b/mar/src/types.rs index 04f2ed4..e64adff 100644 --- a/mar/src/types.rs +++ b/mar/src/types.rs @@ -1,9 +1,11 @@ use std::str::FromStr; +#[cfg(feature = "all")] use thiserror::Error; mod deserialize; pub use deserialize::*; +#[cfg(feature = "all")] #[derive(Default)] pub struct MavenArtifactBuilder { pub(crate) base_url: Option, @@ -20,6 +22,7 @@ pub struct MavenArtifact { pub(crate) version: Option, } +#[cfg(feature = "all")] #[derive(Debug, Error)] pub enum MavenArtifactParseError { #[error("input string is malformed: expected 3 semicolons, got {0}")] @@ -30,6 +33,7 @@ pub enum MavenArtifactParseError { Malformed, } +#[cfg(feature = "all")] impl FromStr for MavenArtifact { type Err = MavenArtifactParseError; @@ -75,6 +79,7 @@ impl MavenArtifact { } } +#[cfg(feature = "all")] #[derive(Debug, Error)] pub enum MavenArtifactBuildError { #[error("missing field: base_url. run with_base_url to fix")] @@ -85,6 +90,7 @@ pub enum MavenArtifactBuildError { ArtifactID, } +#[cfg(feature = "all")] impl MavenArtifactBuilder { pub fn with_base_url(mut self, base_url: T) -> Self { self.base_url = Some(base_url);