跳到主要内容

MagmaCore 开发者指南

生成的 Java 参考提供可搜索的类、方法与签名,并记录各模块的源码版本和提交。

MagmaCore 是通过 shade 打包进使用方插件的库。它不是独立服务器插件,不应在 depend 中将其当作玩家能够安装的 MagmaCore 插件 JAR。

依赖与打包​

当前开发坐标为 com.magmaguy:MagmaCore:2.2.0-SNAPSHOT。它发布在 MagmaGuy 发布仓库,而不是快照仓库;快照仓库只保存较旧的 1.x 快照。快照内容可能改变而版本字符串不变,而且已发布的构建不会随每次插件发布而更新,因此它可能比当前插件中 shade 的 MagmaCore 更旧。2026年10月5日发布的构建已包含下文的免重启更新和对局 API。若要针对更新的未发布改动编译,请从源码构建 MagmaCore 并发布到 Maven Local,见库变更后重建使用方。需要可复现构建时,请记录实际解析的构件。

Gradle Kotlin DSL
repositories {
maven("https://repo.magmaguy.com/releases")
}

dependencies {
implementation("com.magmaguy:MagmaCore:2.2.0-SNAPSHOT")
}
Maven sections
<repositories>
<repository>
<id>magmaguy-releases</id>
<url>https://repo.magmaguy.com/releases</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>MagmaCore</artifactId>
<version>2.2.0-SNAPSHOT</version>
</dependency>
</dependencies>

这些声明用于解析依赖。还需配置 shading 任务,将其包含在最终插件 JAR 中。遵循集成需求相同的现有使用方的重定位规则,改变包名时检查基于字符串的反射查找。分发包将 org.luaj、org.reflections 和 javassist 重定位到 com.magmaguy.shaded,并排除编译期使用的 javax.annotation 类。

每个插件都可以加载自己的库副本。不同插件类加载器中的同名 Java 类是不同类型。请使用明确的跨插件约定,例如 EliteMobs Lua 技能服务与位置注册表适配器。不要将其他插件私有的 MagmaCore 对象强制转换为你的副本中的类型。

模块与职责​

模块职责
core插件生命周期、配置、命令、菜单、对局、位置查询、Lua 脚本、Nightbreak 内容和共享工具
nms:coreNMSManager、NMSAdapter 及不依赖版本的 EasyMinecraftGoals 接口
nms:v*NMS 约定的服务器版本实现
dist包含核心与活动适配器的 shaded 分发包

共享附魔、物品操作、账号处理、设置菜单、目录与更新属于核心服务。为使用方添加行为时,复用负责该功能的组件。

插件生命周期​

最小核心生命周期遵循现有使用方的模式:

CoreConsumer.java
package example;

import com.magmaguy.magmacore.MagmaCore;
import org.bukkit.plugin.java.JavaPlugin;

public final class CoreConsumer extends JavaPlugin {
@Override
public void onLoad() {
MagmaCore.createInstance(this);
}

@Override
public void onEnable() {
MagmaCore.onEnable(this);
}

@Override
public void onDisable() {
MagmaCore.shutdown(this);
}
}

这种初始化不只是获取一个工具对象。它会初始化账号处理、共享命令、监听器和临时方块支持。重载方法 createInstance(plugin, NightbreakPluginSpec) 用于提供插件专属的共享命令文案。

优先使用显式接收所属插件的方法。getInstance() 指向当前加载库副本的单例,请求方插件在实例创建时确定。不要用它推断每个使用方的所有权。

shutdown(plugin) 清除该插件的下载器、内容刷新器、初始化和更新器注册,之后也会关闭当前加载副本的共享运行时。它不只是删除一条注册记录。请在你的插件关闭时,对自己嵌入的库调用;不要为了重置集成而关闭其他插件的库。

在 onLoad 中调用 createInstance,使插件的配置归档所有者能在其他插件为其导入内容之前注册。归档通过目标插件自己的 shaded 实现执行;不要使用你的 MagmaCore 副本解释其他插件的淘汰规则。

