UID19188性别保密经验 EP铁粒 粒回帖0主题精华在线时间 小时注册时间2020-11-1最后登录1970-1-1
| 前言 | 表单(Form)是一种可供玩家操作的用户界面(UI),在SAPI中,表单则是一种承诺(Promise)对象。表单回执(FormResponse)则是表单兑现(fullfill)后的打包形式,玩家在表单上的操作最终会打包进表单回执当中。
| 讲述 | 在《借由附加包开发可获得成就的地图!》中,我介绍了SAPI 1.0中的表单、表单属性和表单方法,以及SAPI 2.0中的部分表单方法。这里来详细讲讲SAPI 2.0中的表单和表单回执,毕竟还是要与时俱进。首先,表单和资源包内的JSONUI不同,JSONUI用的是游戏内接口,通常不方便开发者自定义参数,但是可以在资源包内设计JSONUI的元素,使其看起来更美观;而表单虽然只有几个固定的控件,但是它可以与SAPI脚本内的其他参数交互,这让玩家可以在游戏内对SAPI参数实时交互。接下来介绍,目前拥有的三种表单分对应其表单数据:消息表单数据(MessageFormData),行动表单数据(ActionFormData)和模拟表单数据(ModalFormData)。表单数据有一个共通的构造方法,就是new <Action|Message|Modal>FormData()。其中,消息表单数据的结构非常简单:
 
只有四个设计方法(builder method),都是用来显示文字的。我们使用以下代码:- import { world, system } from "@minecraft/server"
- import { MessageFormData } from "@minecraft/server-ui"
- world.afterEvents.playerJoin.subscribe(event => {
- const player = world.getEntity(event.playerId)
- var demo = new MessageFormData()
- demo = demo.title("标题")
- .body("整体注释")
- .button1("第一个按钮")
- .button2({translate: "第二个按钮"})//实际上,如果没有在语言文件定义替换的文本,就还会显示“第二个按钮”
- system.runTimeout(() => {
- demo.show(player)
- }, 80)
- })
复制代码 这里方法后换行再接方法的方式其实是一种简写,完整的代码应该是这样的:- var demo = new MessageFormData()
- demo.title("标题")
- demo.body("整体注释")
- demo.button1("第一个按钮")
- demo.button2({translate: "第二个按钮"})
复制代码 只不过由于设计方法返回的还是消息表单数据类,所以可以一直在后面接设计方法。这样在玩家进入游戏4秒后就会弹出该表单,效果是这样的: 
看起来像是用的服务器消息的接口,在主界面退出游戏也会弹出类似的窗口。表单有一个共同的.show()方法,将返回各种表单回执,本质是兑现后的承诺对象,存在以下共通属性:

这个canceled属性可以用来避免报错,因为如果表单被取消,表单回执就不会包括表单上的操作,所以有些表单回执的属性就不能读取,进而报错。我们来看消息表单回执(MessageFormResponse)的属性:

一个属性就足够,消息表单是最简单的表单。我们继续使用以下代码:- import { world, system } from "@minecraft/server"
- import { MessageFormData } from "@minecraft/server-ui"
- world.afterEvents.playerJoin.subscribe(event => {
- const player = world.getEntity(event.playerId)
- var demo = new MessageFormData()
- demo = demo.title("标题")
- .body("整体注释")
- .button1("第一个按钮")
- .button2({translate: "第二个按钮"})//实际上,如果没有在语言文件定义替换的文本,就还会显示“第二个按钮”
- system.runTimeout(() => {
- demo.show(player)
- .then(response => {
- if (response.canceled) {
- player.sendMessage("你取消了表单")
- } else {
- player.sendMessage(response.selection === 0? "你选择了第一个按钮" : "你选择了第二个按钮")
- }
- })
- }, 80)
- })
复制代码 就可以在聊天栏显示你对表单进行的操作了。接下来介绍行动表单数据。相比于消息表单数据,行动表单数据不局限于两个按钮,而是有不定的按钮可以选择,并且SAPI 2.0给它也加入了表头、标签和分隔线,它的设计方法如下:   
其中图标路径是表示图片在资源包内相对文件地址的字符串。而行动表单回执(ActionFormResponse)和消息表单回执一样,只有一个selection属性,于是我们可以这样设计表单:- import { world, system } from "@minecraft/server"
- import { ActionFormData } from "@minecraft/server-ui"
- world.afterEvents.playerJoin.subscribe(event => {
- const player = world.getEntity(event.playerId)
- var demo = new ActionFormData()
- demo = demo.title("标题")
- .body("整体注释")
- .header("表头")
- .button("第一个按钮")
- .button({translate: "第二个按钮"})
- .divider()
- .label("标签")
- .button("第三个按钮", "textures/blocks/torchflower")
- .button("第四个按钮", "pack_icon")
- system.runTimeout(() => {
- demo.show(player)
- .then(response => {
- if (response.canceled) {
- player.sendMessage("你取消了表单")
- } else {
- player.sendMessage(`你选择了第${response.selection+1}个按钮`)
- }
- })
- }, 80)
- })
复制代码
这是实机的效果:
 
接下来就是最复杂的模拟表单数据,它的设计方法特别多:     
里面还提到了各种设置项,其实就是几个固定属性的对象,它们的属性都是可选的:    
另外还有模拟表单回执(ModalFormResponse)的属性: 
这里面说的控件(control)其实就对应相应的设计方法,另外要注意,即使文本框的默认值是原始文本类型,它在表单回执中读取时返回的是替换后的字符串,而不是原始文本;而且像分隔线、表头这样的控件,在formValues中读取的值是空(null)。然后我们可以设计以下表单:- import { world, system } from "@minecraft/server"
- import { ModalFormData } from "@minecraft/server-ui"
- world.afterEvents.playerJoin.subscribe(event => {
- const player = world.getEntity(event.playerId)
- const draw = ["选项1", {translate: "选项2"}]
- var demo = new ModalFormData()
- demo = demo.title("标题")
- .header("表头")
- .label({translate: "标签"})
- .toggle("开关", {defaultValue: false, tooltip: "开关小贴士"})
- .slider("滑块", 0, 255, {defaultValue: 0, tooltip: {translate: "滑块小贴士"}, valueStep: 5})
- .divider()
- .dropdown("下拉列表", draw, {defaultValueIndex: 0, tooltip: "下拉列表小贴士"})
- .textField("文本框", {translate: "文本框悬挂文字"}, {defaultValue: "默认文本", tooltip: "文本框小贴士"})
- .submitButton("提交按钮显示文字")
- system.runTimeout(() => {
- demo.show(player)
- .then(response => {
- if (response.canceled) {
- player.sendMessage("你取消了表单")
- } else {
- const list = response.formValues
- player.sendMessage((list[2]?"你扳开了开关":"开关仍然关闭")+`,你将滑块滑至数值${list[3]},`+`你选择了下拉列表中的${draw[list[5]]},`+"这是你填写的文本:"+list[6])
- }
- })
- }, 80)
- })
复制代码
然后是实机画面:
  | 总结 | | 表单是许多SAPI附加包的必要组件,表单回执是玩家实时操纵脚本的通道。在这里我给借助附加包那个帖打一个小补丁,表单看起来是不会读取.json定义的文件地址缩写,本来想着行为包文件里都可以用,结果试验之后还是不能用。所以代码一定要到游戏里试验才可以啊! |
|
|
评分查看全部评分
|