牢冥王 发表于 2025-4-13 11:25:21

借由附加包开发可获得成就的地图!

本帖最后由 牢冥王 于 2026-6-5 15:20 编辑

前言
自1.21.70的正式版以来,基岩版允许玩家在添加了市场附加包或者在注册文件(manifest.json)中声明了附加包的行为包的世界中获得成就。这使得玩家可以在体验更多游戏玩法的同时,也可以获得成就(因为基岩版的某些成就会给予一些奖励)。由于我们不好修改市场附加包,这里介绍,如何通过在注册文件中声明了附加包的行为包开发世界。
正文
行为包的基础设置

[*]首先你需要了解如何创建一个行为包,你可以参阅附加包教程:1.初步准备。我很高兴能看到一个较为全面的附加包教程,它是一个系列的内容,也推荐你们查阅系列中的其他内容。
[*]然后在行为包的manifest.json文件中添加wiki中提及的声明字段

这样,你就能得到一个不会影响成就获得的行为包
学习内容
关于其他的行为包内容开发,你可以参阅附加包教程:2.配方、7.物品(二)、9.物品(四)、10.方块(一)、11.方块(二)、13.战利品表、15.方块(四)、22.行为树、23.生物群系、24.对话、25.生成规则、26.结构、27.地物、28.交易、33.方块(五)、34.方块(六)、35.方块(七)、36.实体(二)、37.实体(三)、38.实体(四)、42.方块(八)、43.方块(九)、45.战利品表(二)、55.物品目录、56.命令、59.生物群系(二)
以下主要介绍的是基于事例附加包来进行操作。当然,事例附加包已经完成了上一步的基础设置,甚至还留下了一些为后续开发准备的其他设置,所以接下来的教程都依赖于该行为包,在进行下一步之前请下载并将其导入到游戏中。
关于事例附加包,为了避免编辑时返回审核,以及提供一个更方便查阅更新日志的平台,我将在本贴列出事例附加包的更新日志:

[*]1.0.0
添加了“调试”物品,可通过右键其打开控制台界面
控制台界面共有三个选项:“命令输入”,“代码编辑器”和“百科全书”
命令输入可直接输入命令,
代码编辑器实际上是快捷指令,共有五种:“游戏模式”,“传送”,“时间”,“天气”和“生物效果”
目前百科全书无效果
[*]1.1.0
现在可以使用“百科全书”,以获得指令提示
[*]1.2.0
加入了“设置重生点”快捷指令
[*]1.3.2
加入了“游戏规则”快捷指令
[*]1.4.4
在控制台界面加入了“世界设置”,目前可以在其中设置“处于旁观者模式下的最大秒数”,以确保在使用旁观者模式时可以切换回其他游戏模式。
[*]1.5.1
在“世界设置”中加入了一个开关,用于决定是否清除具有"op"标签外的玩家的调试棒
由于官方的"isOp"函数仍在开发中,目前只能自己给玩家添加"op"标签(tag)。
[*]1.6.9
添加了注册表系统,优化了一些性能问题。
由于注册表很重要,所以不要轻易更改其中的注册项!
将世界设置拆分为基本设置和高级设置。
大改了调试棒控制台的权限系统,共分为0~5六个等级
限制权限等级:

[*]等级0:无权限使用调试棒,会自动清除拥有的调试棒
[*]等级1:可以查看调试棒中的指令提示,但仅能使用部分快捷指令(传送,更改时间、天气,设置重生点)
[*]等级2:相较于等级1,放开了更多快捷指令(更改游戏模式,修改游戏规则)
[*]等级3:相较于等级2,放开了“生物效果”快捷指令,可以修改“世界设置”选项下的“基础设置”

限制权限等级均不可使用输入命令的聊天栏。
完全权限等级:

[*]等级4:相较于等级3,可以使用输入命令的聊天栏。*请不要给予不可信的玩家等级4的权限,否则他有可能私自修改注册表,造成不可逆的破坏!
[*]等级5:完全的调试棒使用权限,可以设置其他玩家的默认权限。