分阶段启动可使用 startInitialization,传入异步工作、同步工作、成功和失败回调。它会在调用异步初始化之前归档匹配的过时配置。Bukkit 世界和实体操作应放在同步阶段。耗时异步工作应在阶段之间检查 isShutdownRequested(plugin)。getInitializationState 和 isPluginReady 提供初始化管理器状态。

免重启插件更新​

NightbreakPluginBootstrap.registerStandardCommands 会把 applypluginupdate 与其他共享子命令一起注册。它通过在同一次服务器会话中禁用你的插件、替换其 jar 并重新启用来换入已下载的更新,因此 onDisable 必须取消任务、注销监听器,并释放所有会让旧类加载器继续存活的引用。主类位于 com.magmaguy. 下、且依赖或软依赖你的插件的已启用插件会随之重载。只要有其他插件依赖你的插件,换入就会被拒绝并要求重启。服务器管理员一侧的说明请参阅不重启应用更新。

如果你的插件有部分内容无法就地重载,请在更新检查开始之前调用 NightbreakPluginHotSwap.requireRestartForUpdates(plugin, reason),并把 false 作为 NightbreakPluginUpdater.setAutoDownloadConfigDefault 的第二个参数传入,这样 config.yml 就不会提供 applyPluginUpdatesWithoutRestart。当它所依赖的插件被换入时,该插件仍会使用当前 jar 重载。NightbreakPluginUpdater.onPluginUpdateDownloaded(plugin, listener) 会在经过验证的更新到达 update 文件夹后,在下载线程上运行监听器。

NMS 与数据包实体​

仅在插件需要时,通过 com.magmaguy.easyminecraftgoals 中的 NMSManager.initializeAdapter(plugin) 初始化 NMS。使用依赖适配器的功能前,检查 NMSManager.isEnabled()。初始化可能失败,也可能发现服务器版本不受支持。

分发包包含以下适配器系列:

适配器Minecraft 版本
v1_21_R31.21.4
v1_21_R41.21.5
v1_21_R51.21.6, 1.21.7, 1.21.8
v1_21_R61.21.9, 1.21.10
v1_21_R7_spigot, v1_21_R7_paper1.21.11,Spigot 与 Paper 分别实现
v2626.1 及当前 26.x 适配器系列

选中适配器并不保证所有未来服务器版本兼容。NMSManager 中的运行时选择器决定当前服务器能否加载适配器。早于 1.21.4 的版本不在当前适配器范围内。

EasyMinecraftGoals 管理仅通过数据包存在的实体、可见性与交互路由,以及移动和寻路工具。它们不是普通世界实体。应通过所属 API 管理,并在适配器仍可用时清理你的使用方创建的对象。

位置与保护查询​

com.magmaguy.magmacore.location.LocationQueryRegistry 提供地牢及区域保护查询,包括 isInAnyDungeon、isInAnyProtectedRegion 和 canBuild。

通过 registerDungeonLocator 或 registerProtectionProvider 注册自定义提供方;所属插件停用时注销同一个提供方。注册表包含现有插件适配器,并能发现跨插件地牢提供方,而无需使用方共用一个 MagmaCore 类加载器。

请选择符合操作的查询。位于地牢外不等于拥有该位置的建造权限。涉及 Bukkit 或保护插件的查询应在服务器线程执行。

对局​

对局生命周期位于 com.magmaguy.magmacore.match。在启用时调用一次 MatchCore.enable(plugin),然后继承 Match,把由 MatchSettings.builder() 构建的 MatchSettings 传给其构造函数,并在子类构造完成后调用 open()。游戏逻辑写在受保护的钩子中,例如 onJoin、onStart、onDeath 和 onLeave。MagmaCore.shutdown(plugin) 会销毁该插件剩余的对局。

核心本身不触发任何 Bukkit 事件。它调用设置中指定的 MatchApi,因此由你的插件决定公开哪些事件。可取消的回调通过返回 false 或抛出异常来否决该步骤。每个插件的副本只跟踪自己的对局;玩家元数据标记 magmacore_match 会告诉其他副本该玩家已在某个对局中。

