开启辅助访问     
收藏本站

站内搜索

搜索

Minecraft(我的世界)苦力怕论坛

[BE教程] 借由附加包开发可获得成就的地图!

 发表于 2025-4-13 11:25:21|显示全部楼层|阅读模式 IP:北京
本帖最后由 牢冥王 于 2026-6-21 21:35 编辑

前言

自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.生物群系(二)
以下主要介绍的是基于事例附加包来进行操作。当然,事例附加包已经完成了上一步的基础设置,甚至还留下了一些为后续开发准备的其他设置,所以接下来的教程都依赖于该行为包,在进行下一步之前请下载并将其导入到游戏中。
关于事例附加包,为了避免编辑时返回审核,以及提供一个更方便查阅更新日志的平台,我将在本贴列出事例附加包的更新日志:
  • 3.8.6
    • 主包3.8.6
      增强基础功能的完整性保护,彻底废弃了functions/conduct/start
      修复若干bug:
      修改/cmd:editor block的运作方式,以使其能够正确地将方块所在维度对应至辅助实体所在的维度
      启用TNT无害化时,也会模拟TNT的爆炸击退
      向命令输入加入预设命令,可用来实现类似自定义快捷命令的功能
      修改了生物效果快捷命令的运作方式,现在你可以更便捷地选取标识符
    • 副包1.8.0
      添加翻译项
  • 4.0.0(尚未发布)
    • 主包4.0.0
      物品编辑器不会因为非法附魔而无法修改物品,但也不支持非法附魔
      现在可以访问玩家的末影箱库存
      从该版本开始,由于将minecraft/server更新到了2.8.0、minecraft/server-ui更新到了2.1.0,适配的Minecraft版本被限制在了26.30以上
    • 副包1.9.0
      调整翻译项
  • (即将到来)
    添加/locate快捷命令
    将“显示灵魂出窍坐标”改为“显示相机点位坐标”,用以在任何情况下显示相机点位的坐标
    用DDUI重新设计控制台界面

如果你想借助脚本开发,请参考JavaScript语言概览
着手开发
  • 通过事例附加包,你可以任意更改自己的游戏模式,以在地图中建造精美的建筑等。你也可以通过快捷指令来设置生物的状态效果,例如无敌的狗子,一击必杀的僵尸等等。

由于下面的内容需要修改行为包,我推荐你在地图中安装了该行为包之后再修改地图文件夹下的行为包,这样方便在出错的时候得到原始备份。并且如果你想要修改地图文件夹,你需要先把储存设为外部,并且了解地图文件的储存位置
  • 通过事例附加包,你可以借助服务器UI与脚本交互,进而实现一些效果,我们来看一些事例附加包中的例子:
    2.0.5以前
    1. var afds = new ActionFormData()
    2.   afds = afds.body({ translate: "advMode.setCommand" })
    3.     .title({ translate: "key.command" })
    4.     .button({ translate: "advMode.command" })
    5.     .button({ translate: "hostOption.codeBuilder" })
    6.     .button({ translate: "howtoplay.encyclopedia" })
    7.     .button({ translate: "createWorldScreen.game.settings" })
    8.   afds.show(player)
    复制代码
    1. var afds = new ModalFormData()
    2.     afds = afds.title({ translate: "key.mobEffects" })
    3.         .textField({translate: "hostOption.teleport.who"}, "@")
    4.         .textField({translate: "key.mobEffects"}, "?")
    5.         .textField({translate: "commands.schedule.delay.negativeTime"}, "...", "infinite")
    6.         .slider({translate: "generator.amplified"}, 0, 255, 1)
    7.         .toggle({ translate: "commands.spawnParticleEmitter.description" })
    8.      afds.show(player)
    9.         .then((effect) => {
    10.             player.runCommand(`effect ${effect.formValues[0]} ${effect.formValues[1]} ${effect.formValues[2]} ${effect.formValues[3]} ${effect.formValues[4]}`)
    11.         })
    复制代码

    “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以后
      请看下面一段代码:

      1. var box = new ModalFormData()
      2.           box = box.title("1")
      3.             .dropdown("2", ["a","b"])
      4.             .header("3")
      5.             .label("4")
      6.             .divider()
      7.             .slider("6", 1,2)
      8.             .submitButton("7")
      9.             .textField("8","a")
      10.             .toggle("9")
      11.           box.show(player)
      12.           .then((test) => {
      13.             console.log(test.formValues)
      14.           })
      复制代码

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

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

      可以通过“对象 = {属性名1: 值, 属性名2: 值}”的形式来定义对象,关于控件设置的属性,你可以在官方文档进一步查看
      表单拥有共同的显示方法“.show”,“show(要将表单显示给的玩家:玩家)”需要注意,玩家类型本质是一种实体,而不是玩家的名称(字符串)。我们可以在事例附加包的main.js中看见,通过事件
      1. world.afterEvents.itemUse.subscribe(t => {
      2.   var item = t.itemStack
      3.   var player = t.source
      4.   if (item.typeId == 'cmd:debug_stick') {
      5.     cmdBox(player)
      6.   }
      7. })
      复制代码
      取出了使用“调试”物品的玩家

    这里需要理解,表单本质上是一种承诺对象,因此可以使用“.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”文件中加入你的计时项(虽然加到任何一个常加载函数文件都没有区别)
      1. execute as @a[tag=!ck:spectator,m=spectator] run function countdown/spectator

      2. execute if score cd:spectator cmd:countdown matches 0 run function conduct/reset_spectator
      复制代码

      它表示,在检测到处于观察者模式下且没有“ck:spectataor”标签的玩家时,执行functions/countdown目录下的spectator函数文件。在该函数文件中,有两条命令
      1. scoreboard players operation cd:spectator cmd:countdown = cd:spectator cmd:reg
      2. 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文件,文件中有三条命令:
      1. gamemode c @a[m=spectator]
      2. scoreboard players reset cd:spectator cmd:countdown
      3. tag @a remove ck:spectator
      复制代码

      它表示计时项归零时将旁观者模式下的玩家变为创造模式、重置计时项、将所有人的“ck:spectator”标签移除
      当然,重置计时项不是必须的,在main.js中已经存在自动重置的指令
    • 有了前面的例子,假如我想在tnt实体出现的三秒后移除tnt实体,我可以进行以下操作:
      • 在游戏中用“调试”物品输入"scoreboard players set cd:tnt cmd:reg 60"然后保存游戏
      • 在countdown函数文件中加入命令"execute as @e[type=tnt,tag=!ck:tnt] run function countdown/tnt","execute as @e[type=tnt,scores={cmd:countdown}] 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加入这几条命令:
        1. execute if entity @a[tag=红队] unless score "inc:红队时间轴" cmd:countdown matches 0.. run scoreboard players set "inc:红队时间轴" cmd:countdown -200
        2. scoreboard players operation "红队进行秒数" cache:display = "inc:红队时间轴" cmd:countdown
        3. scoreboard players operation "红队进行秒数" cache:display /= "进制:游戏刻" cmd:reg
        4. scoreboard players operation "红队进行分钟" cache:display = "红队进行秒数" cache:display
        5. scoreboard players operation "红队进行秒数" cache:display %= "进制:分秒时" cmd:reg
        6. scoreboard players operation "红队进行分钟" cache:display /= "进制:分秒时" cmd:reg
        7. scoreboard players operation "红队进行小时" cache:display = "红队进行分钟" cache:display
        8. scoreboard players operation "红队进行分钟" cache:display %= "进制:分秒时" cmd:reg
        9. scoreboard players operation "红队进行小时" cache:display /= "进制:分秒时" cmd:reg
        10. execute if score "inc:红队时间轴" "cmd:countdown" matches 0.. run titleraw @a[tag=红队] actionbar {"rawtext":[{"text":"游戏时长:"},{"score":{"name":"红队进行小时","objective":"cache:display"}},{"text":"时"},{"score":{"name":"红队进行分钟","objective":"cache:display"}},{"text":"分"},{"score":{"name":"红队进行秒数", "objective":"cache:display"}},{"text":"秒"}]}
        复制代码

      • 在functions/countdown.mcfunction加入这几条命令:
        1. scoreboard players operation "红队铁锭剩余时间" cache:display = "inc:红队时间轴" cmd:countdown
        2. scoreboard players operation "红队铁锭剩余时间" cache:display %= "cd:铁锭刷新" cmd:reg
        3. execute if score "红队铁锭剩余时间" cache:display matches 0 run structure load iron_ingot 1 1 1
        复制代码

      写完当时我就后悔了,因为这看起来用倒计时循环更好一点,但是倒计时循环在玩家全部退出的时候就停了,而且对于生成铁锭这种固定任务很容易,对于多个不同时点有不同任务的复杂情况来说,倒计时循环要封装多个函数文件才行,所以还是见仁见智吧