该权限系统于基于"op"标签的检测系统完全独立,所以一般不需要动用世界设置。
初次加载附加包时会给予玩家等级5的权限,且地图中不存在权限等级为5的玩家并有新玩家加入时,会给予所有人等级5的权限。
初始的默认玩家权限等级为1,如果你想进一步修改其他玩家的权限等级,可以通过命令"scoreboard players set <玩家名称> cmd:reg <权限等级:正整数>"来设置[*]1.7.10
加强了安全措施:当有人尝试获得不合规的权限等级时,会向认证的拥有者发送一条警告信息
现在在开启“禁止管理员之外的成员获得调试棒”开关时,即使认证的拥有者没有"op"标签也不会清除他的调试棒
将“是否禁止管理员之外的成员获得调试棒”开关从“基础设置”移至“高级设置”
[*]1.8.7
向基础设置增加了“是否TNT无害化”开关,向高级设置添加了“无害化TNT的爆炸威力”设置项
需要注意的是,“TNT无害化”是指TNT的爆炸不会破坏方块,但仍然会使用模拟的爆炸伤害来对周围的生物造成伤害。另外,爆炸威力应当是正整数;且数值越大,爆炸范围越远,爆炸伤害越高。
由于设置项的增加,现在“世界设置”下的设置项会查询并返回当前值,避免了重复设置的不便性
[*]1.9.5
在“世界设置”中添加了“禁止”选项,该选项只有权限等级在3以上的玩家才能使用。
可以在其中选择禁实体或者禁物品,你可以指定所禁物品的数据值,当然如果你只想禁实体或物品中的一种,把另一种的标识符留空即可。标识符可以不带"minecraft:"前缀。
修改了部分结构,以避免低版本的本包向高版本过渡时会出错
[*]1.10.6
更改了调试棒的外观
对“禁止”中为禁止实体的选项添加了“按字段筛选”的下拉菜单,其中type的可选值是实体的typeID,family的可选值是实体的族标签名称(例如怪物:monster),name的可选值是任意字符串,但请注意,该字段不能是在场玩家的名称,否则可能会报错!
对“禁止”中的禁止物品的选项做了更改,现在如果将“data”数据值留空,则认为是禁止使用该标识符的所有物品(无论数据值为何)
加入了“快速更改玩家权限等级(仅认证者)”选项,只有认证的拥有者才能使用,用以更改任意玩家的权限等级
从该版本开始,由于将minecraft/server更新到了1.19.0,适配的Minecraft版本被限制在了1.21.80以上
[*]1.10.7
简化了禁止项的注册表储存格式。但该版本并不会作为一个独立版本发布,这些更改将会继承到下一个发布的版本
[*]1.11.13
优化了部分代码
加入了“传送锚点”功能分区:
目前其下有"添加或修改传送锚点的位置","删除传送锚点"和"传至传送锚点"三个选项
其中,你可以命名你的传送锚点,但不要给它一个过长的名字。传送锚点的坐标将以你的所在位置确定,但请不要在坐标超过2^32-1的位置设置传送锚点,会产生错误。
向“高级设置”加入了“设置使用传送锚点需要的最小等级”设置项。由于设置过多的传送锚点可能导致性能问题,并且当前不同玩家之间无法查看或修改对方的传送锚点,所以加入该设置项。
[*]1.12.3
修复了传送锚点不能跨纬度设置的问题
由于现在注册表变得非常臃肿,建议你有效地设置传送锚点,适时删除无用的传送锚点,进而节约性能
向”高级设置“加入了“是否允许更高的权限等级访问更低权限等级的传送锚点”设置项,默认开启。这样你可以在“传送锚点”分区下的“强行修改传送锚点”中更改较低权限等级玩家设置的传送锚点。需要注意,其中的拥有者ID需要在“传送锚点”分区下的“查看在场玩家的ID”来查询,以及坐标只能修改为整数。
[*]2.0.7
更新了附加包图标
提供了一些安全补丁:
现在op标签不再需要手动赋予
现在认证的拥有者只能认证一次了,且只有房主能自动成为认证的拥有者
现在在开启“是否允许更高的权限等级访问更低权限等级的传送锚点”设置项时,更高权限等级的玩家可以传送至更低权限等级的玩家的传送锚点
从该版本开始,由于将minecraft/server更新到了2.1.0、minecraft/server-ui更新到了2.0.0,适配的Minecraft版本被限制在了1.21.100以上
[*]2.1.8
修复了若干bug
提供了一些安全补丁:
向“高级设置”添加了"设置编辑传送锚点需要的最小等级"设置项,主要影响“强制修改传送锚点”选项的使用,通常不低于使用传送锚点的最小权限等级,默认为2。
现在认证的拥有者的权限等级不会小于1
将“设置无害化TNT的爆炸威力”设置项移至“基础设置”
向“基础设置”添加了"是否点击即移除实体"设置项,用于决定是否可以用调试棒左键来清除实体
向“高级设置”添加了“设置点击移除实体需要的最小等级”设置项
调试棒为移动端加入了一个使用按钮
添加了“编辑器模式”功能分区,权限等级3以上的玩家可以使用。目前可以编辑物品、实体、方块。如果在远处编辑实体,则会选择视线范围内的最近实体,右键实体也可以直接打开实体编辑界面
[*]2.2.4
修复了若干bug
向“高级设置”添加了"设置传送锚点基本操作需要的最小等级"设置项,主要影响“添加或覆盖传送锚点”和“删除传送锚点”选项的使用,通常不低于使用传送锚点的最小权限等级,默认为2。
支持编辑方块序列。并且你可以修改需要编辑的方块的坐标,这使得你能够编辑空气方块和一些有穿透性的方块
现在只有房主可以成为认证的拥有者
进行了一些性能方面的更新
[*]2.3.6
修复若干bug
认证的拥有者在任意权限等级下都能使用输入命令的聊天栏
非认证的拥有者玩家也可以拥有权限等级5
可以用编辑器修改实体的着火时间
将“快速编辑玩家权限等级(仅认证者)”功能分区改为“管理注册表”,认证的拥有者可以在其中更便捷地管理注册表。但仍然不鼓励修改注册表,尤其是在你不熟悉注册表的数据结构的情况下
[*]2.4.2
支持编辑书籍物品的组件
废弃了functions/start.mcfunction;与之相关的cmd:start标签也遭到废弃。
从该版本开始,由于将minecraft/server更新到了2.2.0,适配的Minecraft版本被限制在了1.21.110以上
[*]3.0.4

