chore: remove futures

using futures::executor::block_on(async { was a quick and dirty fix which is not needed anymore, also improved some other things
This commit is contained in:
Alexander Medvedev 2026-01-31 16:22:16 +01:00
parent 88c292274a
commit 26b9727166
8 changed files with 87 additions and 74 deletions

View File

@ -7,17 +7,21 @@ A plugin for [PumpkinMC](https://pumpkinmc.org/) that adds support for [PaperMC]
> [!IMPORTANT] > [!IMPORTANT]
> Currently PatchBukkit is in heavy development, as such releases are not yet available. > Currently PatchBukkit is in heavy development, as such releases are not yet available.
1. Install [java](https://docs.papermc.io/misc/java-install/) 1. **Requirement**: Install Java 25 or newer.
2. Download the plugin in releases `patchbukkit-mac.dylib`, `patchbukkit-linux-aarch64.so`, `patchbukkit-linux-x86.so`, or `patchbukkit-windows-x86.dll`. 2. **Download**: Grab the library matching your operating system from the Releases page:
3. Add it into your PumpkinMC plugin directory (this gets created after runing PumpkinMC for the first time).
4. Run PumpkinMC again, and you should see a new directory in PumpkinMC called `patchbukkit`. You can add any `bukkit`, `spigot`, or `paper` plugin you wish, and it will run. - patchbukkit-windows-x86.dll (Windows)
- patchbukkit-linux-x86.so (Linux x86_64)
- patchbukkit-linux-aarch64.so (Linux ARM64/ Raspberry Pi)
- patchbukkit-mac.dylib (macOS)
3. **Deploy**: Place the downloaded file into your PumpkinMC plugins/ directory. (Run PumpkinMC once to generate this folder if it doesn't exist).
4. **Initialize**: Restart PumpkinMC. This creates a new /patchbukkit directory in your server root.
5. **Add Plugins**: Drop your .jar plugin files (Paper/Spigot/Bukkit) into the newly created patchbukkit/ folder and restart.
## Development ## Development
If you wish to contribute to PatchBukkit, follow the following steps: If you wish to contribute to PatchBukkit, follow the following steps:
1. Build PumpkinMC from source with the `nightly-2025-12-11` rust toolchain. 1. Run `./build.sh`
2. Clone this repository 2. Copy the `target/debug/patchbukkit` binary to the `plugins` directory in your PumpkinMC server.
3. `cd` into the `java` directory and run `./gradlew build`
4. `cd` into the `rust` directory and run `cargo build`
5. Copy the `target/debug/patchbukkit` binary to the `plugins` directory in your PumpkinMC server.

25
rust/Cargo.lock generated
View File

@ -1689,7 +1689,6 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"env_logger", "env_logger",
"futures",
"glob", "glob",
"j4rs", "j4rs",
"j4rs_derive", "j4rs_derive",
@ -1963,7 +1962,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin" name = "pumpkin"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"base64", "base64",
@ -2006,7 +2005,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-api-macros" name = "pumpkin-api-macros"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
@ -2017,7 +2016,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-config" name = "pumpkin-config"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"log", "log",
"pumpkin-util", "pumpkin-util",
@ -2029,7 +2028,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-data" name = "pumpkin-data"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"crc-fast", "crc-fast",
"heck", "heck",
@ -2049,7 +2048,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-inventory" name = "pumpkin-inventory"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"crossbeam-utils", "crossbeam-utils",
"log", "log",
@ -2064,7 +2063,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-macros" name = "pumpkin-macros"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
@ -2076,7 +2075,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-nbt" name = "pumpkin-nbt"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"bytes", "bytes",
"cesu8", "cesu8",
@ -2088,7 +2087,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-protocol" name = "pumpkin-protocol"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"aes", "aes",
"async-compression", "async-compression",
@ -2110,7 +2109,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-util" name = "pumpkin-util"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"base64", "base64",
"bytes", "bytes",
@ -2135,7 +2134,7 @@ dependencies = [
[[package]] [[package]]
name = "pumpkin-world" name = "pumpkin-world"
version = "0.1.0-dev+1.21.11" version = "0.1.0-dev+1.21.11"
source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#72bd4dfbef6326063b1bc0752e2789402f5c9197" source = "git+https://github.com/Pumpkin-MC/Pumpkin.git?branch=master#f93be68caa3969502c13d5d284da59fe1017ed9a"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"bytes", "bytes",
@ -2713,9 +2712,9 @@ checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.11" version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]] [[package]]
name = "slotmap" name = "slotmap"

View File

@ -11,7 +11,6 @@ pumpkin = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master"
pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-util" } pumpkin-util = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-util" }
pumpkin-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-api-macros" } pumpkin-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-api-macros" }
futures = "0.3"
tokio = "1" tokio = "1"
log = "0.4" log = "0.4"
glob = "0.3.3" glob = "0.3.3"

View File

@ -21,8 +21,8 @@ pub fn setup_directories(server: &Context) -> Result<PatchBukkitDirectories, Str
let j4rs = base.join("j4rs"); let j4rs = base.join("j4rs");
let jassets = j4rs.join("jassets"); let jassets = j4rs.join("jassets");
fs::create_dir_all(&plugin_updates) // fs::create_dir_all(&plugin_updates)
.map_err(|err| format!("Failed to create plugin folder: {:?}", err))?; // .map_err(|err| format!("Failed to create plugin folder: {:?}", err))?;
fs::create_dir_all(&jassets) fs::create_dir_all(&jassets)
.map_err(|err| format!("Failed to create jassets folder: {:?}", err))?; .map_err(|err| format!("Failed to create jassets folder: {:?}", err))?;

View File

@ -10,21 +10,19 @@ use zip::ZipArchive;
use crate::config::{paper::PAPER_PLUGIN_CONFIG, spigot::SPIGOT_PLUGIN_CONFIG}; use crate::config::{paper::PAPER_PLUGIN_CONFIG, spigot::SPIGOT_PLUGIN_CONFIG};
pub fn discover_jar_files(plugin_folder: &PathBuf) -> Vec<PathBuf> { pub fn discover_jar_files(plugin_folder: &PathBuf) -> impl Iterator<Item = PathBuf> {
let pattern = format!("{}/**/*.jar", plugin_folder.to_string_lossy()); let pattern = format!("{}/**/*.jar", plugin_folder.display());
let mut entries = Vec::new();
for entry in glob(&pattern).expect("Failed to read glob pattern") { glob(&pattern)
match entry { .expect("Invalid glob pattern")
Ok(inner_path) => match inner_path.canonicalize() { .filter_map(|entry| {
Ok(path) => entries.push(path), entry
Err(e) => log::error!("Failed to convert path to string: {:?}", e), .map_err(|e| log::error!("Glob error: {:?}", e))
}, .ok()?
Err(e) => log::error!("Failed to canonicalize path: {:?}", e), .canonicalize()
} .map_err(|e| log::error!("Canonicalize error: {:?}", e))
} .ok()
})
entries
} }
pub fn read_configs_from_jar<P: AsRef<Path>>( pub fn read_configs_from_jar<P: AsRef<Path>>(

View File

@ -99,7 +99,8 @@ impl JvmWorker {
let _ = respond_to.send( let _ = respond_to.send(
self.plugin_manager self.plugin_manager
.instantiate_all_plugins(jvm, &server, command_tx), .instantiate_all_plugins(jvm, &server, command_tx)
.await,
); );
} }
JvmCommand::EnableAllPlugins { respond_to } => { JvmCommand::EnableAllPlugins { respond_to } => {

View File

@ -1,5 +1,10 @@
use std::{collections::HashSet, fs, path::PathBuf}; use std::{
collections::HashSet,
fs,
path::{Path, PathBuf},
};
use anyhow::{Context, Result};
use rust_embed::Embed; use rust_embed::Embed;
#[derive(Embed)] #[derive(Embed)]
@ -7,55 +12,64 @@ use rust_embed::Embed;
pub struct Resources; pub struct Resources;
pub fn cleanup_stale_files(j4rs_folder: &PathBuf) { pub fn cleanup_stale_files(j4rs_folder: &PathBuf) {
let allowed: HashSet<String> = Resources::iter().map(|p| p.to_string()).collect(); let allowed: HashSet<PathBuf> = Resources::iter()
.map(|p| PathBuf::from(p.to_string()))
.collect();
for entry in walkdir::WalkDir::new(j4rs_folder) for entry in walkdir::WalkDir::new(j4rs_folder)
.into_iter() .into_iter()
.filter_map(|e| e.ok()) .filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file()) .filter(|e| e.file_type().is_file())
{ {
let rel_path = entry let path = entry.path();
.path()
.strip_prefix(j4rs_folder)
.unwrap()
.to_string_lossy()
.to_string();
if !allowed.contains(&rel_path) { if let Ok(rel_path) = path.strip_prefix(j4rs_folder) {
log::warn!("Removing stale j4rs file: {rel_path}"); if !allowed.contains(rel_path) {
let _ = fs::remove_file(entry.path()); log::warn!("Removing stale j4rs file: {}", rel_path.display());
if let Err(e) = fs::remove_file(path) {
log::error!("Failed to remove stale file {}: {}", path.display(), e);
}
}
} }
} }
} }
pub fn sync_embedded_resources(j4rs_folder: &PathBuf) -> Result<(), String> { pub fn sync_embedded_resources(j4rs_folder: &Path) -> Result<(), String> {
for resource_path_str in Resources::iter() { for resource_path_str in Resources::iter() {
let resource_path = j4rs_folder.join(resource_path_str.to_string()); let resource_path = j4rs_folder.join(resource_path_str.to_string());
let resource = Resources::get(&resource_path_str).unwrap(); let resource = Resources::get(&resource_path_str).unwrap();
if !resource_path.exists() { if !resource_path.exists() {
log::info!("Extracting new resource: {}", resource_path.display());
write_resource(&resource_path, &resource.data)?; write_resource(&resource_path, &resource.data)?;
} else { } else {
update_resource_if_changed(&resource_path, &resource.data)?; update_resource_if_changed(&resource_path, &resource.data)?;
} }
} }
Ok(()) Ok(())
} }
fn write_resource(path: &PathBuf, data: &[u8]) -> Result<(), String> { fn write_resource(path: &Path, data: &[u8]) -> Result<(), String> {
let parent = path.parent().ok_or("Resource has no parent directory")?; if let Some(parent) = path.parent() {
fs::create_dir_all(parent) fs::create_dir_all(parent)
.map_err(|err| format!("Failed to create parent for resource: {:?}", err))?; .map_err(|_| format!("Failed to create directory: {}", parent.display()))?;
}
fs::write(path, data).map_err(|err| format!("Failed to add resource: {:?}", err)) fs::write(path, data).map_err(|_| format!("Failed to write resource: {}", path.display()))?;
Ok(())
} }
fn update_resource_if_changed(path: &PathBuf, new_data: &[u8]) -> Result<(), String> { fn update_resource_if_changed(path: &Path, new_data: &[u8]) -> Result<(), String> {
let old_data = fs::read(path).map_err(|err| format!("Failed to read resource: {:?}", err))?; // Quick check: If file sizes differ, it's definitely changed, TODO: use Hash ?
let metadata = fs::metadata(path).ok();
let size_matches = metadata
.map(|m| m.len() == new_data.len() as u64)
.unwrap_or(false);
if new_data != old_data { if !size_matches || fs::read(path).map_err(|e| e.to_string())? != new_data {
fs::write(path, new_data).map_err(|err| format!("Failed to update resource: {:?}", err))?; log::debug!("Updating changed resource: {}", path.display());
fs::write(path, new_data)
.map_err(|_| format!("Failed to update resource: {}", path.display()))?;
} }
Ok(()) Ok(())

View File

@ -288,7 +288,7 @@ impl PluginManager {
Ok(()) Ok(())
} }
pub fn instantiate_all_plugins( pub async fn instantiate_all_plugins(
&mut self, &mut self,
jvm: &Jvm, jvm: &Jvm,
server: &Arc<Context>, server: &Arc<Context>,
@ -381,7 +381,6 @@ impl PluginManager {
// }; // };
let permission = format!("patchbukkit:{}", cmd_name); let permission = format!("patchbukkit:{}", cmd_name);
futures::executor::block_on(async {
server server
.register_permission(Permission::new( .register_permission(Permission::new(
&permission, &permission,
@ -391,7 +390,6 @@ impl PluginManager {
.await .await
.unwrap(); .unwrap();
server.register_command(node, permission).await server.register_command(node, permission).await
});
} }
plugin.state = PluginState::Loaded; plugin.state = PluginState::Loaded;