Re-implement register event ffm
This commit is contained in:
parent
5e6de69913
commit
d382421557
@ -15,7 +15,6 @@ public class NativePatchBukkit {
|
||||
private static final Linker LINKER = Linker.nativeLinker();
|
||||
|
||||
private static MethodHandle sendMessageNative;
|
||||
private static MethodHandle registerEventNative;
|
||||
private static MethodHandle callEventNative;
|
||||
private static MethodHandle getLocationNative;
|
||||
private static MethodHandle getWorldNative;
|
||||
@ -184,7 +183,6 @@ public class NativePatchBukkit {
|
||||
*/
|
||||
public static void initCallbacks(
|
||||
long sendMessageAddr,
|
||||
long registerEventAddr,
|
||||
long callEventAddr,
|
||||
long getLocationAddr,
|
||||
long freeStringAddr,
|
||||
@ -199,17 +197,6 @@ public class NativePatchBukkit {
|
||||
FunctionDescriptor.ofVoid(ValueLayout.ADDRESS, ValueLayout.ADDRESS)
|
||||
);
|
||||
|
||||
// void rust_register_event(const char* event_type, const char* plugin_name, int32_t priority, bool blocking)
|
||||
registerEventNative = LINKER.downcallHandle(
|
||||
MemorySegment.ofAddress(registerEventAddr),
|
||||
FunctionDescriptor.ofVoid(
|
||||
ValueLayout.ADDRESS, // event_type string
|
||||
ValueLayout.ADDRESS, // plugin_name string
|
||||
ValueLayout.JAVA_INT, // priority ordinal
|
||||
ValueLayout.JAVA_BOOLEAN // blocking
|
||||
)
|
||||
);
|
||||
|
||||
// bool rust_call_event(const char* event_type, const char* event_data_json)
|
||||
// Returns true if Pumpkin handled it, false if unknown event type
|
||||
callEventNative = LINKER.downcallHandle(
|
||||
@ -294,28 +281,6 @@ public class NativePatchBukkit {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an event listener with Pumpkin's event system.
|
||||
*
|
||||
* Called by PatchBukkitEventManager when a plugin registers for an event.
|
||||
* Rust will create a PatchBukkitEventHandler that listens for the corresponding
|
||||
* Pumpkin event and dispatches back to Java when it fires.
|
||||
*
|
||||
* @param eventType Fully qualified Bukkit event class name (e.g. "org.bukkit.event.player.PlayerJoinEvent")
|
||||
* @param pluginName Name of the plugin registering this listener
|
||||
* @param priority Bukkit EventPriority ordinal (0=LOWEST through 5=MONITOR), clamped to 0-4 for Pumpkin
|
||||
* @param blocking Whether the handler should block
|
||||
*/
|
||||
public static void registerEvent(String eventType, String pluginName, int priority, boolean blocking) {
|
||||
try (Arena arena = Arena.ofConfined()) {
|
||||
MemorySegment eventTypeStr = arena.allocateFrom(eventType);
|
||||
MemorySegment pluginNameStr = arena.allocateFrom(pluginName);
|
||||
registerEventNative.invokeExact(eventTypeStr, pluginNameStr, priority, blocking);
|
||||
} catch (Throwable t) {
|
||||
throw new RuntimeException("Failed to register event: " + eventType + " for plugin " + pluginName, t);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a player's location by UUID.
|
||||
*
|
||||
|
||||
@ -19,6 +19,8 @@ import com.google.common.collect.Sets;
|
||||
import co.aikar.timings.TimedEventExecutor;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import patchbukkit.bridge.NativeBridgeFfi;
|
||||
import patchbukkit.common.RegisterEventRequest;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
@ -128,12 +130,8 @@ public class PatchBukkitEventManager {
|
||||
|
||||
for (RegisteredListener rl : entry.getValue()) {
|
||||
int priorityOrdinal = Math.min(rl.getPriority().ordinal(), 4);
|
||||
NativePatchBukkit.registerEvent(
|
||||
entry.getKey().getName(),
|
||||
plugin.getName(),
|
||||
priorityOrdinal,
|
||||
true
|
||||
);
|
||||
var request = RegisterEventRequest.newBuilder().setEventType(entry.getKey().getName()).setPluginName(plugin.getName()).setPriority(priorityOrdinal).setBlocking(true).build();
|
||||
NativeBridgeFfi.registerEvent(request);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -151,7 +149,8 @@ public class PatchBukkitEventManager {
|
||||
this.getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled));
|
||||
|
||||
int priorityOrdinal = Math.min(priority.ordinal(), 4);
|
||||
NativePatchBukkit.registerEvent(event.getName(), plugin.getName(), priorityOrdinal, true); // We default to having all events blocking.
|
||||
var request = RegisterEventRequest.newBuilder().setEventType(event.getName()).setPluginName(plugin.getName()).setPriority(priorityOrdinal).setBlocking(true).build();
|
||||
NativeBridgeFfi.registerEvent(request);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
@ -1,11 +1,14 @@
|
||||
syntax = "proto3";
|
||||
package patchbukkit.bridge;
|
||||
|
||||
import "google/protobuf/empty.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "patchbukkit/common/abilities.proto";
|
||||
import "patchbukkit/common/events.proto";
|
||||
import "patchbukkit/common/types.proto";
|
||||
|
||||
service NativeBridge {
|
||||
rpc GetAbilities(patchbukkit.common.UUID) returns (patchbukkit.common.Abilities);
|
||||
rpc SetAbilities(patchbukkit.common.SetAbilitiesRequest) returns (google.protobuf.BoolValue);
|
||||
rpc RegisterEvent(patchbukkit.common.RegisterEventRequest) returns (google.protobuf.Empty);
|
||||
}
|
||||
|
||||
15
proto/patchbukkit/common/events.proto
Normal file
15
proto/patchbukkit/common/events.proto
Normal file
@ -0,0 +1,15 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package patchbukkit.common;
|
||||
|
||||
import "patchbukkit/common/types.proto";
|
||||
|
||||
option java_multiple_files = true;
|
||||
option java_package = "patchbukkit.common";
|
||||
|
||||
message RegisterEventRequest {
|
||||
string event_type = 1;
|
||||
string plugin_name = 2;
|
||||
int32 priority = 3;
|
||||
bool blocking = 4;
|
||||
}
|
||||
@ -162,7 +162,6 @@ pub fn setup_protobufs(base: PathBuf) {
|
||||
config.service_generator(Box::new(generator));
|
||||
config.compile_protos(&paths, &[proto_path]).unwrap();
|
||||
|
||||
// Generate the shared initialization file
|
||||
let out_dir = std::env::var("OUT_DIR").unwrap();
|
||||
let init_path = PathBuf::from(&out_dir).join("ffi_init.rs");
|
||||
|
||||
|
||||
@ -7,22 +7,11 @@ use pumpkin_util::text::TextComponent;
|
||||
|
||||
use crate::events::handler::PatchBukkitEventHandler;
|
||||
use crate::java::native_callbacks::{CALLBACK_CONTEXT, utils::get_string};
|
||||
use crate::proto::patchbukkit::common::RegisterEventRequest;
|
||||
|
||||
pub extern "C" fn rust_register_event(
|
||||
event_type_ptr: *const c_char,
|
||||
plugin_name_ptr: *const c_char,
|
||||
priority: i32,
|
||||
blocking: bool,
|
||||
) {
|
||||
let event_type = get_string(event_type_ptr);
|
||||
let plugin_name = get_string(plugin_name_ptr);
|
||||
|
||||
let Some(ctx) = CALLBACK_CONTEXT.get() else {
|
||||
log::error!("CallbackContext not initialized when registering event");
|
||||
return;
|
||||
};
|
||||
|
||||
let pumpkin_priority = match priority {
|
||||
pub fn ffi_native_bridge_register_event_impl(request: RegisterEventRequest) -> Option<()> {
|
||||
let ctx = CALLBACK_CONTEXT.get()?;
|
||||
let pumpkin_priority = match request.priority {
|
||||
0 => EventPriority::Lowest,
|
||||
1 => EventPriority::Low,
|
||||
2 => EventPriority::Normal,
|
||||
@ -31,16 +20,19 @@ pub extern "C" fn rust_register_event(
|
||||
};
|
||||
|
||||
log::info!(
|
||||
"Plugin '{plugin_name}' registering listener for '{event_type}' (priority={priority:?}, blocking={blocking})"
|
||||
"Plugin '{}' registering listener for '{}' (priority={:?}, blocking={})",
|
||||
request.plugin_name,
|
||||
request.event_type,
|
||||
request.priority,
|
||||
request.blocking
|
||||
);
|
||||
|
||||
let command_tx = ctx.command_tx.clone();
|
||||
let context = ctx.plugin_context.clone();
|
||||
let event_type_owned = event_type;
|
||||
|
||||
tokio::task::block_in_place(|| {
|
||||
ctx.runtime.block_on(async {
|
||||
match event_type_owned.as_str() {
|
||||
match request.event_type.as_str() {
|
||||
"org.bukkit.event.player.PlayerJoinEvent" => {
|
||||
context
|
||||
.register_event::<
|
||||
@ -48,22 +40,25 @@ pub extern "C" fn rust_register_event(
|
||||
PatchBukkitEventHandler<pumpkin::plugin::player::player_join::PlayerJoinEvent>,
|
||||
>(
|
||||
Arc::new(PatchBukkitEventHandler::new(
|
||||
plugin_name.clone(),
|
||||
request.plugin_name.clone(),
|
||||
command_tx.clone(),
|
||||
)),
|
||||
pumpkin_priority,
|
||||
blocking,
|
||||
request.blocking,
|
||||
)
|
||||
.await;
|
||||
}
|
||||
_ => {
|
||||
log::warn!(
|
||||
"Unsupported Bukkit event type '{event_type_owned}' from plugin '{plugin_name}'"
|
||||
"Unsupported Bukkit event type '{}' from plugin '{}'",
|
||||
request.event_type, request.plugin_name
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub extern "C" fn rust_call_event(
|
||||
|
||||
@ -11,6 +11,8 @@ mod abilities;
|
||||
pub use abilities::*;
|
||||
|
||||
pub mod events;
|
||||
pub use events::*;
|
||||
|
||||
pub mod location;
|
||||
pub mod memory;
|
||||
pub mod message;
|
||||
@ -66,7 +68,6 @@ pub extern "C" fn rust_free_bytes(ptr: *mut u8, len: u32) {
|
||||
|
||||
pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
||||
let send_message_addr = message::rust_send_message as *const () as i64;
|
||||
let register_event_addr = events::rust_register_event as *const () as i64;
|
||||
let call_event_addr = events::rust_call_event as *const () as i64;
|
||||
let get_location_addr = location::rust_get_location as *const () as i64;
|
||||
let free_string_addr = memory::rust_free_string as *const () as i64;
|
||||
@ -81,7 +82,6 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
|
||||
"initCallbacks",
|
||||
&[
|
||||
InvocationArg::try_from(send_message_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(register_event_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(call_event_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(get_location_addr)?.into_primitive()?,
|
||||
InvocationArg::try_from(free_string_addr)?.into_primitive()?,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user