[*]行为包3.0.4:
修复了若干bug,进行了一些适于翻译的改动
支持编辑部分生物的颜色组件
向“基础设置”添加了“是否使用区块标示”设置项,用以控制是否显示玩家所在的子区块边框。该项可能会消耗性能,因此默认是关闭的
[*]资源包1.0.0:
添加了适用于行为包的UI控件
添加了适用于行为包的翻译文件
[*]3.1.3
将行为包命名为主包,资源包命名为副包

[*]主包3.1.3
修复了若干bug:修正了区块标示的误差
提供了一些安全补丁
支持显示玩家所处的生物群系
添加了“设置生物群系的显示方式”设置项,默认在标题显示
支持编辑物品的库存(minecraft:inventory)组件
[*]副包1.1.0
添加了一些翻译项

从该版本开始,由于将minecraft/server更新到了2.3.0,适配的Minecraft版本被限制在了1.21.120以上[*]3.2.5

[*]主包3.2.5
修复若干bug
可以编辑实体的驯服组件,朝向
加入“灵魂出窍”功能分区,可在其中调整灵魂出窍下的移动速度,以及进入或退出灵魂出窍模式
向“基础设置”加入“重进即退出灵魂出窍”和“受到伤害即退出灵魂出窍”设置项,默认开启
向“高级设置”加入“使用灵魂出窍的最小等级”设置项,默认为2
[*]副包1.2.1
添加了翻译项
与灵动视效兼容
[*]3.3.2

