Rename to PatchBukkit

This commit is contained in:
Bjorn Beishline 2026-01-21 13:35:19 -07:00
parent f0e3e01f16
commit 8286a34eb9
18 changed files with 157 additions and 94 deletions

4
.gitignore vendored
View File

@ -15,8 +15,8 @@ java/.gradle/
# Build outputs # Build outputs
build/ build/
java/build/ java/build/
java/papkin/build/ java/patchbukkit/build/
java/papkin/bin/ java/patchbukkit/bin/
# Keep Gradle wrapper # Keep Gradle wrapper
!gradle/wrapper/gradle-wrapper.jar !gradle/wrapper/gradle-wrapper.jar

View File

@ -1,23 +1,23 @@
# Papkin # PatchBukkit
A plugin for [PumpkinMC](https://pumpkinmc.org/) that adds support for [PaperMC](https://papermc.io/), [Spigot](https://www.spigotmc.org/), and [Bukkit](https://dev.bukkit.org/) plugins. A plugin for [PumpkinMC](https://pumpkinmc.org/) that adds support for [PaperMC](https://papermc.io/), [Spigot](https://www.spigotmc.org/), and [Bukkit](https://dev.bukkit.org/) plugins.
## Installation ## Installation
> [!IMPORTANT] > [!IMPORTANT]
> Currently Papkin 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. Install [java](https://docs.papermc.io/misc/java-install/)
2. Download the plugin in releases `papkin-mac.dylib`, `papkin-linux-aarch64.so`, `papkin-linux-x86.so`, or `papkin-windows-x86.dll`. 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). 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 `papkin`. You can add any `bukkit`, `spigot`, or `paper` plugin you wish, and it will run. 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.
## Development ## Development
If you wish to contribute to Papkin, 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. Build PumpkinMC from source with the `nightly-2025-12-11` rust toolchain.
2. Clone this repository 2. Clone this repository
3. `cd` into the `java` directory and run `./gradlew build` 3. `cd` into the `java` directory and run `./gradlew build`
4. `cd` into the `rust` directory and run `cargo build` 4. `cd` into the `rust` directory and run `cargo build`
5. Copy the `target/debug/papkin` binary to the `plugins` directory in your PumpkinMC server. 5. Copy the `target/debug/patchbukkit` binary to the `plugins` directory in your PumpkinMC server.

View File

@ -1 +0,0 @@
org.papkin.PumpkinServerBuildInfo

View File

@ -1,4 +1,4 @@
package org.papkin; package org.patchbukkit;
import com.destroystokyo.paper.entity.ai.MobGoals; import com.destroystokyo.paper.entity.ai.MobGoals;
import io.papermc.paper.ban.BanListType; import io.papermc.paper.ban.BanListType;
@ -84,7 +84,7 @@ import org.bukkit.util.CachedServerIcon;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
public class PapkinServer implements Server { public class PatchBukkitServer implements Server {
private final String serverName = private final String serverName =
io.papermc.paper.ServerBuildInfo.buildInfo().brandName(); io.papermc.paper.ServerBuildInfo.buildInfo().brandName();
@ -1537,7 +1537,7 @@ public class PapkinServer implements Server {
@Override @Override
public @NotNull UnsafeValues getUnsafe() { public @NotNull UnsafeValues getUnsafe() {
return PapkinUnsafeValues.INSTANCE; return PatchBukkitUnsafeValues.INSTANCE;
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package org.papkin; package org.patchbukkit;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
@ -6,6 +6,10 @@ import io.papermc.paper.entity.EntitySerializationFlag;
import io.papermc.paper.inventory.tooltip.TooltipContext; import io.papermc.paper.inventory.tooltip.TooltipContext;
import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager;
import io.papermc.paper.registry.RegistryKey; import io.papermc.paper.registry.RegistryKey;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.BooleanSupplier;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.flattener.ComponentFlattener; import net.kyori.adventure.text.flattener.ComponentFlattener;
@ -38,15 +42,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jspecify.annotations.NonNull; import org.jspecify.annotations.NonNull;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.function.BooleanSupplier;
@SuppressWarnings("removal") @SuppressWarnings("removal")
public class PapkinUnsafeValues implements UnsafeValues { public class PatchBukkitUnsafeValues implements UnsafeValues {
public static final PapkinUnsafeValues INSTANCE = new PapkinUnsafeValues(); public static final PatchBukkitUnsafeValues INSTANCE =
new PatchBukkitUnsafeValues();
// These are commonly used - implement first // These are commonly used - implement first
@Override @Override
@ -79,22 +79,33 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public @NotNull JsonObject serializeItemAsJson(@NotNull ItemStack itemStack) { public @NotNull JsonObject serializeItemAsJson(
@NotNull ItemStack itemStack
) {
return null; return null;
} }
@Override @Override
public @NotNull ItemStack deserializeItemFromJson(@NotNull JsonObject data) throws IllegalArgumentException { public @NotNull ItemStack deserializeItemFromJson(@NotNull JsonObject data)
throws IllegalArgumentException {
return null; return null;
} }
@Override @Override
public byte @NotNull [] serializeEntity(@NotNull Entity entity, @NonNull @NotNull EntitySerializationFlag... serializationFlags) { public byte@NotNull [] serializeEntity(
@NotNull Entity entity,
@NonNull @NotNull EntitySerializationFlag... serializationFlags
) {
return new byte[0]; return new byte[0];
} }
@Override @Override
public @NotNull Entity deserializeEntity(byte @NotNull [] data, @NotNull World world, boolean preserveUUID, boolean preservePassengers) { public @NotNull Entity deserializeEntity(
byte@NotNull [] data,
@NotNull World world,
boolean preserveUUID,
boolean preservePassengers
) {
return null; return null;
} }
@ -114,29 +125,45 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public boolean isValidRepairItemStack(@NotNull ItemStack itemToBeRepaired, @NotNull ItemStack repairMaterial) { public boolean isValidRepairItemStack(
@NotNull ItemStack itemToBeRepaired,
@NotNull ItemStack repairMaterial
) {
return false; return false;
} }
@Override @Override
public boolean hasDefaultEntityAttributes(@NotNull NamespacedKey entityKey) { public boolean hasDefaultEntityAttributes(
@NotNull NamespacedKey entityKey
) {
return false; return false;
} }
@Override @Override
public @NotNull Attributable getDefaultEntityAttributes(@NotNull NamespacedKey entityKey) { public @NotNull Attributable getDefaultEntityAttributes(
@NotNull NamespacedKey entityKey
) {
return null; return null;
} }
@Override @Override
public @NotNull NamespacedKey getBiomeKey(RegionAccessor accessor, int x, int y, int z) { public @NotNull NamespacedKey getBiomeKey(
RegionAccessor accessor,
int x,
int y,
int z
) {
return null; return null;
} }
@Override @Override
public void setBiomeKey(RegionAccessor accessor, int x, int y, int z, NamespacedKey biomeKey) { public void setBiomeKey(
RegionAccessor accessor,
} int x,
int y,
int z,
NamespacedKey biomeKey
) {}
@Override @Override
public String getStatisticCriteriaKey(@NotNull Statistic statistic) { public String getStatisticCriteriaKey(@NotNull Statistic statistic) {
@ -144,17 +171,27 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public @Nullable Color getSpawnEggLayerColor(EntityType entityType, int layer) { public @Nullable Color getSpawnEggLayerColor(
EntityType entityType,
int layer
) {
return null; return null;
} }
@Override @Override
public LifecycleEventManager<Plugin> createPluginLifecycleEventManager(JavaPlugin plugin, BooleanSupplier registrationCheck) { public LifecycleEventManager<Plugin> createPluginLifecycleEventManager(
JavaPlugin plugin,
BooleanSupplier registrationCheck
) {
return null; return null;
} }
@Override @Override
public @NotNull List<Component> computeTooltipLines(@NotNull ItemStack itemStack, @NotNull TooltipContext tooltipContext, @Nullable Player player) { public @NotNull List<Component> computeTooltipLines(
@NotNull ItemStack itemStack,
@NotNull TooltipContext tooltipContext,
@Nullable Player player
) {
return List.of(); return List.of();
} }
@ -169,17 +206,22 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public @NotNull ItemStack deserializeStack(@NotNull Map<String, Object> args) { public @NotNull ItemStack deserializeStack(
@NotNull Map<String, Object> args
) {
return null; return null;
} }
@Override @Override
public @NotNull ItemStack deserializeItemHover(HoverEvent.@NotNull ShowItem itemHover) { public @NotNull ItemStack deserializeItemHover(
HoverEvent.@NotNull ShowItem itemHover
) {
return null; return null;
} }
@Override @Override
public void checkSupported(PluginDescriptionFile pdf) throws InvalidPluginException { public void checkSupported(PluginDescriptionFile pdf)
throws InvalidPluginException {
// Be lenient during development - accept most plugins // Be lenient during development - accept most plugins
String api = pdf.getAPIVersion(); String api = pdf.getAPIVersion();
if (api != null && !isSupportedApiVersion(api)) { if (api != null && !isSupportedApiVersion(api)) {
@ -208,7 +250,10 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(Material material, EquipmentSlot slot) { public Multimap<Attribute, AttributeModifier> getDefaultAttributeModifiers(
Material material,
EquipmentSlot slot
) {
return null; return null;
} }
@ -243,12 +288,16 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public PotionType.InternalPotionData getInternalPotionData(NamespacedKey key) { public PotionType.InternalPotionData getInternalPotionData(
NamespacedKey key
) {
return null; return null;
} }
@Override @Override
public DamageSource.@NotNull Builder createDamageSourceBuilder(@NotNull DamageType damageType) { public DamageSource.@NotNull Builder createDamageSourceBuilder(
@NotNull DamageType damageType
) {
return null; return null;
} }
@ -294,7 +343,12 @@ public class PapkinUnsafeValues implements UnsafeValues {
} }
@Override @Override
public Component resolveWithContext(Component component, CommandSender context, Entity scoreboardSubject, boolean bypassPermissions) throws IOException { public Component resolveWithContext(
Component component,
CommandSender context,
Entity scoreboardSubject,
boolean bypassPermissions
) throws IOException {
return null; return null;
} }

View File

@ -1,4 +1,4 @@
package org.papkin.loader; package org.patchbukkit.loader;
import io.papermc.paper.plugin.provider.util.ProviderUtil; import io.papermc.paper.plugin.provider.util.ProviderUtil;
import java.io.File; import java.io.File;

View File

@ -1,4 +1,4 @@
package org.papkin; package org.patchbukkit;
import io.papermc.paper.ServerBuildInfo; import io.papermc.paper.ServerBuildInfo;
import java.time.Instant; import java.time.Instant;

View File

@ -1,4 +1,4 @@
package org.papkin; package org.patchbukkit;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;

View File

@ -0,0 +1 @@
org.patchbukkit.PumpkinServerBuildInfo

View File

@ -10,5 +10,5 @@ plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
} }
rootProject.name = "papkin" rootProject.name = "patchbukkit"
include("papkin") include("patchbukkit")

44
rust/Cargo.lock generated
View File

@ -1588,28 +1588,6 @@ dependencies = [
"sha2 0.10.9", "sha2 0.10.9",
] ]
[[package]]
name = "papkin"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"env_logger",
"glob",
"j4rs",
"j4rs_derive",
"log",
"pumpkin",
"pumpkin-api-macros",
"pumpkin-util",
"rust-embed",
"serde",
"serde-saphyr",
"tokio",
"walkdir",
"zip",
]
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.12.5" version = "0.12.5"
@ -1633,6 +1611,28 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "patchbukkit"
version = "0.1.0"
dependencies = [
"anyhow",
"async-trait",
"env_logger",
"glob",
"j4rs",
"j4rs_derive",
"log",
"pumpkin",
"pumpkin-api-macros",
"pumpkin-util",
"rust-embed",
"serde",
"serde-saphyr",
"tokio",
"walkdir",
"zip",
]
[[package]] [[package]]
name = "pbkdf2" name = "pbkdf2"
version = "0.12.2" version = "0.12.2"

View File

@ -1,5 +1,5 @@
[package] [package]
name = "papkin" name = "patchbukkit"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"

View File

@ -129,14 +129,14 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
} }
if !Path::new("../java/papkin/build/libs/papkin.jar").exists() { if !Path::new("../java/patchbukkit/build/libs/patchbukkit.jar").exists() {
panic!( panic!(
"Failed to find papkin.jar, build the java library first by running `gradle build` in the java directory!" "Failed to find patchbukkit.jar, build the java library first by running `gradle build` in the java directory!"
); );
} }
jvm.deploy_artifact(&LocalJarArtifact::new( jvm.deploy_artifact(&LocalJarArtifact::new(
"../java/papkin/build/libs/papkin.jar", "../java/patchbukkit/build/libs/patchbukkit.jar",
)) ))
.unwrap(); .unwrap();

View File

@ -2,7 +2,7 @@ use std::{fs, path::PathBuf};
use pumpkin::plugin::Context; use pumpkin::plugin::Context;
pub struct PapkinDirectories { pub struct PatchBukkitDirectories {
pub base: PathBuf, pub base: PathBuf,
pub plugins: PathBuf, pub plugins: PathBuf,
pub plugin_updates: PathBuf, pub plugin_updates: PathBuf,
@ -10,13 +10,13 @@ pub struct PapkinDirectories {
pub jassets: PathBuf, pub jassets: PathBuf,
} }
pub fn setup_directories(server: &Context) -> Result<PapkinDirectories, String> { pub fn setup_directories(server: &Context) -> Result<PatchBukkitDirectories, String> {
let base = server let base = server
.get_data_folder() .get_data_folder()
.canonicalize() .canonicalize()
.map_err(|_| "Failed to get absolute directory from relative")?; .map_err(|_| "Failed to get absolute directory from relative")?;
let plugins = base.join("papkin-plugins"); let plugins = base.join("patchbukkit-plugins");
let plugin_updates = plugins.join("update"); let plugin_updates = plugins.join("update");
let j4rs = base.join("j4rs"); let j4rs = base.join("j4rs");
let jassets = j4rs.join("jassets"); let jassets = j4rs.join("jassets");
@ -27,7 +27,7 @@ pub fn setup_directories(server: &Context) -> Result<PapkinDirectories, String>
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))?;
Ok(PapkinDirectories { Ok(PatchBukkitDirectories {
base, base,
plugins, plugins,
plugin_updates, plugin_updates,

View File

@ -15,15 +15,15 @@ pub fn initialize_jvm(
Ok(jvm) Ok(jvm)
} }
pub fn setup_papkin_server(jvm: &Jvm) -> Result<(), String> { pub fn setup_patchbukkit_server(jvm: &Jvm) -> Result<(), String> {
let papkin_server = jvm let patchbukkit_server = jvm
.create_instance("org.papkin.PapkinServer", InvocationArg::empty()) .create_instance("org.patchbukkit.PatchBukkitServer", InvocationArg::empty())
.map_err(|err| format!("Failed to create PapkinServer instance: {:?}", err))?; .map_err(|err| format!("Failed to create PatchBukkitServer instance: {:?}", err))?;
jvm.invoke_static( jvm.invoke_static(
"org.bukkit.Bukkit", "org.bukkit.Bukkit",
"setServer", "setServer",
&[InvocationArg::from(papkin_server)], &[InvocationArg::from(patchbukkit_server)],
) )
.map_err(|err| format!("Failed to set Bukkit server: {:?}", err))?; .map_err(|err| format!("Failed to set Bukkit server: {:?}", err))?;

View File

@ -12,7 +12,7 @@ pub mod plugin;
use directories::setup_directories; use directories::setup_directories;
use java::{ use java::{
jar::discover_jar_files, jar::discover_jar_files,
jvm::{initialize_jvm, setup_papkin_server}, jvm::{initialize_jvm, setup_patchbukkit_server},
resources::{cleanup_stale_files, sync_embedded_resources}, resources::{cleanup_stale_files, sync_embedded_resources},
}; };
@ -20,7 +20,7 @@ use crate::{java::jar::read_configs_from_jar, plugin::manager::PluginManager};
async fn on_load_inner(_plugin: &mut MyPlugin, server: Arc<Context>) -> Result<(), String> { async fn on_load_inner(_plugin: &mut MyPlugin, server: Arc<Context>) -> Result<(), String> {
server.init_log(); server.init_log();
log::info!("Starting Papkin"); log::info!("Starting PatchBukkit");
// Setup directories // Setup directories
let dirs = setup_directories(&server)?; let dirs = setup_directories(&server)?;
@ -53,7 +53,10 @@ async fn on_load_inner(_plugin: &mut MyPlugin, server: Arc<Context>) -> Result<(
), ),
}, },
Err(err) => { Err(err) => {
log::error!("Failed to read configs from papkin plugin jar: {}", err); log::error!(
"Failed to read configs from PatchBukkit plugin jar: {}",
err
);
} }
} }
} }
@ -66,17 +69,17 @@ async fn on_load_inner(_plugin: &mut MyPlugin, server: Arc<Context>) -> Result<(
cleanup_stale_files(&dirs.j4rs); cleanup_stale_files(&dirs.j4rs);
sync_embedded_resources(&dirs.j4rs)?; sync_embedded_resources(&dirs.j4rs)?;
// Initialize JVM and Papkin server // Initialize JVM and PatchBukkit server
let jvm = initialize_jvm(classpath_entries, &dirs.j4rs)?; let jvm = initialize_jvm(classpath_entries, &dirs.j4rs)?;
setup_papkin_server(&jvm)?; setup_patchbukkit_server(&jvm)?;
plugin_manager plugin_manager
.load_all_plugins(&jvm) .load_all_plugins(&jvm)
.map_err(|err| format!("Failed to load papkin plugins: {}", err))?; .map_err(|err| format!("Failed to load PatchBukkit plugins: {}", err))?;
plugin_manager plugin_manager
.enable_all_plugins(&jvm) .enable_all_plugins(&jvm)
.map_err(|err| format!("Failed to enable papkin plugins: {}", err))?; .map_err(|err| format!("Failed to enable PatchBukkit plugins: {}", err))?;
Ok(()) Ok(())
} }

View File

@ -134,11 +134,15 @@ impl PluginManager {
match result { match result {
Ok(_) => { Ok(_) => {
plugin.state = PluginState::Enabled; plugin.state = PluginState::Enabled;
log::info!("Enabled papkin plugin: {}", plugin.name); log::info!("Enabled PatchBukkit plugin: {}", plugin.name);
} }
Err(e) => { Err(e) => {
plugin.state = PluginState::Errored; plugin.state = PluginState::Errored;
log::error!("Failed to enable papkin plugin {}: {:?}", plugin.name, e); log::error!(
"Failed to enable PatchBukkit plugin {}: {:?}",
plugin.name,
e
);
} }
} }
} }
@ -146,8 +150,10 @@ impl PluginManager {
} }
pub fn load_all_plugins(&mut self, jvm: &Jvm) -> Result<()> { pub fn load_all_plugins(&mut self, jvm: &Jvm) -> Result<()> {
let loader = let loader = jvm.create_instance(
jvm.create_instance("org.papkin.loader.PluginLoader", InvocationArg::empty())?; "org.patchbukkit.loader.PluginLoader",
InvocationArg::empty(),
)?;
for plugin in &mut self.plugins { for plugin in &mut self.plugins {
let result = jvm.invoke( let result = jvm.invoke(
&loader, &loader,
@ -159,11 +165,11 @@ impl PluginManager {
Ok(instance) => { Ok(instance) => {
plugin.instance = Some(instance); plugin.instance = Some(instance);
plugin.state = PluginState::Loaded; plugin.state = PluginState::Loaded;
log::info!("Loaded papkin plugin: {}", plugin.name); log::info!("Loaded PatchBukkit plugin: {}", plugin.name);
} }
Err(e) => { Err(e) => {
plugin.state = PluginState::Errored; plugin.state = PluginState::Errored;
log::error!("Failed to load papkin plugin {}: {:?}", plugin.name, e); log::error!("Failed to load PatchBukkit plugin {}: {:?}", plugin.name, e);
} }
} }
} }