Let events modify
This commit is contained in:
parent
a1abcfa8fd
commit
3f4db9f5b4
@ -1,57 +1,89 @@
|
|||||||
package org.patchbukkit.events;
|
package org.patchbukkit.events;
|
||||||
|
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||||
|
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import patchbukkit.common.UUID;
|
||||||
|
import patchbukkit.events.Event;
|
||||||
|
import patchbukkit.events.FireEventResponse;
|
||||||
|
import patchbukkit.events.PlayerJoinEvent;
|
||||||
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class PatchBukkitEventFactory {
|
public class PatchBukkitEventFactory {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger("PatchBukkit");
|
private static final Logger LOGGER = Logger.getLogger("PatchBukkit");
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PlayerJoinEvent createPlayerJoinEvent(@NotNull String playerUuid, @NotNull String joinMessage) {
|
public static org.bukkit.event.Event createEventFromBytes(byte[] data) {
|
||||||
Player player = getPlayer(playerUuid);
|
try {
|
||||||
if (player == null) return null;
|
Event event = Event.parseFrom(data);
|
||||||
|
return createEvent(event);
|
||||||
Component joinMessageComponent = Component.translatable("multiplayer.player.joined",
|
} catch (InvalidProtocolBufferException e) {
|
||||||
Component.text(joinMessage));
|
LOGGER.severe("Failed to parse Event: " + e.getMessage());
|
||||||
|
return null;
|
||||||
return new PlayerJoinEvent(player, joinMessageComponent);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static PlayerQuitEvent createPlayerQuitEvent(@NotNull String playerUuid) {
|
public static org.bukkit.event.Event createEvent(@NotNull Event event) {
|
||||||
Player player = getPlayer(playerUuid);
|
Event.DataCase dataCase = event.getDataCase();
|
||||||
if (player == null) return null;
|
|
||||||
|
|
||||||
Component quitMessage = Component.translatable("multiplayer.player.left",
|
return switch (dataCase) {
|
||||||
Component.text(player.getName()));
|
case PLAYER_JOIN -> {
|
||||||
|
PlayerJoinEvent joinEvent = event.getPlayerJoin();
|
||||||
|
Player player = getPlayer(joinEvent.getPlayerUuid().getValue());
|
||||||
|
if (player == null) yield null;
|
||||||
|
|
||||||
return new PlayerQuitEvent(player, quitMessage, PlayerQuitEvent.QuitReason.DISCONNECTED);
|
Component joinMessage = GsonComponentSerializer.gson().deserialize(joinEvent.getJoinMessage());
|
||||||
|
yield new org.bukkit.event.player.PlayerJoinEvent(player, joinMessage);
|
||||||
|
}
|
||||||
|
case DATA_NOT_SET -> {
|
||||||
|
LOGGER.warning("EventFactory: Received Event with no data");
|
||||||
|
yield null;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@NotNull
|
||||||
* Check if an event implements Cancellable.
|
public static byte[] toFireEventResponse(@NotNull org.bukkit.event.Event event) {
|
||||||
*/
|
boolean cancelled = event instanceof org.bukkit.event.Cancellable c && c.isCancelled();
|
||||||
public static boolean isCancellable(@NotNull Event event) {
|
|
||||||
|
FireEventResponse.Builder builder = FireEventResponse.newBuilder()
|
||||||
|
.setCancelled(cancelled);
|
||||||
|
|
||||||
|
Event.Builder eventBuilder = Event.newBuilder();
|
||||||
|
|
||||||
|
if (event instanceof org.bukkit.event.player.PlayerJoinEvent joinEvent) {
|
||||||
|
String joinMessage = GsonComponentSerializer.gson().serialize(joinEvent.joinMessage());
|
||||||
|
|
||||||
|
eventBuilder.setPlayerJoin(
|
||||||
|
PlayerJoinEvent.newBuilder()
|
||||||
|
.setPlayerUuid(UUID.newBuilder()
|
||||||
|
.setValue(joinEvent.getPlayer().getUniqueId().toString())
|
||||||
|
.build())
|
||||||
|
.setJoinMessage(joinMessage)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.setData(eventBuilder.build());
|
||||||
|
|
||||||
|
return builder.build().toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isCancellable(@NotNull org.bukkit.event.Event event) {
|
||||||
return event instanceof org.bukkit.event.Cancellable;
|
return event instanceof org.bukkit.event.Cancellable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a player by UUID string. Returns null with a warning if not found.
|
|
||||||
*/
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private static Player getPlayer(@NotNull String uuidStr) {
|
private static Player getPlayer(@NotNull String uuidStr) {
|
||||||
try {
|
try {
|
||||||
UUID uuid = UUID.fromString(uuidStr);
|
java.util.UUID uuid = java.util.UUID.fromString(uuidStr);
|
||||||
Player player = Bukkit.getServer().getPlayer(uuid);
|
Player player = Bukkit.getServer().getPlayer(uuid);
|
||||||
if (player == null) {
|
if (player == null) {
|
||||||
LOGGER.warning("EventFactory: Player not found for UUID " + uuidStr);
|
LOGGER.warning("EventFactory: Player not found for UUID " + uuidStr);
|
||||||
|
|||||||
@ -51,10 +51,12 @@ public class PatchBukkitEventManager {
|
|||||||
switch (event.getEventName()) {
|
switch (event.getEventName()) {
|
||||||
case "org.bukkit.event.player.PlayerJoinEvent":
|
case "org.bukkit.event.player.PlayerJoinEvent":
|
||||||
var castedEvent = (org.bukkit.event.player.PlayerJoinEvent) event;
|
var castedEvent = (org.bukkit.event.player.PlayerJoinEvent) event;
|
||||||
request.setPlayerJoin(
|
request.setEvent(
|
||||||
|
patchbukkit.events.Event.newBuilder().setPlayerJoin(
|
||||||
PlayerJoinEvent.newBuilder()
|
PlayerJoinEvent.newBuilder()
|
||||||
.setJoinMessage(castedEvent.joinMessage().toString())
|
.setJoinMessage(castedEvent.joinMessage().toString())
|
||||||
.setPlayerUuid(BridgeUtils.convertUuid(castedEvent.getPlayer().getUniqueId()))
|
.setPlayerUuid(BridgeUtils.convertUuid(castedEvent.getPlayer().getUniqueId())).build()
|
||||||
|
).build()
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
package org.patchbukkit.events;
|
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
public class PatchBukkitEventSerializer {
|
|
||||||
public static String serialize(Event event) {
|
|
||||||
JsonObject json = new JsonObject();
|
|
||||||
|
|
||||||
if (event instanceof PlayerJoinEvent joinEvent) {
|
|
||||||
var joinMessage = joinEvent.joinMessage();
|
|
||||||
if (joinMessage != null) {
|
|
||||||
json.addProperty("playerUuid", joinEvent.getPlayer().getUniqueId().toString());
|
|
||||||
json.addProperty("joinMessage", joinMessage.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -8,6 +8,12 @@ import "patchbukkit/events/player_events.proto";
|
|||||||
option java_multiple_files = true;
|
option java_multiple_files = true;
|
||||||
option java_package = "patchbukkit.events";
|
option java_package = "patchbukkit.events";
|
||||||
|
|
||||||
|
message Event {
|
||||||
|
oneof data {
|
||||||
|
PlayerJoinEvent player_join = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
message RegisterEventRequest {
|
message RegisterEventRequest {
|
||||||
string event_type = 1;
|
string event_type = 1;
|
||||||
string plugin_name = 2;
|
string plugin_name = 2;
|
||||||
@ -16,11 +22,14 @@ message RegisterEventRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message CallEventRequest {
|
message CallEventRequest {
|
||||||
oneof event_data {
|
Event event = 1;
|
||||||
PlayerJoinEvent player_join = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message CallEventResponse {
|
message CallEventResponse {
|
||||||
bool handled = 1;
|
bool handled = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message FireEventResponse {
|
||||||
|
bool cancelled = 1;
|
||||||
|
Event data = 2;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use pumpkin::entity::player::Player;
|
use pumpkin::entity::player::Player;
|
||||||
@ -8,37 +9,62 @@ use pumpkin_api_macros::with_runtime;
|
|||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
|
|
||||||
use crate::java::jvm::commands::JvmCommand;
|
use crate::java::jvm::commands::JvmCommand;
|
||||||
|
use crate::proto::patchbukkit::common::Uuid;
|
||||||
|
use crate::proto::patchbukkit::events::event::Data;
|
||||||
|
use crate::proto::patchbukkit::events::{Event, PlayerJoinEvent};
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub struct EventContext {
|
||||||
pub enum PatchBukkitEvent {
|
pub server: Arc<Server>,
|
||||||
PlayerJoinEvent {
|
pub player: Option<Arc<Player>>,
|
||||||
server: Arc<Server>,
|
}
|
||||||
player: Arc<Player>,
|
|
||||||
join_message: String,
|
pub struct JvmEventPayload {
|
||||||
|
pub event: Event,
|
||||||
|
pub context: EventContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait PatchBukkitEvent {
|
||||||
|
fn to_payload(&self, server: Arc<Server>) -> JvmEventPayload;
|
||||||
|
fn apply_modifications(&mut self, server: &Arc<Server>, data: Data) -> Option<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PatchBukkitEvent for pumpkin::plugin::player::player_join::PlayerJoinEvent {
|
||||||
|
fn to_payload(&self, server: Arc<Server>) -> JvmEventPayload {
|
||||||
|
JvmEventPayload {
|
||||||
|
event: Event {
|
||||||
|
data: Some(Data::PlayerJoin(PlayerJoinEvent {
|
||||||
|
player_uuid: Some(Uuid {
|
||||||
|
value: self.player.gameprofile.id.to_string(),
|
||||||
|
}),
|
||||||
|
join_message: serde_json::to_string(&self.join_message).unwrap(),
|
||||||
|
})),
|
||||||
},
|
},
|
||||||
}
|
context: EventContext {
|
||||||
|
|
||||||
pub trait IntoEventData {
|
|
||||||
fn get_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IntoEventData for pumpkin::plugin::player::player_join::PlayerJoinEvent {
|
|
||||||
fn get_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent {
|
|
||||||
PatchBukkitEvent::PlayerJoinEvent {
|
|
||||||
server,
|
server,
|
||||||
player: self.player.clone(),
|
player: Some(self.player.clone()),
|
||||||
join_message: self.join_message.clone().get_text(),
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apply_modifications(&mut self, server: &Arc<Server>, data: Data) -> Option<()> {
|
||||||
|
match data {
|
||||||
|
Data::PlayerJoin(event) => {
|
||||||
|
self.join_message = serde_json::from_str(&event.join_message).ok()?;
|
||||||
|
server.get_player_by_uuid(uuid::Uuid::from_str(&event.player_uuid?.value).ok()?)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PatchBukkitEventHandler<E: IntoEventData> {
|
pub struct PatchBukkitEventHandler<E: PatchBukkitEvent> {
|
||||||
plugin_name: String,
|
plugin_name: String,
|
||||||
command_tx: mpsc::Sender<JvmCommand>,
|
command_tx: mpsc::Sender<JvmCommand>,
|
||||||
_phantom: PhantomData<E>,
|
_phantom: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E: IntoEventData> PatchBukkitEventHandler<E> {
|
impl<E: PatchBukkitEvent> PatchBukkitEventHandler<E> {
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn new(plugin_name: String, command_tx: mpsc::Sender<JvmCommand>) -> Self {
|
pub const fn new(plugin_name: String, command_tx: mpsc::Sender<JvmCommand>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -52,7 +78,7 @@ impl<E: IntoEventData> PatchBukkitEventHandler<E> {
|
|||||||
#[with_runtime(global)]
|
#[with_runtime(global)]
|
||||||
impl<E> EventHandler<E> for PatchBukkitEventHandler<E>
|
impl<E> EventHandler<E> for PatchBukkitEventHandler<E>
|
||||||
where
|
where
|
||||||
E: IntoEventData + Payload + Cancellable + 'static,
|
E: PatchBukkitEvent + Payload + Cancellable + 'static,
|
||||||
{
|
{
|
||||||
fn handle_blocking<'a>(
|
fn handle_blocking<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
@ -65,7 +91,7 @@ where
|
|||||||
let (tx, rx) = oneshot::channel();
|
let (tx, rx) = oneshot::channel();
|
||||||
if let Err(e) = command_tx
|
if let Err(e) = command_tx
|
||||||
.send(JvmCommand::FireEvent {
|
.send(JvmCommand::FireEvent {
|
||||||
patchbukkit_event: event.get_patch_bukkit_event(server.clone()),
|
payload: event.to_payload(server.clone()),
|
||||||
respond_to: tx,
|
respond_to: tx,
|
||||||
plugin: self.plugin_name.clone(),
|
plugin: self.plugin_name.clone(),
|
||||||
})
|
})
|
||||||
@ -76,11 +102,9 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
match rx.await {
|
match rx.await {
|
||||||
Ok(cancelled) => {
|
Ok(response) => {
|
||||||
if cancelled {
|
event.set_cancelled(response.cancelled);
|
||||||
log::debug!("Event was cancelled by a Java plugin");
|
event.apply_modifications(server, response.data.unwrap().data.unwrap());
|
||||||
event.set_cancelled(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
log::warn!("JVM worker dropped response channel for event");
|
log::warn!("JVM worker dropped response channel for event");
|
||||||
|
|||||||
@ -6,7 +6,10 @@ use pumpkin_protocol::java::client::play::CommandSuggestion;
|
|||||||
use tokio::sync::{mpsc, oneshot};
|
use tokio::sync::{mpsc, oneshot};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::{commands::SimpleCommandSender, events::handler::PatchBukkitEvent};
|
use crate::{
|
||||||
|
commands::SimpleCommandSender, events::handler::JvmEventPayload,
|
||||||
|
proto::patchbukkit::events::FireEventResponse,
|
||||||
|
};
|
||||||
|
|
||||||
pub enum LoadPluginResult {
|
pub enum LoadPluginResult {
|
||||||
SuccessfullyLoadedSpigot,
|
SuccessfullyLoadedSpigot,
|
||||||
@ -43,9 +46,9 @@ pub enum JvmCommand {
|
|||||||
respond_to: oneshot::Sender<Result<()>>,
|
respond_to: oneshot::Sender<Result<()>>,
|
||||||
},
|
},
|
||||||
FireEvent {
|
FireEvent {
|
||||||
patchbukkit_event: PatchBukkitEvent,
|
payload: JvmEventPayload,
|
||||||
plugin: String,
|
plugin: String,
|
||||||
respond_to: oneshot::Sender<bool>, // true = cancelled
|
respond_to: oneshot::Sender<FireEventResponse>, // true = cancelled
|
||||||
},
|
},
|
||||||
TriggerCommand {
|
TriggerCommand {
|
||||||
full_command: String,
|
full_command: String,
|
||||||
|
|||||||
@ -4,13 +4,16 @@ use j4rs::{InvocationArg, Jvm, JvmBuilder};
|
|||||||
use pumpkin::plugin::Context;
|
use pumpkin::plugin::Context;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::java::{
|
use crate::{
|
||||||
|
java::{
|
||||||
jar::read_configs_from_jar,
|
jar::read_configs_from_jar,
|
||||||
jvm::commands::{JvmCommand, LoadPluginResult},
|
jvm::commands::{JvmCommand, LoadPluginResult},
|
||||||
native_callbacks::{init_callback_context, initialize_callbacks},
|
native_callbacks::{init_callback_context, initialize_callbacks},
|
||||||
plugin::{
|
plugin::{
|
||||||
command_manager::CommandManager, event_manager::EventManager, manager::PluginManager,
|
command_manager::CommandManager, event_manager::EventManager, manager::PluginManager,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
proto::patchbukkit::events::FireEventResponse,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct JvmWorker {
|
pub struct JvmWorker {
|
||||||
@ -138,22 +141,22 @@ impl JvmWorker {
|
|||||||
JvmCommand::FireEvent {
|
JvmCommand::FireEvent {
|
||||||
respond_to,
|
respond_to,
|
||||||
plugin,
|
plugin,
|
||||||
patchbukkit_event,
|
payload,
|
||||||
} => {
|
} => {
|
||||||
let jvm = match self.jvm {
|
let jvm = match self.jvm {
|
||||||
Some(ref jvm) => jvm,
|
Some(ref jvm) => jvm,
|
||||||
None => &Jvm::attach_thread().unwrap(),
|
None => &Jvm::attach_thread().unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let cancelled =
|
let original_event = payload.event.clone();
|
||||||
match self
|
let cancelled = match self.event_manager.fire_event(jvm, payload, plugin) {
|
||||||
.event_manager
|
|
||||||
.fire_event(jvm, patchbukkit_event, plugin)
|
|
||||||
{
|
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to fire event: {e}");
|
log::error!("Failed to fire event: {e}");
|
||||||
false
|
FireEventResponse {
|
||||||
|
cancelled: false,
|
||||||
|
data: Some(original_event),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use pumpkin_util::text::TextComponent;
|
|||||||
|
|
||||||
use crate::events::handler::PatchBukkitEventHandler;
|
use crate::events::handler::PatchBukkitEventHandler;
|
||||||
use crate::java::native_callbacks::CALLBACK_CONTEXT;
|
use crate::java::native_callbacks::CALLBACK_CONTEXT;
|
||||||
use crate::proto::patchbukkit::events::call_event_request::EventData;
|
use crate::proto::patchbukkit::events::event::Data;
|
||||||
use crate::proto::patchbukkit::events::{
|
use crate::proto::patchbukkit::events::{
|
||||||
CallEventRequest, CallEventResponse, RegisterEventRequest,
|
CallEventRequest, CallEventResponse, RegisterEventRequest,
|
||||||
};
|
};
|
||||||
@ -65,15 +65,15 @@ pub fn ffi_native_bridge_register_event_impl(request: RegisterEventRequest) -> O
|
|||||||
|
|
||||||
pub fn ffi_native_bridge_call_event_impl(request: CallEventRequest) -> Option<CallEventResponse> {
|
pub fn ffi_native_bridge_call_event_impl(request: CallEventRequest) -> Option<CallEventResponse> {
|
||||||
let ctx = CALLBACK_CONTEXT.get()?;
|
let ctx = CALLBACK_CONTEXT.get()?;
|
||||||
let event_data = request.event_data?;
|
let event = request.event?;
|
||||||
log::debug!("Java calling event {:?}", event_data);
|
log::debug!("Java calling event {:?}", event);
|
||||||
|
|
||||||
let context = ctx.plugin_context.clone();
|
let context = ctx.plugin_context.clone();
|
||||||
|
|
||||||
let handled = tokio::task::block_in_place(|| {
|
let handled = tokio::task::block_in_place(|| {
|
||||||
ctx.runtime.block_on(async {
|
ctx.runtime.block_on(async {
|
||||||
match event_data {
|
match event.data? {
|
||||||
EventData::PlayerJoin(player_join_event_data) => {
|
Data::PlayerJoin(player_join_event_data) => {
|
||||||
let uuid =
|
let uuid =
|
||||||
uuid::Uuid::parse_str(&player_join_event_data.player_uuid?.value).ok()?;
|
uuid::Uuid::parse_str(&player_join_event_data.player_uuid?.value).ok()?;
|
||||||
let player = context.server.get_player_by_uuid(uuid)?;
|
let player = context.server.get_player_by_uuid(uuid)?;
|
||||||
|
|||||||
@ -2,9 +2,13 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use j4rs::{Instance, InvocationArg, Jvm};
|
use j4rs::{Instance, InvocationArg, Jvm};
|
||||||
|
use prost::Message;
|
||||||
use pumpkin::{entity::player::Player, server::Server};
|
use pumpkin::{entity::player::Player, server::Server};
|
||||||
|
|
||||||
use crate::events::handler::PatchBukkitEvent;
|
use crate::{
|
||||||
|
events::handler::JvmEventPayload,
|
||||||
|
proto::patchbukkit::events::{FireEventResponse, event::Data},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct EventManager {}
|
pub struct EventManager {}
|
||||||
|
|
||||||
@ -23,61 +27,71 @@ impl EventManager {
|
|||||||
pub fn fire_event(
|
pub fn fire_event(
|
||||||
&self,
|
&self,
|
||||||
jvm: &Jvm,
|
jvm: &Jvm,
|
||||||
event: PatchBukkitEvent,
|
payload: JvmEventPayload,
|
||||||
plugin_name: String,
|
plugin_name: String,
|
||||||
) -> Result<bool> {
|
) -> Result<FireEventResponse> {
|
||||||
let server = jvm.invoke_static("org.bukkit.Bukkit", "getServer", InvocationArg::empty())?;
|
let server = jvm.invoke_static("org.bukkit.Bukkit", "getServer", InvocationArg::empty())?;
|
||||||
let patch_server = jvm.cast(&server, "org.patchbukkit.PatchBukkitServer")?;
|
let patch_server = jvm.cast(&server, "org.patchbukkit.PatchBukkitServer")?;
|
||||||
let event_manager = jvm.invoke(&patch_server, "getEventManager", InvocationArg::empty())?;
|
let event_manager = jvm.invoke(&patch_server, "getEventManager", InvocationArg::empty())?;
|
||||||
|
|
||||||
let j_event = match event {
|
if let Some(ref event) = payload.event.data
|
||||||
PatchBukkitEvent::PlayerJoinEvent {
|
&& matches!(event, Data::PlayerJoin(_))
|
||||||
server,
|
&& let Some(ref player) = payload.context.player
|
||||||
player,
|
{
|
||||||
join_message,
|
Self::register_player(jvm, &patch_server, player, &payload.context.server)?;
|
||||||
} => {
|
}
|
||||||
Self::register_player(jvm, &patch_server, &player, &server)?;
|
|
||||||
jvm.invoke_static(
|
let bytes = payload.event.encode_to_vec();
|
||||||
"org.patchbukkit.events.PatchBukkitEventFactory",
|
let j_bytes = jvm.create_java_array(
|
||||||
"createPlayerJoinEvent",
|
"byte",
|
||||||
&[
|
&bytes
|
||||||
InvocationArg::try_from(player.gameprofile.id.to_string())?,
|
.iter()
|
||||||
InvocationArg::try_from(join_message)?,
|
.map(|&b| {
|
||||||
],
|
InvocationArg::try_from(b as i8)
|
||||||
)?
|
.unwrap()
|
||||||
|
.into_primitive()
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let j_event = jvm.invoke_static(
|
||||||
|
"org.patchbukkit.events.PatchBukkitEventFactory",
|
||||||
|
"createEventFromBytes",
|
||||||
|
&[InvocationArg::from(j_bytes)],
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let is_null: bool = jvm.to_rust(jvm.invoke_static(
|
||||||
|
"java.util.Objects",
|
||||||
|
"isNull",
|
||||||
|
&[InvocationArg::from(jvm.clone_instance(&j_event)?)],
|
||||||
|
)?)?;
|
||||||
|
|
||||||
|
if is_null {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"Failed to create event - factory returned null"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
let j_event_for_fire = jvm.clone_instance(&j_event)?;
|
|
||||||
jvm.invoke(
|
jvm.invoke(
|
||||||
&event_manager,
|
&event_manager,
|
||||||
"fireEvent",
|
"fireEvent",
|
||||||
&[
|
&[
|
||||||
InvocationArg::from(j_event_for_fire),
|
InvocationArg::from(jvm.clone_instance(&j_event)?),
|
||||||
InvocationArg::try_from(plugin_name)?,
|
InvocationArg::try_from(plugin_name)?,
|
||||||
],
|
],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let is_cancellable: bool = jvm.to_rust(jvm.invoke_static(
|
let response_bytes: Vec<i8> = jvm.to_rust(jvm.invoke_static(
|
||||||
"org.patchbukkit.events.PatchBukkitEventFactory",
|
"org.patchbukkit.events.PatchBukkitEventFactory",
|
||||||
"isCancellable",
|
"toFireEventResponse",
|
||||||
&[InvocationArg::from(jvm.clone_instance(&j_event)?)],
|
&[InvocationArg::from(j_event)],
|
||||||
)?)?;
|
)?)?;
|
||||||
|
|
||||||
let cancelled = if is_cancellable {
|
let response_bytes: Vec<u8> = response_bytes.iter().map(|&b| b as u8).collect();
|
||||||
match jvm.invoke(
|
let response = FireEventResponse::decode(response_bytes.as_slice())?;
|
||||||
&jvm.clone_instance(&j_event)?,
|
|
||||||
"isCancelled",
|
|
||||||
InvocationArg::empty(),
|
|
||||||
) {
|
|
||||||
Ok(instance) => jvm.to_rust::<bool>(instance).unwrap_or(false),
|
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(cancelled)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_player(
|
pub fn register_player(
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user