[*]主包3.3.2
修复若干bug
可以在实体编辑器中查看属性值,但是一次只能更改一个属性
向“基础设置”加入“显示灵魂出窍坐标”设置项,默认为关,用以显示灵魂出窍时的摄像机点位,可能会消耗性能
将“设置生物群系的显示方式”中的“屏幕下方”的动作栏显示改为常驻模式
加入了"/cmd:dynamicproperty <目标实体:目标选择器> <自定义属性ID:字符串> [值:JSON文本字符串]"自定义命令,用以设置或查询对应实体上的自定义属性值
[*]副包1.3.0
添加翻译项
[*]3.4.2

[*]主包3.4.2
优化了/cmd:dynamicproperty的逻辑(顺便删掉了测试代码)
加入"/cmd:cmd_box [目标实体:玩家选择器]"自定义命令,用以随时为一个至多个玩家打开调试界面,无需作弊,但需要管理员权限
可以在“禁止”中通过名称来封禁玩家(对房主无效)
在空中也可以打开方块编辑器
可以编辑实体驯服坐骑组件
现在也可以在cmd:countdown中创建数值递增的计时项,比如"inc:neverend"或"inc:20|ends_at_20ticks"
[*]副包1.4.0
添加翻译项
[*]3.5.3

[*]主包3.5.3
提供了一些安全补丁:
解决了某些面板服无法认证拥有者的问题。相应地,在这些面板服中,操作员即为认证的拥有者
优化了性能:
现在传送锚点不再储存在注册表,而是储存在世界自定义属性中,对于数据结构的修正也只在玩家退出之前进行
添加临时自定义命令"/cmd:world_dynamicprop <自定义属性ID:字符串> [值:JSON文本字符串]",用以设置或查询所处世界的自定义属性值
[*]副包1.5.0
调整了翻译项
[*]3.6.3

[*]主包3.6.3
修复了若干bug
将“管理注册项”功能分区改为“管理面板”,在其中可选择“管理注册项”和“管理世界属性”
将传送锚点维度的存储类型从数字改为字符串,以求更高的兼容性
移除了"/cmd:world_dynamicprop"自定义命令
将"/cmd:dynamicproperty"改为"/cmd:dynamicproperty entity <目标实体:目标选择器> <自定义属性ID:字符串> [值:JSON文本字符串]" 或 "/cmd:dynamicproperty world <任选:目标选择器> <自定义属性ID:字符串> [值:JSON文本字符串]" 或 "/cmd:dynamicproperty item <持有物品的实体:目标选择器> <自定义属性ID:字符串> [值:JSON文本字符串]"
该版本领地系统暂未实装
[*]副包1.6.0
添加翻译项
[*]3.7.2

[*]主包3.7.2
修复若干bug
可将含耐久的物品设置为不可摧毁
/cmd:dynamicproperty的dynamicPropertyId(自定义属性ID)参数变为可选参数,留空则可查询实体/物品/世界上储存的所有自定义属性标识符
加入了/cmd:editor自定义命令,语法结构如下:“cmd:editor block <操作者:玩家选择器> <辅助对象:目标选择器> [方块位置:XYZ三维坐标]”或“cmd:editor entity <操作者:玩家选择器> <操作对象:目标选择器>”或“cmd:editor item <操作者:玩家选择器> <所在实体:目标选择器> [槽位类型:数字] [槽位序号:数字] [任选:数字]”其中,方块编辑器的辅助实体用来确定方块所在的维度,以及未指定方块位置时,以辅助实体所处坐标选取方块;物品编辑器的槽位类型对应的是调试里物品编辑器槽位类型列表中从0开始的序号(例如0对应主手槽),槽位类型和槽位序号都默认为0,指定槽位类型时必填槽位序号和任选数字。
从该版本开始,由于将minecraft/server更新到了2.6.0,适配的Minecraft版本被限制在了26.10以上
[*]副包1.7.1
添加翻译项

[*]3.8.6

