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]
> Currently PatchBukkit is in heavy development, as such releases are not yet available.
1. Install [java](https://docs.papermc.io/misc/java-install/)
2. Download the plugin in releases `patchbukkit-mac.dylib`, `patchbukkit-linux-aarch64.so`, `patchbukkit-linux-x86.so`, or `patchbukkit-windows-x86.dll`.
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.
1. **Requirement**: Install Java 25 or newer.
2. **Download**: Grab the library matching your operating system from the Releases page:
- 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
If you wish to contribute to PatchBukkit, follow the following steps:
1. Build PumpkinMC from source with the `nightly-2025-12-11` rust toolchain.
2. Clone this repository
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.
1. Run `./build.sh`
2. 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 = [
"anyhow",
"env_logger",
"futures",
"glob",
"j4rs",
"j4rs_derive",
@ -1963,7 +1962,7 @@ dependencies = [
[[package]]
name = "pumpkin"
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 = [
"arc-swap",
"base64",
@ -2006,7 +2005,7 @@ dependencies = [
[[package]]
name = "pumpkin-api-macros"
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 = [
"proc-macro-error2",
"proc-macro2",
@ -2017,7 +2016,7 @@ dependencies = [
[[package]]
name = "pumpkin-config"
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 = [
"log",
"pumpkin-util",
@ -2029,7 +2028,7 @@ dependencies = [
[[package]]
name = "pumpkin-data"
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 = [
"crc-fast",
"heck",
@ -2049,7 +2048,7 @@ dependencies = [
[[package]]
name = "pumpkin-inventory"
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 = [
"crossbeam-utils",
"log",
@ -2064,7 +2063,7 @@ dependencies = [
[[package]]
name = "pumpkin-macros"
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 = [
"proc-macro-error2",
"proc-macro2",
@ -2076,7 +2075,7 @@ dependencies = [
[[package]]
name = "pumpkin-nbt"
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 = [
"bytes",
"cesu8",
@ -2088,7 +2087,7 @@ dependencies = [
[[package]]
name = "pumpkin-protocol"
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 = [
"aes",
"async-compression",
@ -2110,7 +2109,7 @@ dependencies = [
[[package]]
name = "pumpkin-util"
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 = [
"base64",
"bytes",
@ -2135,7 +2134,7 @@ dependencies = [
[[package]]
name = "pumpkin-world"
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 = [
"bitflags",
"bytes",
@ -2713,9 +2712,9 @@ checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e"
[[package]]
name = "slab"
version = "0.4.11"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
[[package]]
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-api-macros = { git = "https://github.com/Pumpkin-MC/Pumpkin.git", branch = "master", package = "pumpkin-api-macros" }
futures = "0.3"
tokio = "1"
log = "0.4"
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 jassets = j4rs.join("jassets");
fs::create_dir_all(&plugin_updates)
.map_err(|err| format!("Failed to create plugin folder: {:?}", err))?;
// fs::create_dir_all(&plugin_updates)
// .map_err(|err| format!("Failed to create plugin folder: {:?}", err))?;
fs::create_dir_all(&jassets)
.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};
pub fn discover_jar_files(plugin_folder: &PathBuf) -> Vec<PathBuf> {
let pattern = format!("{}/**/*.jar", plugin_folder.to_string_lossy());
let mut entries = Vec::new();
pub fn discover_jar_files(plugin_folder: &PathBuf) -> impl Iterator<Item = PathBuf> {
let pattern = format!("{}/**/*.jar", plugin_folder.display());
for entry in glob(&pattern).expect("Failed to read glob pattern") {
match entry {
Ok(inner_path) => match inner_path.canonicalize() {
Ok(path) => entries.push(path),
Err(e) => log::error!("Failed to convert path to string: {:?}", e),
},
Err(e) => log::error!("Failed to canonicalize path: {:?}", e),
}
}
entries
glob(&pattern)
.expect("Invalid glob pattern")
.filter_map(|entry| {
entry
.map_err(|e| log::error!("Glob error: {:?}", e))
.ok()?
.canonicalize()
.map_err(|e| log::error!("Canonicalize error: {:?}", e))
.ok()
})
}
pub fn read_configs_from_jar<P: AsRef<Path>>(

View File

@ -99,7 +99,8 @@ impl JvmWorker {
let _ = respond_to.send(
self.plugin_manager
.instantiate_all_plugins(jvm, &server, command_tx),
.instantiate_all_plugins(jvm, &server, command_tx)
.await,
);
}
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;
#[derive(Embed)]
@ -7,55 +12,64 @@ use rust_embed::Embed;
pub struct Resources;
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)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.file_type().is_file())
{
let rel_path = entry
.path()
.strip_prefix(j4rs_folder)
.unwrap()
.to_string_lossy()
.to_string();
let path = entry.path();
if !allowed.contains(&rel_path) {
log::warn!("Removing stale j4rs file: {rel_path}");
let _ = fs::remove_file(entry.path());
if let Ok(rel_path) = path.strip_prefix(j4rs_folder) {
if !allowed.contains(rel_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() {
let resource_path = j4rs_folder.join(resource_path_str.to_string());
let resource = Resources::get(&resource_path_str).unwrap();
if !resource_path.exists() {
log::info!("Extracting new resource: {}", resource_path.display());
write_resource(&resource_path, &resource.data)?;
} else {
update_resource_if_changed(&resource_path, &resource.data)?;
}
}
Ok(())
}
fn write_resource(path: &PathBuf, data: &[u8]) -> Result<(), String> {
let parent = path.parent().ok_or("Resource has no parent directory")?;
fn write_resource(path: &Path, data: &[u8]) -> Result<(), String> {
if let Some(parent) = path.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> {
let old_data = fs::read(path).map_err(|err| format!("Failed to read resource: {:?}", err))?;
fn update_resource_if_changed(path: &Path, new_data: &[u8]) -> Result<(), String> {
// 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 {
fs::write(path, new_data).map_err(|err| format!("Failed to update resource: {:?}", err))?;
if !size_matches || fs::read(path).map_err(|e| e.to_string())? != new_data {
log::debug!("Updating changed resource: {}", path.display());
fs::write(path, new_data)
.map_err(|_| format!("Failed to update resource: {}", path.display()))?;
}
Ok(())

View File

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