Clean up codebase

This commit is contained in:
Bjorn Beishline 2026-01-31 05:39:25 -07:00
parent b4521e1c8e
commit 609f894c56
8 changed files with 141 additions and 136 deletions

View File

@ -23,18 +23,18 @@ impl CommandExecutor for JavaCommandExecutor {
fn execute<'a>( fn execute<'a>(
&'a self, &'a self,
sender: &'a pumpkin::command::CommandSender, sender: &'a pumpkin::command::CommandSender,
server: &'a pumpkin::server::Server, _server: &'a pumpkin::server::Server,
args: &'a pumpkin::command::args::ConsumedArgs<'a>, _args: &'a pumpkin::command::args::ConsumedArgs<'a>,
) -> pumpkin::command::CommandResult<'a> { ) -> pumpkin::command::CommandResult<'a> {
Box::pin(async move { Box::pin(async move {
let (tx, rx) = oneshot::channel(); let (tx, _rx) = oneshot::channel();
let sender = match sender { let sender = match sender {
pumpkin::command::CommandSender::Rcon(mutex) => todo!(), pumpkin::command::CommandSender::Rcon(_mutex) => todo!(),
pumpkin::command::CommandSender::Console => SimpleCommandSender::Console, pumpkin::command::CommandSender::Console => SimpleCommandSender::Console,
pumpkin::command::CommandSender::Player(player) => { pumpkin::command::CommandSender::Player(player) => {
SimpleCommandSender::Player(player.gameprofile.id.to_string()) SimpleCommandSender::Player(player.gameprofile.id.to_string())
} }
pumpkin::command::CommandSender::CommandBlock(block_entity, world) => todo!(), pumpkin::command::CommandSender::CommandBlock(_block_entity, _world) => todo!(),
}; };
self.command_tx self.command_tx
.send(JvmCommand::TriggerCommand { .send(JvmCommand::TriggerCommand {

View File

@ -16,7 +16,6 @@ use crate::{
pub struct JvmWorker { pub struct JvmWorker {
command_rx: mpsc::Receiver<JvmCommand>, command_rx: mpsc::Receiver<JvmCommand>,
command_tx: mpsc::Sender<JvmCommand>,
pub plugin_manager: PluginManager, pub plugin_manager: PluginManager,
pub event_manager: EventManager, pub event_manager: EventManager,
jvm: Option<j4rs::Jvm>, jvm: Option<j4rs::Jvm>,
@ -24,13 +23,9 @@ pub struct JvmWorker {
} }
impl JvmWorker { impl JvmWorker {
pub fn new( pub fn new(command_rx: mpsc::Receiver<JvmCommand>) -> Self {
command_tx: mpsc::Sender<JvmCommand>,
command_rx: mpsc::Receiver<JvmCommand>,
) -> Self {
Self { Self {
command_rx, command_rx,
command_tx,
plugin_manager: PluginManager::new(), plugin_manager: PluginManager::new(),
event_manager: EventManager::new(), event_manager: EventManager::new(),
jvm: None, jvm: None,

View File

@ -0,0 +1,84 @@
use std::ffi::{CStr, c_char};
use pumpkin::entity::player::Abilities;
use tokio::sync::MutexGuard;
use crate::java::native_callbacks::CALLBACK_CONTEXT;
#[repr(C)]
pub struct AbilitiesFFI {
pub invulnerable: bool,
pub flying: bool,
pub allow_flying: bool,
pub creative: bool,
pub allow_modify_world: bool,
pub fly_speed: f32,
pub walk_speed: f32,
}
impl AbilitiesFFI {
fn new(abilities: MutexGuard<'_, Abilities>) -> Self {
Self {
invulnerable: abilities.invulnerable,
flying: abilities.flying,
allow_flying: abilities.allow_flying,
creative: abilities.creative,
allow_modify_world: abilities.allow_modify_world,
fly_speed: abilities.fly_speed,
walk_speed: abilities.walk_speed,
}
}
}
pub extern "C" fn rust_set_abilities(
uuid_ptr: *const c_char,
abilities: *mut AbilitiesFFI,
) -> bool {
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
tokio::task::block_in_place(|| {
ctx.runtime.block_on(async {
let mut server_abilities = player.abilities.lock().await;
unsafe {
server_abilities.allow_flying = (*abilities).allow_flying;
server_abilities.allow_modify_world = (*abilities).allow_modify_world;
server_abilities.creative = (*abilities).creative;
server_abilities.fly_speed = (*abilities).fly_speed;
server_abilities.flying = (*abilities).flying;
server_abilities.invulnerable = (*abilities).invulnerable;
server_abilities.walk_speed = (*abilities).walk_speed;
}
})
});
return true;
}
}
false
}
pub extern "C" fn rust_get_abilities(uuid_ptr: *const c_char, out: *mut AbilitiesFFI) -> bool {
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
let abilities = tokio::task::block_in_place(|| {
ctx.runtime
.block_on(async { AbilitiesFFI::new(player.abilities.lock().await) })
});
unsafe {
*out = abilities;
}
return true;
}
}
false
}

View File

@ -0,0 +1,9 @@
use std::ffi::c_void;
#[unsafe(no_mangle)]
pub extern "C" fn rust_register_event(
_listener_ptr: *const c_void, // opaque pointer to Java object
_plugin_ptr: *const c_void,
) {
// Handle event registration
}

View File

@ -0,0 +1,25 @@
use std::ffi::{CStr, c_char};
use pumpkin_util::text::TextComponent;
use crate::java::native_callbacks::CALLBACK_CONTEXT;
#[unsafe(no_mangle)]
pub extern "C" fn rust_send_message(uuid_ptr: *const c_char, message_ptr: *const c_char) {
// This into_owned might not seem to make any sense, but it's necessary to ensure that the string is owned by the Rust code and can move into the runtime.
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
let message = unsafe { CStr::from_ptr(message_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
ctx.runtime.spawn(async move {
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
player
.send_system_message(&TextComponent::from_legacy_string(&message))
.await;
}
});
}
}

View File

@ -1,13 +1,12 @@
use std::{ use std::sync::{Arc, OnceLock};
ffi::{CStr, c_char, c_void},
sync::{Arc, OnceLock},
};
use anyhow::Result; use anyhow::Result;
use j4rs::{InvocationArg, Jvm}; use j4rs::{InvocationArg, Jvm};
use pumpkin::{entity::player::Abilities, plugin::Context}; use pumpkin::plugin::Context;
use pumpkin_util::text::TextComponent;
use tokio::sync::MutexGuard; pub mod abilities;
pub mod events;
pub mod message;
static CALLBACK_CONTEXT: OnceLock<CallbackContext> = OnceLock::new(); static CALLBACK_CONTEXT: OnceLock<CallbackContext> = OnceLock::new();
@ -32,10 +31,10 @@ pub fn init_callback_context(
} }
pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> { pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
let send_message_addr = rust_send_message as *const () as i64; let send_message_addr = message::rust_send_message as *const () as i64;
let register_event_addr = rust_register_event as *const () as i64; let register_event_addr = events::rust_register_event as *const () as i64;
let get_abilities_addr = rust_get_abilities as *const () as i64; let get_abilities_addr = abilities::rust_get_abilities as *const () as i64;
let set_abilities_addr = rust_set_abilities as *const () as i64; let set_abilities_addr = abilities::rust_set_abilities as *const () as i64;
jvm.invoke_static( jvm.invoke_static(
"org.patchbukkit.bridge.NativePatchBukkit", "org.patchbukkit.bridge.NativePatchBukkit",
@ -50,109 +49,3 @@ pub fn initialize_callbacks(jvm: &Jvm) -> Result<()> {
Ok(()) Ok(())
} }
#[unsafe(no_mangle)]
pub extern "C" fn rust_send_message(uuid_ptr: *const c_char, message_ptr: *const c_char) {
// This into_owned might not seem to make any sense, but it's necessary to ensure that the string is owned by the Rust code and can move into the runtime.
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
let message = unsafe { CStr::from_ptr(message_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
ctx.runtime.spawn(async move {
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
player
.send_system_message(&TextComponent::from_legacy_string(&message))
.await;
}
});
}
}
#[repr(C)]
pub struct AbilitiesFFI {
pub invulnerable: bool,
pub flying: bool,
pub allow_flying: bool,
pub creative: bool,
pub allow_modify_world: bool,
pub fly_speed: f32,
pub walk_speed: f32,
}
impl AbilitiesFFI {
fn new(abilities: MutexGuard<'_, Abilities>) -> Self {
Self {
invulnerable: abilities.invulnerable,
flying: abilities.flying,
allow_flying: abilities.allow_flying,
creative: abilities.creative,
allow_modify_world: abilities.allow_modify_world,
fly_speed: abilities.fly_speed,
walk_speed: abilities.walk_speed,
}
}
}
pub extern "C" fn rust_set_abilities(
uuid_ptr: *const c_char,
abilities: *mut AbilitiesFFI,
) -> bool {
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
tokio::task::block_in_place(|| {
ctx.runtime.block_on(async {
let mut server_abilities = player.abilities.lock().await;
unsafe {
server_abilities.allow_flying = (*abilities).allow_flying;
server_abilities.allow_modify_world = (*abilities).allow_modify_world;
server_abilities.creative = (*abilities).creative;
server_abilities.fly_speed = (*abilities).fly_speed;
server_abilities.flying = (*abilities).flying;
server_abilities.invulnerable = (*abilities).invulnerable;
server_abilities.walk_speed = (*abilities).walk_speed;
}
})
});
return true;
}
}
false
}
pub extern "C" fn rust_get_abilities(uuid_ptr: *const c_char, out: *mut AbilitiesFFI) -> bool {
let uuid_str = unsafe { CStr::from_ptr(uuid_ptr).to_string_lossy().into_owned() };
if let Some(ctx) = CALLBACK_CONTEXT.get() {
let uuid = uuid::Uuid::parse_str(&uuid_str).unwrap();
let player = ctx.plugin_context.server.get_player_by_uuid(uuid);
if let Some(player) = player {
let abilities = tokio::task::block_in_place(|| {
ctx.runtime
.block_on(async { AbilitiesFFI::new(player.abilities.lock().await) })
});
unsafe {
*out = abilities;
}
return true;
}
}
false
}
#[unsafe(no_mangle)]
pub extern "C" fn rust_register_event(
listener_ptr: *const c_void, // opaque pointer to Java object
plugin_ptr: *const c_void,
) {
// Handle event registration
}

View File

@ -1,6 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use pumpkin::{plugin::Context, server::Server}; use pumpkin::plugin::Context;
use pumpkin_api_macros::{plugin_impl, plugin_method}; use pumpkin_api_macros::{plugin_impl, plugin_method};
pub mod config; pub mod config;
@ -15,7 +15,7 @@ use java::{
resources::{cleanup_stale_files, sync_embedded_resources}, resources::{cleanup_stale_files, sync_embedded_resources},
}; };
use tokio::sync::{ use tokio::sync::{
mpsc::{self, Receiver, Sender}, mpsc::{self, Receiver},
oneshot, oneshot,
}; };
@ -200,17 +200,16 @@ pub struct PatchBukkitPlugin {
impl PatchBukkitPlugin { impl PatchBukkitPlugin {
pub fn new() -> Self { pub fn new() -> Self {
let (tx, rx) = mpsc::channel(100); let (tx, rx) = mpsc::channel(100);
let command_tx = tx.clone();
#[tokio::main] #[tokio::main]
pub async fn jvm_thread_task(command_tx: Sender<JvmCommand>, rx: Receiver<JvmCommand>) { pub async fn jvm_thread_task(rx: Receiver<JvmCommand>) {
JvmWorker::new(command_tx, rx).attach_thread().await; JvmWorker::new(rx).attach_thread().await;
} }
std::thread::Builder::new() std::thread::Builder::new()
.name("patchbukkit-jvm-worker".to_string()) .name("patchbukkit-jvm-worker".to_string())
.spawn(move || { .spawn(move || {
jvm_thread_task(command_tx.clone(), rx); jvm_thread_task(rx);
}) })
.unwrap(); .unwrap();
PatchBukkitPlugin { command_tx: tx } PatchBukkitPlugin { command_tx: tx }

View File

@ -223,9 +223,9 @@ impl PluginManager {
&self, &self,
jvm: &Jvm, jvm: &Jvm,
cmd_name: &str, cmd_name: &str,
command: Arc<Mutex<Instance>>, _command: Arc<Mutex<Instance>>,
sender: SimpleCommandSender, sender: SimpleCommandSender,
args: Vec<String>, _args: Vec<String>,
) -> Result<(), String> { ) -> Result<(), String> {
let j_sender = match sender { let j_sender = match sender {
SimpleCommandSender::Console => jvm SimpleCommandSender::Console => jvm