[*]主包3.8.6
增强基础功能的完整性保护,彻底废弃了functions/conduct/start
修复若干bug:
修改/cmd:editor block的运作方式,以使其能够正确地将方块所在维度对应至辅助实体所在的维度
启用TNT无害化时,也会模拟TNT的爆炸击退
向命令输入加入预设命令,可用来实现类似自定义快捷命令的功能
修改了生物效果快捷命令的运作方式,现在你可以更便捷地选取标识符
[*]副包1.8.0
添加翻译项
[*]4.0.0(尚未发布)
[*]主包4.0.0
物品编辑器不会因为非法附魔而无法修改物品,但也不支持非法附魔
[*](即将到来)
添加/locate快捷命令
将“显示灵魂出窍坐标”改为“显示相机点位坐标”,用以在任何情况下显示相机点位的坐标
用DDUI重新设计控制台界面

如果你想借助脚本开发,请参考JavaScript语言概览
着手开发

[*]通过事例附加包,你可以任意更改自己的游戏模式,以在地图中建造精美的建筑等。你也可以通过快捷指令来设置生物的状态效果,例如无敌的狗子,一击必杀的僵尸等等。

由于下面的内容需要修改行为包,我推荐你在地图中安装了该行为包之后再修改地图文件夹下的行为包,这样方便在出错的时候得到原始备份。并且如果你想要修改地图文件夹,你需要先把储存设为外部,并且了解地图文件的储存位置

[*]通过事例附加包,你可以借助服务器UI与脚本交互,进而实现一些效果,我们来看一些事例附加包中的例子:
2.0.5以前
var afds = new ActionFormData()
afds = afds.body({ translate: "advMode.setCommand" })
    .title({ translate: "key.command" })
    .button({ translate: "advMode.command" })
    .button({ translate: "hostOption.codeBuilder" })
    .button({ translate: "howtoplay.encyclopedia" })
    .button({ translate: "createWorldScreen.game.settings" })
afds.show(player)
var afds = new ModalFormData()
    afds = afds.title({ translate: "key.mobEffects" })
      .textField({translate: "hostOption.teleport.who"}, "@")
      .textField({translate: "key.mobEffects"}, "?")
      .textField({translate: "commands.schedule.delay.negativeTime"}, "...", "infinite")
      .slider({translate: "generator.amplified"}, 0, 255, 1)
      .toggle({ translate: "commands.spawnParticleEmitter.description" })
   afds.show(player)
      .then((effect) => {
            player.runCommand(`effect ${effect.formValues} ${effect.formValues} ${effect.formValues} ${effect.formValues} ${effect.formValues}`)
      })
“var”表示声明一个变量,这个变量可以为任意类型或对象,“.”后面可以为变量的属性(不带圆括号)或方法(带圆括号)。关于服务器UI的属性和方法请参阅开发者文档
你需要让这个变量等于“new 某类表单”才能方便定义和显示你创建的表单
目前官方提供了三种表单"ActionFormData”,“ModalFormData”和“MessageFormData”。最后一种没有包含在事例中,应用场景也比较少,我们不作介绍。

[*]“ActionFormData”中提供了三种设计表单的方法:“.title”,“.body”和“.button”,分别可以设置表单框架上的、表单内容标题上的、表单选项按钮上的文本(按钮前可设置图标)

[*]title(可选值:原始文本 或 字符串): ActionFormData
比如事例附加包中的“{ translate: "advMode.setCommand" }”,它是一个原始文本对象,将会在按钮上显示该字符串在语言文件中定义的替换文本;如果把它换成"advMode.setCommand"则会直接显示该字符串
[*]body(可选值:原始文本 或 字符串): ActionFormData
[*]button(按钮文本:原始文本 或 字符串, 图标路径:字符串): ActionFormData
图标一般储存在资源包中的resource_pack/textures文件夹下,在输入路径时,可以是资源包文件夹下的相对地址,也可以是在资源包材质文件中定义的代称[需要更多信息]
[*]“ModalFormData”提供了六种设计表单的方法:“.title”,“.dropdown”,“.toggle”,“.textField”,“slider”和“submitButton”

