一、【Minecraft Paper 服务器插件开发】Paper插件的项目搭建及简要配置 项目搭建Paper 团队主要使用 IntelliJ IDEA本文档将围绕该 IDE 进行讲解但下方步骤仅需小幅修改即可适配其他 IDE。Paper 采用 Gradle 作为构建系统配套工具均基于 Gradle 开发。下文绝大多数代码可改造适配 Maven 等其他构建工具但本文仅覆盖Gradle Kotlin DSL写法。如需将 Maven 项目迁移至 Gradle可查阅官方迁移文档https://docs.gradle.org/current/userguide/migrating_from_maven.html新建项目打开 IDE选择新建项目。在 IntelliJ 中点击「New Project」项目类型选择Gradle - Kotlin DSL点击创建。创建完成后会自动打开build.gradle.kts你可在此文件中添加项目依赖。将 Paper 作为项目依赖想要引入 Paper 依赖需要在build.gradle.kts中配置 Paper 仓库与依赖声明。提示如需锁定指定构建版本将版本号末尾的替换为完整构建标识例如{版本号}.build.25-alpha代表对应版本的第25个Alpha测试构建。26.1对应1.21.11及更早版本版本号格式为{版本号}-R0.1-SNAPSHOT无法单独指定某一个构建。Gradle 配置文档https://docs.papermc.io/paper/dev/project-setup/#tab-panel-77Maven不推荐使用https://docs.papermc.io/paper/dev/project-setup/#tab-panel-78若使用 Maven 并希望自动拉取最新构建版本使用区间写法[26.1.2.build,)锁定固定构建则填写完整版本26.1.2.build.74-stable。pom.xml 配置示例projectrepositoriesrepositoryidpapermc/idurlhttps://repo.papermc.io/repository/maven-public//url/repository/repositoriesdependenciesdependencygroupIdio.papermc.paper/groupIdartifactIdpaper-api/artifactIdversion[26.1.2.build,)/versionscopeprovided/scope/dependency/dependencies/project配置 src 源码目录备注若你的 IDE 已自动生成 src 目录可跳过本节。手动创建目录结构新建src文件夹内部创建main在 main 内新建两个文件夹javaJava源码、resources资源文件。完整目录结构example-plugin/ ├─ build.gradle.kts ├─ settings.gradle.kts └─ src/ └─ main/ ├─ java/ └─ resources/java 源码目录规范所有 Java 源代码存放于 java 文件夹必须通过包分层管理代码。本示例创建包io.papermc.testplugin并在包内新建主类ExamplePlugin.java。目录层级example-plugin/ ├─ build.gradle.kts ├─ settings.gradle.kts └─ src/ └─ main/ ├─ java/ │ └─ io/ │ └─ papermc/ │ └─ testplugin/ │ └─ ExamplePlugin.java └─ resources/包命名规范前文示例中ExamplePlugin类位于io.papermc.testplugin包下。包是代码分层管理机制本质是文件夹用于归类功能相近的类。Oracle 官方包教程https://docs.oracle.com/javase/tutorial/java/package/packages.html包命名规范文档https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html优先使用域名倒序作为基础包名例官网域名 papermc.io → 基础包io.papermc无自有域名可使用 GitHub 用户名用户名为 torvalds →io.github.torvalds末尾追加项目名保证全平台包名唯一例项目名为 ExamplePlugin → 完整包io.github.torvalds.exampleplugin插件主类主类是插件唯一入口整个插件仅允许一个类继承JavaPlugin。开发规范不建议直接命名为 Main建议使用插件名称命名例如插件名为 Example主类命名为 ExamplePlugin。ExamplePlugin.java 完整示例packageio.papermc.testplugin;importnet.kyori.adventure.text.Component;importorg.bukkit.Bukkit;importorg.bukkit.event.EventHandler;importorg.bukkit.event.Listener;importorg.bukkit.event.player.PlayerJoinEvent;importorg.bukkit.plugin.java.JavaPlugin;publicclassExamplePluginextendsJavaPluginimplementsListener{OverridepublicvoidonEnable(){// 注册当前类为事件监听器Bukkit.getPluginManager().registerEvents(this,this);}// 玩家进入服务器事件EventHandlerpublicvoidonPlayerJoin(PlayerJoinEventevent){event.getPlayer().sendMessage(Component.text(Hello, event.getPlayer().getName()!));}}resources 资源目录resources 文件夹用于存放插件配置核心文件plugin.yml配置文档参考https://docs.papermc.io/paper/dev/plugin-yml使用 IntelliJ Minecraft Development 插件快速创建项目你也可以借助 Minecraft Development IntelliJ 插件 一键生成项目。备注该教程仅支持 IntelliJ IDEA其他 IDE 请遵循上文手动搭建流程。安装 Minecraft Development 插件打开文件 设置 插件File Settings Plugins在市场Marketplace分类搜索Minecraft Development完成安装安装完成后点击重启 IDERestart IDE按钮生效。通过插件新建项目安装插件后打开文件 新建 项目File New Project…左侧分类选择Minecraft。填写项目参数说明表字段说明Name项目文件夹名称Location项目本地存储路径Platform Type开发目标类型固定填写PluginPlatform服务端平台固定填写PaperMinecraft Version目标 Minecraft 游戏版本Plugin Name插件对外展示名称Main Class插件主类必须继承JavaPluginOptional Settings可选配置作者、官网、插件描述等不填不影响插件运行Build System构建工具Paper 推荐 Gradle也可选择 MavenPaper Manifest是否启用新式 Paper 插件paper-plugin.yml目前仍处于开发阶段不推荐开启Group IDMaven/Gradle 分组标识规范为域名倒序无域名可用io.github.你的用户名无 GitHub 则用me.你的用户名Artifact ID项目构件标识一般与项目 Name 保持一致Version项目版本号默认1.0-SNAPSHOT开发阶段无需严格定义JDK编译使用的 Java 版本最低 Java 25 及以上填写完成点击「Create」IDEA 将自动生成完整插件项目结构。插件运行原理插件是用于拓展 Minecraft 服务端功能的程序使用 JVM 系语言开发Java、Kotlin、Groovy、Scala。插件存放于服务端根目录的plugins文件夹以.jar压缩包形式加载。每个插件都在plugin.yml中声明主类该类必须继承 JavaPlugin是插件执行入口同时定义插件全生命周期回调方法。不建议在主类构造函数中编写业务代码插件加载阶段无法保证 Bukkit API 可用。初始化逻辑请放在onLoad方法中同时禁止手动调用插件主类构造函数会引发插件运行异常。插件生命周期插件在服务端运行时会经历加载/卸载流程加载时完成初始化与启用卸载时执行停用与资源回收。初始化阶段onLoad插件被载入内存时触发onLoad方法用于初始化底层资源。此阶段绝大多数 Bukkit API 未就绪禁止调用游戏相关接口。启用阶段onEnable插件启用时触发onEnable用于初始化运行所需资源。该阶段插件已完成初始化但服务端尚未开始游戏刻度循环可安全注册事件监听器但大量游戏API仍不可调用。适合操作建立数据库连接、启动后台线程等无法在 onLoad 执行的逻辑。停用阶段onDisable插件卸载前触发onDisable用于清理插件占用的全部资源。会在所有插件统一卸载前执行负责持久化本地数据、关闭数据库连接等回收操作。事件监听器事件机制允许插件监听服务端发生的各类行为对应事件触发时自动执行自定义代码相比循环轮询性能更高。示例玩家进入服务器时触发PlayerJoinEvent事件完整文档https://docs.papermc.io/paper/dev/event-listeners部分事件支持取消cancellable取消后事件对应的行为不会生效。示例PlayerMoveEvent玩家移动事件取消后玩家无法移动常用于反作弊限速检测。编写监听器必须注意事件热度高频触发的事件称为“热事件”例如玩家移动事件监听器内禁止执行复杂耗时逻辑极易造成服务器卡顿。优化方案前置快速判断不满足处理条件直接 return例如仅当玩家更换方块坐标时才执行逻辑坐标未变化直接跳过。指令系统指令允许玩家、控制台、RCON、命令方块在服务端执行插件代码由插件注册、指令发送者调用。示例服务端内置/help指令玩家可在聊天框或命令方块执行。指令支持参数参数以空格分隔例/give Notch diamond参数数组为[Notch, diamond]。权限系统权限用于管控指令、事件功能的访问权限由插件注册可被其他插件读取权限可分配给玩家或权限组支持层级继承。示例插件定义example.command.help为example.command的子权限拥有父权限的玩家自动获得子权限。备注权限管理插件支持通配符*授予example.command.*会匹配所有以该前缀开头的权限。强烈不推荐使用全局通配符*全部权限存在严重安全风险还会产生非预期功能副作用谨慎使用。配置文件插件可自定义配置文件用于存储运行所需数据例如自定义方块ID。配置文件存放于服务端plugins目录下对应插件的数据文件夹服务端提供标准 YAML 读写API。配置文档https://docs.papermc.io/paper/dev/plugin-configurations任务调度插件可调度延时/循环任务例如延迟5秒执行逻辑。时间换算服务器正常运行下 20 tick 1 秒延时100 tick 等价5秒。注意服务器卡顿会导致任务延后执行例如TPS仅10时100tick任务实际耗时10秒。Java 原生Thread#sleep()会阻塞主线程直接造成服务器卡死禁止在主线程使用统一使用官方Scheduler调度API。调度文档https://docs.papermc.io/paper/dev/scheduler富文本组件ComponentMinecraft 1.7 引入富文本组件机制插件可向玩家发送带格式消息颜色、加粗、可点击链接。旧版仅支持传统颜色代码格式受限。Paper 内置 Adventure 富文本库快速构建格式化消息。Adventure 官方文档https://docs.papermc.io/adventure/Paper 适配文档https://docs.papermc.io/paper/dev/component-api/introductionPaper新式插件paper-plugin.yml 实验性功能Paper 新式插件允许开发者使用 Mojang 原生数据包等现代特性拓展 Paper API 能力边界。实验性功能接口随时可能大幅调整不建议生产环境直接使用引导器Bootstrapperhttps://docs.papermc.io/paper/dev/getting-started/paper-plugins/#bootstrapper加载器Loaderhttps://docs.papermc.io/paper/dev/getting-started/paper-plugins/#loaders新旧差异https://docs.papermc.io/paper/dev/getting-started/paper-plugins/#differences使用方式与传统 Bukkit 插件类似需在资源目录添加paper-plugin.yml但不能完全替代plugin.yml二者配置声明规则存在区别。同一Jar包可同时携带plugin.ymlpaper-plugin.yml两份配置。paper-plugin.yml 基础示例name:Paper-Test-Pluginversion:1.0main:io.papermc.testplugin.TestPlugindescription:Paper 测试插件api-version:26.1.2bootstrapper:io.papermc.testplugin.TestPluginBootstraploader:io.papermc.testplugin.TestPluginLoader依赖声明新式插件将依赖分为两大模块配置示例dependencies:bootstrap:# RegistryPlugin 在启动阶段注册数据运行时无需依赖仅引导阶段加载RegistryPlugin:load:BEFORErequired:truejoin-classpath:true# 默认trueserver:# 运行时必需插件在本插件加载完成后再加载RequiredPlugin:load:AFTERrequired:true# 本插件无法访问该插件的类路径join-classpath:false分类说明bootstrap引导阶段依赖用于 Bootstrapper 引导器代码server服务运行阶段依赖插件核心业务逻辑使用单条依赖配置参数详解RegistryPlugin:load:BEFORE# 默认 OMITrequired:true# 默认 truejoin-classpath:true# 默认 trueload可选值BEFORE/AFTER/OMIT控制目标插件在本插件之前/之后加载OMIT 加载顺序无定义requiredtrue缺少该插件则本插件加载失败false可选依赖join-classpathtrue本插件可读取目标插件内部类与依赖false隔离类加载器多插件互相前置依赖会形成加载死循环服务器启动失败。依赖场景示例# 1. 前置必需依赖 ProtocolLibProtocolLib:load:BEFORErequired:true# 2. 可选后置依赖本插件加载完成后再加载商店插件SuperShopsXUnlimited:load:AFTERrequired:false# 3. 需要读取对方内部代码开启类路径共享SuperDuperTacoParty:required:truejoin-classpath:true新式插件设计目标为未来官方API提供底层框架对齐原版Mojang原生机制通过引导器Bootstrapper在服务端启动前加载插件资源解锁更多原生拓展能力。引导器 Bootstrapper实现PluginBootstrap接口并在paper-plugin.yml声明类路径即可启用自定义引导器。TestPluginBootstrap.javapublicclassTestPluginBootstrapimplementsPluginBootstrap{Overridepublicvoidbootstrap(BootstrapContextcontext){}OverridepublicJavaPlugincreatePlugin(PluginProviderContextcontext){// 支持自定义构造参数传入主类returnnewTestPlugin(My custom parameter);}}引导器可自定义插件初始化流程向主类构造函数传参当前功能较少仍处于高度实验阶段后续API会持续改动。加载器 Loader实现PluginLoader接口在配置文件声明全类名自定义插件类加载环境。当前核心用途动态引入外部依赖库构建插件专属类路径。TestPluginLoader.javapublicclassTestPluginLoaderimplementsPluginLoader{Overridepublicvoidclassloader(PluginClasspathBuilderclasspathBuilder){// 引入本地Jar依赖classpathBuilder.addLibrary(newJarLibrary(Path.of(dependency.jar)));// Maven远程依赖解析器MavenLibraryResolverresolvernewMavenLibraryResolver();resolver.addDependency(newDependency(newDefaultArtifact(com.example:example:version),null));resolver.addRepository(newRemoteRepository.Builder(paper,default,https://repo.papermc.io/repository/maven-public/).build());classpathBuilder.addLibrary(resolver);}}支持两种依赖库类型JarLibrary本地Jar文件MavenLibraryResolverMaven远程仓库依赖拉取Maven中央库必须使用镜像源直接访问maven.org违反服务条款会触发访问限流。推荐使用Paper内置镜像配置代码resolver.addRepository(newRemoteRepository.Builder(central,default,MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR).build());直接使用Maven中央源会在控制台输出警告日志。新旧插件核心差异1. Bukkit序列化机制新式插件仍兼容 Bukkit 序列化工具org.bukkit.configuration.serialization但自定义类不会自动注册序列化。调用ConfigurationSection#getObject读取自定义对象前必须手动执行ConfigurationSerialization#registerClass(Class)注册类。2. 类加载隔离机制默认情况下新式插件互相隔离无法读取对方内部类与依赖仅在配置join-classpath: true时才能访问目标插件类加载器。PluginName:join-classpath:true# 允许读取该插件内部代码注意单向生效其他插件无法反向访问你的插件类加载器。3. 加载顺序逻辑拆分新式插件不再依靠基础 dependencies 字段控制加载顺序完全拆分依赖与加载时序配置实现精细化类路径共享。加载顺序配置文档https://docs.papermc.io/paper/dev/getting-started/paper-plugins/#dependency-declaration4. 指令注册方式新式插件不再通过paper-plugin.yml的 commands 节点注册指令统一使用 Brigadier 原生指令API 在代码中动态注册。5. 循环加载报错机制传统Bukkit插件会自动尝试修复循环依赖新式插件不会自动处理检测到加载死循环直接抛出致命错误并终止服务端启动。报错示例[ERROR]: [LoadOrderTree] [ERROR]: [LoadOrderTree] Circular plugin loading detected: [ERROR]: [LoadOrderTree] 1) Paper-Test-Plugin1 - Paper-Test-Plugin - Paper-Test-Plugin1 [ERROR]: [LoadOrderTree] Paper-Test-Plugin1 loadbefore: [Paper-Test-Plugin] [ERROR]: [LoadOrderTree] Paper-Test-Plugin loadbefore: [Paper-Test-Plugin1] [ERROR]: [LoadOrderTree] Please report this to the plugin authors of the first plugin of each loop or join the PaperMC Discord server for further help. [ERROR]: [LoadOrderTree] 循环依赖问题需要开发者自行调整依赖加载顺序解决。plugin.yml 传统插件配置文件plugin.yml是传统Bukkit/Paper插件的核心配置文件存放插件基础信息、依赖、权限、指令等元数据。文件路径项目src/main/resources/plugin.yml完整示例name:ExamplePluginversion:1.0.0main:io.papermc.testplugin.ExamplePlugindescription:示例演示插件author:PaperMCwebsite:https://papermc.ioapi-version:26.1.2字段详解备注字段无固定顺序带*标记为必填项。name*插件名称日志、插件列表展示若配置 prefix 日志会优先显示前缀。name: ExamplePluginversion*插件版本号日志与插件信息指令展示。version: 1.0.0main*插件主类全限定路径必须继承 JavaPlugin插件唯一入口。main: io.papermc.testplugin.ExamplePlugindescription插件简短功能描述/plugins 指令展示。description: 示例演示插件author / authors插件作者单作者使用 author多作者数组使用 authorsauthor:PaperMCauthors:[PaperMC,SpigotMC,Bukkit]contributors非核心维护贡献者列表contributors: [PaperMC, SpigotMC, Bukkit]website插件官网/GitHub地址website: https://papermc.ioapi-version目标PaperAPI版本1.20.5起支持小版本号低于该版本的服务端拒绝加载插件合法区间 1.13 ~ 26.1.2。api-version: 26.1.2备注未填写会被识别为遗留插件控制台输出警告。load插件加载时机可选STARTUP世界生成前/POSTWORLD世界生成后默认load: STARTUPprefix日志输出自定义前缀替代插件名称prefix: EpicPaperMCHypePluginlibraries远程Maven依赖服务端自动下载引入无需手动打包依赖shadelibraries:-com.google.guava:guava:30.1.1-jre-com.google.code.gson:gson:2.8.6中央仓库地址可通过环境变量PAPER_DEFAULT_CENTRAL_REPOSITORY、系统属性org.bukkit.plugin.java.LibraryLoader.centralURL自定义。permissions权限节点定义控制功能访问权限permissions:permission.node:description:基础权限节点default:opchildren:permission.node.child:trueanother.permission.node:description:第二个权限节点default:notop参数说明description权限说明文本default默认持有者op/notop/true/false未填写继承全局 default-permission默认opchildren子权限true代表拥有父权限自动获得子权限default-permission未单独设置 default 的权限默认归属default-permission: truepaper-plugin-loader新式插件自定义加载器全类名实验性功能paper-plugin-loader: com.example.paperplugin.MyPluginLoaderpaper-skip-librariestrue跳过自动下载libraries节点依赖交由自定义Loader管理依赖实验性功能paper-skip-libraries: falsecommands 指令配置节点传统插件可在yml声明指令元数据commands:command:description:指令功能描述usage:/command argaliases:[cmd,command]permission:permission.nodepermission-message:你没有权限执行该指令description指令说明/help 查询展示usage指令参数格式提示aliases指令别名列表permission执行所需权限节点玩家仅能看见拥有权限的指令permission-message无权限时提示文本依赖相关配置depend 内插件会在本插件前加载互相依赖会形成死循环导致启动失败。depend强制前置依赖缺少则插件加载失败depend: [Vault, WorldEdit]softdepend可选前置依赖缺失不影响插件加载仅部分功能失效softdepend: [Vault, WorldEdit]loadbefore声明本插件需要在指定插件之前加载用于对外提供APIloadbefore: [Vault, FactionsUUID]provides声明本插件替代某插件/库其他依赖该插件的程序会将本插件视为目标依赖存在provides: [SomeOtherPlugin]paperweight-userdev 开发工具paperweight 是 Paper 官方自研构建工具集paperweight-userdev 是配套 Gradle 插件用于开发阶段直接访问服务端内部代码NMS。前置要求掌握基础 Gradle Kotlin DSL完整可运行示例插件仓库https://github.com/PaperMC/paperweight-test-plugin工具作用这是官方唯一支持的NMS访问方案直接分发服务端Jar违反Minecraft用户协议EULA。Spigot及1.20.5前Paper使用混淆映射开发体验极差该工具在开发阶段提供完整反混淆代码提示打包时自动重映射适配线上混淆服务端。注意反射代码不会自动重映射如需反射使用原生名称可引入库https://github.com/jpenilla/reflection-remapper26.1版本重大改动Minecraft 26.1起官方移除服务端混淆Paper不再支持混淆插件重混淆功能对26.1开发包完全失效本节仅作旧版本参考。引入插件build.gradle.kts 配置plugins{id(io.papermc.paperweight.userdev)version2.0.0-beta.21}Gradle版本要求使用最新稳定版Gradle升级文档https://docs.gradle.org/current/userguide/gradle_wrapper.html当前版本支持1.17.1及以上Minecraft版本开发包仅最新版官方提供技术支持旧版本问题会要求升级。疑难问题可前往PaperMC Discord #build-tooling-help 频道咨询https://discord.gg/PaperMCSNAPSHOT预览版仓库配置settings.gradle.ktspluginManagement{repositories{gradlePluginPortal()maven(https://repo.papermc.io/repository/maven-public/)}}引入开发包依赖项目缺少开发包会直接报错在dependencies块添加dependencies{// 其他依赖paperweight.paperDevBundle(26.1.2.build.)}提示引入开发包后请删除原paper-api依赖开发包已内置完整API。自定义Java工具链部分版本开发包对JDK版本有限制执行 paperweightUserdevSetup 补丁失败时可手动指定JDK示例 1.17.1适配paperweight{javaLauncherjavaToolchains.launcherFor{// 场景示例1.17.1原生编译JDK16开发包不兼容21但编译使用JDK25languageVersionJavaLanguageVersion.of(17)}}多项目示例仓库https://github.com/PaperMC/paperweight-test-plugin/tree/multi-project重混淆打包仅1.21.11及以下旧版本26.1起该功能彻底失效仅作历史参考reobfJar任务生成适配Spigot混淆映射的插件Jar可在标准Paper服务端运行。输出目录build/libs-dev后缀包Mojang原生映射未混淆无法在非Paper服务端使用Shadow打包兼容项目引入shadow插件时工具会自动以打包后的Jar作为重混淆输入-dev-all.jar是打包但未混淆产物。编译时自动执行重混淆配置tasks.assemble{dependsOn(tasks.reobfJar)}1.20.5及以上版本映射规则1.20.5起Paper服务端原生使用Mojang无混淆映射CraftBukkit类不再分版本包插件按需自动反混淆加载绝大多数流程由paperweight自动处理。默认映射判定规则无清单映射声明的Spigot/Bukkit插件默认判定为Spigot混淆映射首次加载需反混淆无清单映射声明的Paper插件默认判定为Mojang原生映射无需反混淆打包输出映射模式1. 输出Mojang原生映射推荐优势跳过服务端启动时一次性重映射小版本间兼容性更好缺陷无法在Spigot服务端运行移除所有 dependsOn(reobfJar)添加配置paperweight.reobfArtifactConfigurationio.papermc.paperweight.userdev.ReobfArtifactConfiguration.MOJANG_PRODUCTION2. 输出Spigot混淆映射兼容Spigot与Paper双端配置paperweight.reobfArtifactConfigurationio.papermc.paperweight.userdev.ReobfArtifactConfiguration.REOBF_PRODUCTION备注Gradle Groovy DSL需调用静态方法getMOJANG_PRODUCTION()获取枚举。