Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pumpkin-api-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ pub fn plugin_impl(_attr: TokenStream, item: TokenStream) -> TokenStream {
description: env!("CARGO_PKG_DESCRIPTION"),
};

#[unsafe(no_mangle)]
pub static PUMPKIN_API_VERSION: u32 = pumpkin::plugin::PLUGIN_API_VERSION;

#input_struct

impl pumpkin::plugin::Plugin for #struct_ident {
Expand Down
13 changes: 13 additions & 0 deletions pumpkin/src/plugin/loader/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,17 @@ pub enum LoaderError {

#[error("Invalid loader data")]
InvalidLoaderData,

#[error(
"Plugin was built for an incompatible API version. Please rebuild it against this Pumpkin build."
)]
ApiVersionMissing,

#[error(
"Plugin API version mismatch (plugin {plugin_version}, server {server_version}). Please rebuild it against this Pumpkin build."
)]
ApiVersionMismatch {
plugin_version: u32,
server_version: u32,
},
}
20 changes: 19 additions & 1 deletion pumpkin/src/plugin/loader/native.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use std::any::Any;

use libloading::Library;

use crate::plugin::loader::{PluginLoadFuture, PluginUnloadFuture};
use crate::plugin::{
PLUGIN_API_VERSION,
loader::{PluginLoadFuture, PluginUnloadFuture},
};

use super::{LoaderError, Path, Plugin, PluginLoader, PluginMetadata};

Expand All @@ -16,6 +19,21 @@ impl PluginLoader for NativePluginLoader {
let library = unsafe { Library::new(&path) }
.map_err(|e| LoaderError::LibraryLoad(e.to_string()))?;

// Ensure this plugin was built against a compatible Pumpkin plugin API version
let plugin_api_version = unsafe {
match library.get::<*const u32>(b"PUMPKIN_API_VERSION") {
Ok(symbol) => **symbol,
Err(_) => return Err(LoaderError::ApiVersionMissing),
}
};

if plugin_api_version != PLUGIN_API_VERSION {
return Err(LoaderError::ApiVersionMismatch {
plugin_version: plugin_api_version,
server_version: PLUGIN_API_VERSION,
});
}

// 2. Extract Metadata (METADATA)
let metadata = unsafe {
&**library
Expand Down
4 changes: 4 additions & 0 deletions pumpkin/src/plugin/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ pub use api::*;

type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

/// Bump this whenever the public plugin API or any event layout changes in a way
/// that makes old binary plugins incompatible.
pub const PLUGIN_API_VERSION: u32 = 2;

/// A trait for handling events dynamically.
///
/// This trait allows for handling events of any type that implements the `Event` trait.
Expand Down