[*]“.title”上同
[*]dropdown(下拉列表的题目:原始文本 或 字符串, 选项: (由原始文本 或 字符串 组成的数组), dropdownOptions?: 该字段尚未在正式版应用): ModalFormData
创建一个有多个选项的下拉列表,返回值是选择的选项在列表中从0开始的编号
[*]toggle(开关的题目:原始文本 或 字符串, toggleOptions?: 目前仅应用了默认值:布尔值(真或假)): ModalFormData
需要注意,它的返回值是真或假(true/false)
[*]textField(输入文本框的题目:原始文本 或 字符串, 在文本框内显示的文本:原始文本 或 字符串, textFieldOptions?: 目前仅应用了默认值:字符串): ModalFormData
以字符串类型返回你输入的文本
[*]slider(滑块的题目:原始文本 或 字符串, 最小值:数字, 最大值:数字, sliderOptions?: 目前仅应用了步长:数字,默认值:数字): ModalFormData
返回值是选择的数字
[*]submitButton(提交按钮上显示的文本:原始文本 或 字符串): ModalFormData
即使不设置也会显示提交按钮,并且按钮上的文本就是“提交”

2.0.5以后
请看下面一段代码:
var box = new ModalFormData()
          box = box.title("1")
            .dropdown("2", ["a","b"])
            .header("3")
            .label("4")
            .divider()
            .slider("6", 1,2)
            .submitButton("7")
            .textField("8","a")
            .toggle("9")
          box.show(player)
          .then((test) => {
            console.log(test.formValues)
          })

这是提交表单之后控制台的反馈
这说明在minecraft/server-ui-2.0.0之后,像.header()这些表单控件也会在formValues中返回值,这需要我们在读取动态属性(方括号内含数字的形式)时格外注意
以及这是游戏中的实际画面
另外,minecraft/server-ui在2.0.0之后将表单控件的某些设置参数改成了对象,所以如果你想用2.0.0的服务器表单,就要把格式更新到2.0.0,以下是事例附加包中的节选:

