什么是 Cumulus?
基岩版有一个很酷的专属功能叫做表单。
Cumulus 是我们在 Geyser 和 Floodgate 中使用的表单 API。
源代码可在此处获取。你可以通过Floodgate API或Geyser API访问 Cumulus API。
基岩版支持三种类型的表单:
- 模态表单(ModalForm)
- 简单表单(SimpleForm)
- 自定义表单(CustomForm)
我们将从最简单的表单类型开始,逐一介绍它们,最后介绍最复杂的 表单类型。
之后,你将了解每个组件的概述。
然后我们会讨论如何发送表单、接收响应以及一些高级用法。
模态表单(ModalForm)
虽然这是最简单的表单类型,但它的自定义性也最差。
它包含一个标题、描述(内容)和两个按钮。

图片中使用的代码:
ModalForm.builder()
.title("Title")
.content("Content")
.button1("Button 1")
.button2("Button 2")
简单表单(SimpleForm)
虽然它比模态表单稍微复杂一些,但也具有更多的自定义性。
它仍然局限于标题、内容和按钮,但这些按钮也可以包含图片,并且按钮数量没有最少和最多两个的限制。

图片中使用的代码:
SimpleForm.builder()
.title("Title")
.content("Content")
.button("Button without an image")
.button("Button with URL image", FormImage.Type.URL, "https://github.com/GeyserMC.png?size=200")
.button("Button with path image", FormImage.Type.PATH, "textures/i/glyph_world_template.png")
自定义表单(CustomForm)
虽然自定义表单是我们列表中的最后一个(因此也是最复杂的一个),但它的自定义性也最强。
这种表单由标题、内容和一系列不同的组件组成,例如标签、滑块和输入框。
有关你可以使用的每个组件以及适用于哪种表单类型的更多信息,请参见组件。

图片中使用的代码:
CustomForm.builder()
.title("Title")
.dropdown("文本", "选项 1", "选项 2")
.input("输入框", "占位符")
.toggle("开关")
.slider("文本", 0, 10, 1, 5)
发送表单
在你决定要使用哪种表单类型并完成实际内容的填写后,就可以将表单发送给基岩版玩家了。
你可以通过调用 API 并将表单发送到玩家的 UUID 来实现:
FloodgateApi.getInstance().sendForm(uuid, form); // 或 #sendForm(uuid, formBuilder)
或 者你可以使用玩家的 FloodgatePlayer 实例来实现:
FloodgatePlayer player = FloodgateApi.getInstance().getPlayer(uuid);
player.sendForm(form); // 或 #sendForm(formBuilder)
因此,你可以通过类似以下的方式以非常简洁的方式创建并发送表单:
FloodgatePlayer player = FloodgateApi.getInstance().getPlayer(uuid);
...
player.sendForm(
CustomForm.builder()
.title("我的超酷标题")
.label("10/10 内容")
);
接收客户端的响应
我们可以向客户端发送表单固然很好,但我们也希望能够从客户端获取响应并进行处理。
我们可以使用一个(或多个)结果处理器来实现这一点。最常用的结果处理器有:validResultHandler(BiConsumer<Form, ValidFormResponseResult> | Consumer<ValidFormResponseResult>)、invalidResultHandler、closedResultHandler 和 closedOrInvalidResultHandler。
以下是一个使用结果处理器的示例:
CustomForm.builder()
.title("geyser.auth.login.form.details.title")
.label("geyser.auth.login.form.details.desc")
.input("geyser.auth.login.form.details.email", "account@geysermc.org", "")
.input("geyser.auth.login.form.details.pass", "123456", "")
.closedOrInvalidResultHandler(() -> buildAndShowLoginDetailsWindow(session))
.validResultHandler(response -> session.authenticate(response.next(), response.next())));
高级用法
FormBuilder 还支持翻译构建器中使用的数据。
要添加翻译器,你可以使用 translator(BiFunction<String, String, String>) 或 translator(BiFunction<String, String, String>, String) 方法:
ModalForm form = ModalForm.builder()
.translator(this::translate, userLanguage)
.title("Title")
.content("Content")
.button1("translate.button1")
.button2("translate.button2")
.build();
public String translate(String key, String locale) {
// 此方法将为每个字符串调用,在这个例子中会调用4次:
// Title、Content、translate.button1、translate.button2
// 这里放入你自己的翻译逻辑
// 返回替换键的值
}
或者你可以将翻译方法直接放在 FormBuilder 中,而不是单独的方法:
ModalForm form = ModalForm.builder()
.translator((key, unused) -> {
// 此方法将为每个字符串调用,在这个例子中会调用4次:
// Title、Content、translate.button1、translate.button2
// 由于这不是一个单独的方法,你不需要locale参数,所以它是未使用的。
// 这里放入你自己的翻译逻辑
// 返回替换键的值
})
.title("Title")
.content("Content")
.button1("translate.button1")
.button2("translate.button2")
.build();