MatchSettings.builder().permission(...) 设置玩家加入所需的权限。重写 hasJoinPermission(player) 可以逐个玩家做出判断,例如让管理员无需该权限也能进入。因死亡(LeaveReason.DIED)而离开的参与者,会在被移出之前恢复满生命值,这样在退出途中被移除的最大生命值加成,仍能保持满血的比例。对局期间的其他退出方式会保留已受的伤害,而对局结束时仍在其中的玩家会被治疗。这两项行为都是在 2026 年 10 月 5 日发布的构建之后加入的。

com.magmaguy.magmacore.instance 中的旧对局类(包括 MatchInstance)已被移除。InstanceProtector 仍保留在那里,并由 MagmaCore.enableWorldProtections(plugin) 注册。

Lua Mind 宿主​

MagmaCore 为宿主插件编译用 Lua 编写的 Mind 程序。脚本格式见行为程序。宿主创建自己的 LuaMindModuleRegistry,用 openOwner(namespace) 为其命名空间打开一个所有者,用所有者的 registerModule 注册模块,并从所有者的 validateProgram 获得 LuaMindDefinition。对该定义的每次 instantiate 调用,都会为一个实体构建一个全新的程序,并带有它自己的 Lua 环境。下面的钩子比 2026 年 10 月 5 日发布的构建更新。

  • 检查模块。 LuaMindModuleRegistry.inspectModule(sourceName, source) 在不注册模块的情况下读取其 id、revision、依赖和 settings 默认值。LuaMindModuleDescriptor.settings() 保存 Double、Boolean、String 或 List<String> 类型的值。MagmaCore 不会把设置交给脚本。想要按生物设置值的宿主,需要把自己的值合并到这些默认值之上并公开它们,FreeMinecraftModels 的宠物就是通过 c.settings 这样做的。
  • 扩展回调上下文。 LuaMindDefinition.instantiate(LuaMindContextExtension) 会把你的字段添加到每个回调的上下文表中。extend(table, context, contribution) 会在 Lua 看到该表之前收到它、该回调的 MindContext,以及声明该回调的模块的 id(或程序自己的 id)。它在服务器线程上、在该回调的执行预算之内运行,因此它的 CPU 时间计入程序的 cpu_micros,抛出异常会使该回调失败。请用 rawset 或 LuaTableSupport.lazyField 添加字段,后者会为其他所有键保留该表现有的 __index。不要替换该表的元表或其 __index,因为内置部分是通过它们读取的,也不要覆盖 tick、generation、entity、memory、perception、actuator 或 actions。在 extend 中读取内置部分会为该回调构建它。当扩展持有按实体划分的状态时,请为每次 instantiate 调用传入单独的扩展。
  • 探测间隔。 Java 行为可以重写 MindBehavior.probeInterval()(相当于 Lua 的 probe_interval),使其在停止状态下每 N 个 tick 询问一次 canStart。它必须在 1 到 MindBehavior.MAX_PROBE_INTERVAL(200)之间;MindProgram 会拒绝其他值。默认值 1 表示每个 tick 都询问。MindSensor 在其身体第一次被 tick 的那个 tick 感知,此后每 intervalTicks() 个 tick 感知一次,且每个实体有各自的相位。
  • 飞行。 MindActuator.steerFlight(Vector) 在该构建中已经存在,它让 FLYING 身体按该速度飞行一个 tick,并需要 MOVE 和 LOOK 租约。新增的是它的上限和 Lua 的 steer_flight:MindActuator.MAX_FLIGHT_SPEED 为每 tick 4 个方块,更快的速度会被缩小到该值。RouteFlight 的速度也在此封顶,因此设置为超过每秒 80 个方块的路线,会以每秒 80 个方块飞行。

库变更后重建使用方​

使用 JDK 21,并通过 ./gradlew publishToMavenLocal 将 MagmaCore 发布到 Maven Local;Windows 下使用 .\gradlew.bat publishToMavenLocal。确认使用方解析该仓库及所需版本,再重建其 shaded JAR。替换 Maven Local 中的库不会更新已经构建的插件。

已安装插件的 API 见开发者索引。这类集成通常使用 provided 或 compileOnly;MagmaCore 的嵌入式库打包约定不同。