box =box.title("详细信息")
      .textField("拥有者的ID", "?", {defaultValue: regVerify(pool.displayName).id, tooltip: "应当在“查看在场玩家的ID”处按玩家的名字查询对应"})
      .textField({ translate: "npcscreen.name" }, "?", {defaultValue: name, tooltip: "传送锚点的名字"})
      .textField("x", "...", {defaultValue: `${reg.getScore(`pos_x|${name}`)}`, tooltip: "只能是-2^32+1到2^32-1之间的整数"})
      .textField("y", "...", {defaultValue: `${reg.getScore(`pos_y|${name}`)}`, tooltip: "只能是-2^32+1到2^32-1之间的整数"})
      .textField("z", "...", {defaultValue: `${reg.getScore(`pos_z|${name}`)}`, tooltip: "只能是-2^32+1到2^32-1之间的整数"})
      .textField("dimension", "?", {defaultValue: dimList}`)], tooltip: `只能为以下值:${dimList}`})
      .slider("权限等级", 0, 5, {valueStep: 1, defaultValue: reg.getScore(pool)})
      .toggle("是否删除传送锚点", {defaultValue: false})
box.show(player)

可以通过“对象 = {属性名1: 值, 属性名2: 值}”的形式来定义对象,关于控件设置的属性,你可以在官方文档进一步查看
表单拥有共同的显示方法“.show”,“show(要将表单显示给的玩家:玩家)”需要注意,玩家类型本质是一种实体,而不是玩家的名称(字符串)。我们可以在事例附加包的main.js中看见,通过事件:world.afterEvents.itemUse.subscribe(t => {
var item = t.itemStack
var player = t.source
if (item.typeId == 'cmd:debug_stick') {
    cmdBox(player)
}
})取出了使用“调试”物品的玩家
这里需要理解,表单本质上是一种承诺对象,因此可以使用“.then”或“.catch”方法来获得表单内的信息。当然表单显示给玩家后再提取表单信息就可以得到玩家在表单上的操作。
比如例子中的“.then((effect) =>”是代表把表单的信息注册为一个“effect”对象,然后再对对象进行操作。表单的信息本质上是一个对象,不同表单拥有不同的属性。比如ActionFormData有一个selection属性,是返回玩家选择的按钮在其按钮序列中,从0开始的序号(数字);而ModelFormData的formatValues属性是一个数组,因此可以用方括号取出数组中的值(或对象)[*]通过事例附加包,你可以制作一个计时器。如果脚本实在是太烧脑,我们还可以回到相对简单的函数。

[*]首先你需要了解基岩版中的函数,可以参阅附加包教程:3.函数
[*]在应用了事例附加包的世界中,会创建一个注册表计分板“cmd:reg”,它是用来记录某些不会被引用它的进程改变的值(比如玩家权限等级),所以你可以在上面创建一个新的计时项,用来储存倒计时的初始时间。比如:"scoreboard players add test:cd cmd:reg 200"。需要注意,函数的执行方式是每游戏刻(每秒20游戏刻),你在注册表中储存的初始值应当以游戏刻为单位。在事例附加包3.4.2版本之后,你可以直接在命名上决定截止时间,比如"scoreboard players set inc:200|test_cd cmd:countdown 0"这样相当于一个倒过来的倒计时,你要反过来检测inc:200|test_cd这个计分项的值等于200的时候触发执行函数
[*]然后我们可以给这个计时项设置一个触发条件。在事例附加包的functions文件夹中,有两个注册的常加载函数文件:“countdown”和“setting”。在“countdown”文件中存在一个例子,我也建议你在“countdown”文件中加入你的计时项(虽然加到任何一个常加载函数文件都没有区别)execute as @a run function countdown/spectator

execute if score cd:spectator cmd:countdown matches 0 run function conduct/reset_spectator
它表示,在检测到处于观察者模式下且没有“ck:spectataor”标签的玩家时,执行functions/countdown目录下的spectator函数文件。在该函数文件中,有两条命令scoreboard players operation cd:spectator cmd:countdown = cd:spectator cmd:reg
tag @a add ck:spectator第一个是用来将计时项在“cmd:countdown”倒计时计分项的值设置为储存在“cmd:reg”注册表计分项的值,第二个用来给执行过第一条命令的玩家打上标签,防止重复初始化计时项
另外还有一个倒计时归零时的执行命令"execute if score cd:spectator cmd:countdown matches 0 run function conduct/reset_spectator",它要执行的函数文件在functions/conduct目录下的reset_spectator文件,文件中有三条命令:gamemode c @a
scoreboard players reset cd:spectator cmd:countdown
tag @a remove ck:spectator
它表示计时项归零时将旁观者模式下的玩家变为创造模式、重置计时项、将所有人的“ck:spectator”标签移除
当然,重置计时项不是必须的,在main.js中已经存在自动重置的指令
[*]有了前面的例子,假如我想在tnt实体出现的三秒后移除tnt实体,我可以进行以下操作:

[*]在游戏中用“调试”物品输入"scoreboard players set cd:tnt cmd:reg 60"然后保存游戏
[*]在countdown函数文件中加入命令"execute as @e run function countdown/tnt","execute as @e run function conduct/remove_tnt"
[*]在functions/countdown目录下新建一个tnt.mcfunction文件,并在其中输入命令"scoreboard players operation @s cmd:countdown = cd:tnt cmd:reg","tag @s add ck:tnt"
[*]在functions/conduct目录下新建一个remove_tnt.mcfunction文件,并在其中输入命令"kill @s"

当然了,这只是一个普通的例子,根据不同的情境你还需要改变触发条件时的执行命令或者计时归零时的执行命令[*]3.4.2之后:
当你需要创建一个有多个时间节点的时间轴,该怎么做呢?聪明的你可能会想到在一个倒计时结束的时候立刻触发下一个倒计时,但是这样太麻烦,还要创建多个倒计时。现在你可以创建一个永远递增的计时项来简化这一步骤。比如,我想在红队的玩家全部加入10秒后,每隔五秒在1 1 1产生一个铁锭,同时还想知道红队究竟进行了多长时间的比赛:

[*]先在游戏里用结构方块将一个铁锭物品储存为mystructure:iron_ingot
[*]在调试的命令框内陆续输入“scoreboard players set "进制:游戏刻" cmd:reg 20”,“scoreboard players set "进制:分秒时” cmd:reg 60”,“scoreboard players set "cd:铁锭刷新" cmd:reg 100”
[*]为了节约性能,我们需要创建一个缓存显示变量的计分板“cache:display”
[*]在functions/setting.mcfunction加入这几条命令:execute if entity @a unless score "inc:红队时间轴" cmd:countdown matches 0.. run scoreboard players set "inc:红队时间轴" cmd:countdown -200
scoreboard players operation "红队进行秒数" cache:display = "inc:红队时间轴" cmd:countdown
scoreboard players operation "红队进行秒数" cache:display /= "进制:游戏刻" cmd:reg
scoreboard players operation "红队进行分钟" cache:display = "红队进行秒数" cache:display
scoreboard players operation "红队进行秒数" cache:display %= "进制:分秒时" cmd:reg
scoreboard players operation "红队进行分钟" cache:display /= "进制:分秒时" cmd:reg
scoreboard players operation "红队进行小时" cache:display = "红队进行分钟" cache:display
scoreboard players operation "红队进行分钟" cache:display %= "进制:分秒时" cmd:reg
scoreboard players operation "红队进行小时" cache:display /= "进制:分秒时" cmd:reg
execute if score "inc:红队时间轴" "cmd:countdown" matches 0.. run titleraw @a actionbar {"rawtext":[{"text":"游戏时长:"},{"score":{"name":"红队进行小时","objective":"cache:display"}},{"text":"时"},{"score":{"name":"红队进行分钟","objective":"cache:display"}},{"text":"分"},{"score":{"name":"红队进行秒数", "objective":"cache:display"}},{"text":"秒"}]}
[*]在functions/countdown.mcfunction加入这几条命令:scoreboard players operation "红队铁锭剩余时间" cache:display = "inc:红队时间轴" cmd:countdown
scoreboard players operation "红队铁锭剩余时间" cache:display %= "cd:铁锭刷新" cmd:reg
execute if score "红队铁锭剩余时间" cache:display matches 0 run structure load iron_ingot 1 1 1
写完当时我就后悔了,因为这看起来用倒计时循环更好一点,但是倒计时循环在玩家全部退出的时候就停了,而且对于生成铁锭这种固定任务很容易,对于多个不同时点有不同任务的复杂情况来说,倒计时循环要封装多个函数文件才行,所以还是见仁见智吧

我将在这里提供至攥稿为止的最新版事例附加包:
希望你们能够摸索出其他新奇的玩法!

天才爱游戏 发表于 2025-4-14 20:54:52

想问个问题,比如把一些本来不能获取成就的行为包加入wiki中声明的这段说明就可以正常获取成就吗

牢冥王 发表于 2025-4-15 00:56:48

天才爱游戏 发表于 2025-4-14 20:54
想问个问题,比如把一些本来不能获取成就的行为包加入wiki中声明的这段说明就可以正常获取成就吗 ...

理论上在1.21.70之后的我的世界都可以

蛊惑人心 发表于 2025-4-15 15:43:58

我在背包满了的时候把附加包加了进去 把调试卡没了重新添加也没用了 请问有解决办法么[贴吧_汗]

天才爱游戏 发表于 2025-4-15 20:33:25

所有行为包都可以改成可以获取成就的吗

牢冥王 发表于 2025-4-16 00:07:40

蛊惑人心 发表于 2025-4-15 15:43
我在背包满了的时候把附加包加了进去 把调试卡没了重新添加也没用了 请问有解决办法么 ...

你在地图文件夹里面改行为包,在functions/setting.mcfunction里面加一条"tag @a add op"。进入游戏后就自动给你调试棒了,然后你再把加的那条命令删除就没问题了
页: [1]
查看完整版本: 借由附加包开发可获得成就的地图!