mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added a Global State API in plugins
This commit is contained in:
parent
c74cdaeb65
commit
6dffd1a9e2
@ -2,7 +2,22 @@ extern crate proc_macro;
|
|||||||
|
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{parse_macro_input, ItemFn};
|
use syn::{parse_macro_input, ItemFn, ItemStruct};
|
||||||
|
|
||||||
|
#[proc_macro_attribute]
|
||||||
|
pub fn global_state(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
|
let parsed = parse_macro_input!(item as ItemStruct);
|
||||||
|
let name = &parsed.ident;
|
||||||
|
let out: proc_macro2::TokenStream = quote! {
|
||||||
|
#parsed
|
||||||
|
type PLUGIN_STATE_TYPE = #name;
|
||||||
|
|
||||||
|
static mut PLUGIN_STATE: Option<PLUGIN_STATE_TYPE> = None;
|
||||||
|
|
||||||
|
static PLUGIN_STATE_GUARD: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false);
|
||||||
|
};
|
||||||
|
out.into()
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream {
|
pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
@ -13,20 +28,48 @@ pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream {
|
|||||||
let fn_args = sig.inputs; // comma separated args
|
let fn_args = sig.inputs; // comma separated args
|
||||||
let fn_return = sig.output; // comma separated args
|
let fn_return = sig.output; // comma separated args
|
||||||
|
|
||||||
let out: proc_macro2::TokenStream = quote! {
|
let out: proc_macro2::TokenStream = if fn_args.len() == 1 {
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
quote! {
|
||||||
#[no_mangle]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
pub fn #fn_name(intern__ptr: i64, intern__len: i64) -> i64 {
|
#[no_mangle]
|
||||||
let input = ::veloren_plugin_rt::read_input(intern__ptr as _,intern__len as _).unwrap();
|
pub fn #fn_name(intern__ptr: i64, intern__len: i64) -> i64 {
|
||||||
#[inline]
|
let input = ::veloren_plugin_rt::read_input(intern__ptr as _,intern__len as _).unwrap();
|
||||||
fn inner(#fn_args) #fn_return {
|
#[inline]
|
||||||
#fn_body
|
fn inner(#fn_args) #fn_return {
|
||||||
|
#fn_body
|
||||||
|
}
|
||||||
|
// Artificially force the event handler to be type-correct
|
||||||
|
fn force_event<E: ::veloren_plugin_rt::api::Event>(event: E, inner: fn(E) -> E::Response) -> E::Response {
|
||||||
|
inner(event)
|
||||||
|
}
|
||||||
|
::veloren_plugin_rt::write_output(&force_event(input, inner))
|
||||||
}
|
}
|
||||||
// Artificially force the event handler to be type-correct
|
}
|
||||||
fn force_event<E: ::veloren_plugin_rt::api::Event>(event: E, inner: fn(E) -> E::Response) -> E::Response {
|
} else {
|
||||||
inner(event)
|
quote! {
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn #fn_name(intern__ptr: i64, intern__len: i64) -> i64 {
|
||||||
|
let input = ::veloren_plugin_rt::read_input(intern__ptr as _,intern__len as _).unwrap();
|
||||||
|
#[inline]
|
||||||
|
fn inner(#fn_args) #fn_return {
|
||||||
|
#fn_body
|
||||||
|
}
|
||||||
|
// Artificially force the event handler to be type-correct
|
||||||
|
fn force_event<E: ::veloren_plugin_rt::api::Event>(event: E, inner: fn(E, &mut PLUGIN_STATE_TYPE) -> E::Response) -> E::Response {
|
||||||
|
//let mut plugin_state = PLUGIN_STATE.lock().unwrap();
|
||||||
|
unsafe {
|
||||||
|
assert_eq!(PLUGIN_STATE_GUARD.swap(true, std::sync::atomic::Ordering::Acquire), false);
|
||||||
|
if PLUGIN_STATE.is_none() {
|
||||||
|
PLUGIN_STATE = Some(PLUGIN_STATE_TYPE::default());
|
||||||
|
}
|
||||||
|
let out = inner(event, PLUGIN_STATE.as_mut().unwrap());
|
||||||
|
PLUGIN_STATE_GUARD.store(false, std::sync::atomic::Ordering::Release);
|
||||||
|
out
|
||||||
|
}
|
||||||
|
}
|
||||||
|
::veloren_plugin_rt::write_output(&force_event(input, inner))
|
||||||
}
|
}
|
||||||
::veloren_plugin_rt::write_output(&force_event(input, inner))
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
out.into()
|
out.into()
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
|
||||||
|
|
||||||
use veloren_plugin_rt::{
|
use veloren_plugin_rt::{
|
||||||
api::{event::*, Action, GameMode},
|
api::{event::*, Action, GameMode},
|
||||||
*,
|
*,
|
||||||
@ -31,11 +29,16 @@ pub fn on_command_testplugin(command: ChatCommandEvent) -> Result<Vec<String>, S
|
|||||||
)])
|
)])
|
||||||
}
|
}
|
||||||
|
|
||||||
static COUNTER: AtomicBool = AtomicBool::new(false);
|
#[global_state]
|
||||||
|
#[derive(Default)]
|
||||||
|
struct State {
|
||||||
|
counter: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[event_handler]
|
#[event_handler]
|
||||||
pub fn on_join(input: PlayerJoinEvent) -> PlayerJoinResult {
|
pub fn on_join(input: PlayerJoinEvent, state: &mut State) -> PlayerJoinResult {
|
||||||
if COUNTER.swap(!COUNTER.load(Ordering::SeqCst), Ordering::SeqCst) {
|
state.counter = !state.counter;
|
||||||
|
if !state.counter {
|
||||||
PlayerJoinResult::Kick(format!("You are a cheater {:?}", input))
|
PlayerJoinResult::Kick(format!("You are a cheater {:?}", input))
|
||||||
} else {
|
} else {
|
||||||
PlayerJoinResult::None
|
PlayerJoinResult::None
|
||||||
|
Loading…
Reference in New Issue
Block a user