我将在这里提供至攥稿为止的最新版事例附加包:  控制台附加包.mcaddon(35.76 KB, 下载次数: 210)
希望你们能够摸索出其他新奇的玩法!

评分

参与人数 1铁粒 +20收起理由
 Phant*** + 20苦力怕论坛感谢有你~

查看全部评分

苦力怕论坛,感谢有您~
 发表于 2025-4-14 20:54:52 来自手机|显示全部楼层 IP:浙江省
想问个问题,比如把一些本来不能获取成就的行为包加入wiki中声明的这段说明就可以正常获取成就吗
2#2025-4-14 20:54:52回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

 楼主|  发表于 2025-4-15 00:56:48 来自手机|显示全部楼层 IP:北京
天才爱游戏 发表于 2025-4-14 20:54
想问个问题,比如把一些本来不能获取成就的行为包加入wiki中声明的这段说明就可以正常获取成就吗 ...

理论上在1.21.70之后的我的世界都可以
3#2025-4-15 00:56:48回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

 发表于 2025-4-15 15:43:58 来自手机|显示全部楼层 IP:云南省
我在背包满了的时候把附加包加了进去 把调试卡没了重新添加也没用了 请问有解决办法么
4#2025-4-15 15:43:58回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

 发表于 2025-4-15 20:33:25 来自手机|显示全部楼层 IP:浙江省
所有行为包都可以改成可以获取成就的吗
5#2025-4-15 20:33:25回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

 楼主|  发表于 2025-4-16 00:07:40 来自手机|显示全部楼层 IP:北京
蛊惑人心 发表于 2025-4-15 15:43
我在背包满了的时候把附加包加了进去 把调试卡没了重新添加也没用了 请问有解决办法么 ...

你在地图文件夹里面改行为包,在functions/setting.mcfunction里面加一条"tag @a add op"。进入游戏后就自动给你调试棒了,然后你再把加的那条命令删除就没问题了
6#2025-4-16 00:07:40回复收起回复
苦力怕论坛,感谢有您~
回复支持

使用道具举报

本版积分规则

本站
关于我们
联系我们
坛史纲要
官方
哔哩哔哩
技术博客
下载
网易版
安卓版
JAVA
反馈
意见建议
教程中心
更多
捐助本站
QQ群
QQ群

QQ群

访问手机版

访问手机版

手机版|小黑屋|系统状态|klpbbs.com

| 由 木韩网络 提供支持 | GMT+8, 2026-6-23 15:07

声明:本站与Mojang以及微软公司没有从属关系

Powered by Discuz! X3.4