From 87bf7654d2c65dbd44f9cb1354d1a302138d9386 Mon Sep 17 00:00:00 2001 From: Jady Wright Date: Fri, 20 Sep 2024 00:24:01 -0400 Subject: [PATCH] Start to figure out modding Currently this doesn't work. The TypeIds of things in different binaries are different, so all the bevy reflecty things break. Depends on: - https://github.com/bevyengine/bevy/pull/13080 - https://github.com/bevyengine/bevy/discussions/8390 - https://github.com/bevyengine/bevy/issues/32 --- Cargo.toml | 2 +- mod_bin/Cargo.toml | 11 ++++++++++ mod_bin/src/main.rs | 50 +++++++++++++++++++++++++++++++++++++++++++++ mod_lib/Cargo.toml | 11 ++++++++++ mod_lib/src/lib.rs | 31 ++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 mod_bin/Cargo.toml create mode 100644 mod_bin/src/main.rs create mode 100644 mod_lib/Cargo.toml create mode 100644 mod_lib/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 5df15bb0..007de59f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["sbepis", "marching_cubes", "jack_noir"] +members = ["sbepis", "marching_cubes", "jack_noir", "mod_lib", "mod_bin"] default-members = ["sbepis"] resolver = "2" diff --git a/mod_bin/Cargo.toml b/mod_bin/Cargo.toml new file mode 100644 index 00000000..641c843f --- /dev/null +++ b/mod_bin/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mod_bin" +version = "0.1.0" +edition = "2021" + +[dependencies] +bevy_dylib = "0.14.2" +bevy = { version = "0.14.2", features = ["dynamic_linking"] } +bevy-inspector-egui = "0.26.0" +bevy_mod_debugdump = "0.11.1" +libloading = "0.8.5" diff --git a/mod_bin/src/main.rs b/mod_bin/src/main.rs new file mode 100644 index 00000000..e4e9f20a --- /dev/null +++ b/mod_bin/src/main.rs @@ -0,0 +1,50 @@ +#![allow(deprecated)] + +use std::any::TypeId; +use std::ffi::OsStr; + +use bevy::prelude::*; +use libloading::{Library, Symbol}; + +fn main() { + let mut app = App::new(); + app.add_plugins(( + DefaultPlugins, + bevy_inspector_egui::quick::WorldInspectorPlugin::new(), + )); + unsafe { + // app.load_plugin("./target/debug/libmod_lib.so"); + + match dynamically_load_plugin("./target/debug/libmod_lib.so") { + Ok((lib, plugin)) => { + info!( + "Plugin loaded! {:?} {:?}", + app.world(), + TypeId::of::() + ); + std::mem::forget(lib); + plugin.build(&mut app); + } + Err(e) => error!("Failed to load plugin: {:?}", e), + } + } + bevy_mod_debugdump::print_schedule_graph(&mut app, Update); + app.run(); +} + +pub unsafe fn dynamically_load_plugin>( + path: P, +) -> Result<(Library, Box), libloading::Error> { + // SAFETY: Caller must follow the safety requirements of Library::new. + let lib = unsafe { Library::new(path)? }; + + // SAFETY: Loaded plugins are not allowed to specify `_bevy_create_plugin` symbol manually, but + // must instead automatically generate it through `DynamicPlugin`. + let func: Symbol *mut dyn Plugin> = unsafe { lib.get(b"_bevy_create_plugin")? }; + + // SAFETY: `func` is automatically generated and is guaranteed to return a pointer created using + // `Box::into_raw`. + let plugin = unsafe { Box::from_raw(func()) }; + + Ok((lib, plugin)) +} diff --git a/mod_lib/Cargo.toml b/mod_lib/Cargo.toml new file mode 100644 index 00000000..1e95fe07 --- /dev/null +++ b/mod_lib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "mod_lib" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["dylib"] + +[dependencies] +bevy_dylib = "0.14.2" +bevy = { version = "0.14.2", features = ["dynamic_linking"] } diff --git a/mod_lib/src/lib.rs b/mod_lib/src/lib.rs new file mode 100644 index 00000000..e9ef2cdb --- /dev/null +++ b/mod_lib/src/lib.rs @@ -0,0 +1,31 @@ +#![allow(deprecated)] + +use bevy::prelude::*; +use std::any::TypeId; + +#[no_mangle] +pub fn _bevy_create_plugin() -> *mut dyn Plugin { + // make sure the constructor is the correct type. + let object = ModLib {}; + let boxed = Box::new(object); + Box::into_raw(boxed) +} + +pub struct ModLib; + +impl Plugin for ModLib { + fn build(&self, app: &mut App) { + println!( + "ModLib loaded! {:?} {:?}", + app.world(), + TypeId::of::() + ); + app.add_systems(Update, setup); + println!("ModLib system added!"); + } +} + +fn setup(mut commands: Commands) { + println!("Hello from mod_lib!"); + commands.spawn(Name::new("Sample modded entity")); +}