Minecraft Wiki

除另有声明,转载时均必须注明出处若簡繁轉換出錯,請以遊戲內為準请勇于扩充与修正内容有兴趣逛逛我们的微博沟通交流,欢迎到社区专页需要协助,请在告示板留言

了解更多

Minecraft Wiki
Advertisement
Information icon
此特性为Java版独有。

此教程介绍一个数据包制作的实例,阅读此教程前请先确保自己掌握教程/制作数据包教程/制作资源包的知识。了解命令记分板原始JSON文本等页面也会有所帮助。

目标

动手制作一个数据包前,你应该有一个明确的目标。也许你已经阅读过很多命令教程,但是却不知道如何有机地整合这些知识。在本实例中,我们会解析如何制作一个数据包,使得玩家视线所指的地方发生爆炸。

由于教程/制作数据包/实例:蜜蜂助手中已经包含了这篇实例的一部分内容,所以本实例讲述的会较为含糊,甚至有一段全部是命令。这就需要你自己静下心来思考这些文件的关系了。

本实例的GitHub地址:点击这里

开始

视线所指

在实例:蜜蜂助手中我们已经较为清楚的描述了“视线所指”如何实现,这里仅再一次给出局部坐标的解释图。

Local coordinates explained

图中三色羊毛所组成的坐标轴是世界坐标系,蓝绿红对应ZYX三个坐标轴的正半轴;粒子所组成的坐标轴是玩家坐标系(摄像机坐标系),蓝绿红对应左上前三个坐标轴的正半轴。

爆炸

嗯,爆炸。还能多简单呢?

为了达到爆炸的目的,我们可以在所指的地方召唤一个瞬间爆炸的TNT或者苦力怕。

但是,我们也可以做的更有趣一些,比如……一个小小的世界橡皮擦,又或是加一些粒子特效。这就看你怎么发挥了。

编写与实现

初始化

以下#<命名空间>:<名字>表示<命名空间>下的<名字>标签,<命名空间>:<名字>表示<命名空间>下的<名字>对象(可以是函数、模型等)。

新建一个文件夹,填写好pack.mcmeta,建立data文件夹。在data文件夹下建立nuke(本实例以此为主要的命名空间)和minecraft/tags/functions(一些函数需要被每刻执行和在地图加载时执行)文件夹。

本实例中不使用队伍来侦测正在使用该功能的玩家(因为使用队伍可能会影响其他数据包的运作),而是使用记分项。本实例的记分项前缀为nuke

建立data/nuke/functions,建立load.mcfunction函数,内容如下:

 scoreboard objectives add nukePerson dummy
 scoreboard objectives add nukeUseCSt minecraft.used:minecraft.carrot_on_a_stick

第一条命令初始化了一个nukePerson记分项,用来记录玩家是否正在使用爆炸功能,类型为dummy,也就是只能被命令修改。

第二条命令初始化了一个nukeUseCSt记分项,类型是……

好,你可能会问,“为什么这一次不用dummy了”,对吧?

在原版中,胡萝卜钓竿应该算是最方便检测右键功能的物品,原因就是有这么一个准则minecraft.used:minecraft.carrot_on_a_stick,它可以自动记录玩家使用胡萝卜钓竿的次数。

没错,我们这次会使用胡萝卜钓竿作为本功能的开关(的本体)。nukeUseCSt记分项中的“CSt”也就是“Carrot on a Stick”(胡萝卜钓竿)的缩写。我们需要这个记分项来制作这个开关。

这一次胡萝卜钓竿的检测会参照更多的合成的某个版本编写,如果目录结构过于分散可以尝试自己简化。

建立data/minecraft/tags/functions/load.json,内容如下:

{
    "replace": false,
    "values": [
        "nuke:load"
    ]
}

这样,将nuke:load函数设定为地图载入时执行。

下文提及到将函数加入标签时请参照这里。

视线投射

现在,我们要获取玩家所指的位置来生成我们的TNT。

nuke命名空间下,建立tick.mcfunctionray.mcfunction函数。

tick.mcfunction
 execute as @a run function nuke:entities/player
 execute as @a[scores={nukePerson=1..}] at @s anchored eyes run function nuke:ray

第一条命令用于后面的胡萝卜钓竿检测。

第二条命令将执行位置对齐到头部,然后开始执行视线投射。

nuke:tick函数也加入#minecraft:tick,使得其每刻执行。

ray.mcfunction
 execute unless entity @s[distance=..20] positioned ^ ^ ^2 run function nuke:nuke
 execute if entity @s[distance=..20] unless block ~ ~ ~ #nuke:get_through run function nuke:nuke
 execute if entity @s[distance=..20] if block ~ ~ ~ #nuke:get_through positioned ^ ^ ^0.005 run function nuke:ray

好,一上来出现了很多东西,但是基本和实例:蜜蜂助手中的差不多。

#nuke:get_through标签内储存的是视线追踪会忽略的方块,毕竟我们获取“视线所指”的方块并不想包含空气、草、花这些东西,但同时我们需要获取的也不仅仅是一类方块(不同于蜜蜂助手中我们只获取蜂巢类方块)。这个标签是自创的,也就是你需要自己整理一份/抄实例的标签列表,然后把列表放到data/nuke/tags/blocks/get_through.json里面。

nuke:nuke是实际执行爆炸的函数。

你会发现,这次出现了三个命令。其中两条和实例:蜜蜂助手差不多,这里不再赘述。

第一条是因为,我们并不希望我们看着天空就不会发生爆炸(也就是并没有看着任何方块的时候),所以如果视线追踪往前20格都没有碰到任何方块,那就直接再前进两格然后执行爆炸。“再前进两格”并不是必须的。

爆炸和消除

nuke命名空间下,建立nuke:nuke函数。

 summon minecraft:tnt ~ ~ ~

没错,生成一个TNT,就这么简单。或者,如果你想做世界橡皮擦:

 setblock ~ ~ ~ minecraft:air

到此,基本功能的逻辑就实现(但还未实装)完毕了。

你也可以生成一个会瞬间爆炸的苦力怕,甚至可以调节它的爆炸威力,但是不要尝试用隐身状态效果隐藏它——苦力怕爆炸时会生成所带的状态效果的区域效果云,这可能会导致异常的卡顿。

胡萝卜钓竿开关

还记得上面提到的函数nuke:entities/player吗?

下面我会给出所有和这个胡萝卜钓竿开关相关的函数,接好了:

nuke:entities/player
 execute as @s[scores={nukeUseCSt=1..}] at @s run function nuke:use_carrot_on_a_stick/type
nuke:use_carrot_on_a_stick/type
 execute as @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] run function nuke:use_carrot_on_a_stick/mainhand
 execute as @s[nbt=!{SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] run function nuke:use_carrot_on_a_stick/offhand
 scoreboard players reset @s nukeUseCSt
nuke:use_carrot_on_a_stick/mainhand
 execute as @s[nbt={SelectedItem:{tag:{id:"nuke:remote"}}}] run function nuke:use_carrot_on_a_stick/items/remote
 execute as @s[tag=!nuke_used,nbt={SelectedItem:{tag:{id:"nuke:remote_off"}}}] run function nuke:use_carrot_on_a_stick/items/remote_off
 tag @s remove nuke_used
nuke:use_carrot_on_a_stick/items/remote_off
 loot replace entity @s[nbt=!{SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] weapon.offhand 1 loot nuke:remote
 loot replace entity @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] weapon.mainhand 1 loot nuke:remote
 function nuke:start
nuke:use_carrot_on_a_stick/items/remote
 loot replace entity @s[nbt=!{SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] weapon.offhand 1 loot nuke:remote_off
 loot replace entity @s[nbt={SelectedItem:{id:"minecraft:carrot_on_a_stick"}}] weapon.mainhand 1 loot nuke:remote_off
 function nuke:stop
 tag @s add nuke_used
nuke:start
 scoreboard players set @s nukePerson 1
nuke:stop
 scoreboard players set @s nukePerson 0
Nuke remote off

“随便做”牌遥控器

Nuke remote on

“随便做”牌遥控器,打开状态

让我们解析一下为什么会这么写。

首先,我们得构想我们的这个胡萝卜钓竿开关——就叫遥控器好了,到底是怎么样的。

为了和普通的胡萝卜钓竿区别开来,我们会在物品的tag中嵌入自己的id标签(如果你不希望这个标签被其他的数据包占用,你也可以命名为类似nuke_id),并把关闭状态的遥控器的id的值设定为nuke:remote_off,开启的设定为nuke:remote

检测玩家的SelectedItem标签就可以检测主手上的物品了。此处我们检测tag,就是检测玩家手上有没有遥控器。

同时,因为遥控器肯定长得不像胡萝卜钓竿,所以我们需要通过CustomModelData来重新指定遥控器的材质。

段落内会有两个遥控器的图片(随便画的)。

新建一个资源包,填写好pack.mcmeta,在assets/minecraft/models/item/carrot_on_a_stick.json写入以下内容:

{
    "parent": "item/handheld_rod",
    "textures": {
        "layer0": "item/carrot_on_a_stick"
    },
    "overrides": [
        { "predicate": { "custom_model_data": 13400000 }, "model": "nuke:item/remote"},
        { "predicate": { "custom_model_data": 13400001 }, "model": "nuke:item/remote_off"}
    ]
}

其中的overrides就是来指定CustomModelData的。我们指定了两个物品标签谓词,分别指定了一个CustomModelData和它对应的模型:13400000(对应nuke:item/remote)和13400001(对应nuke:item/remote_off)。

assets/nuke/models/item/remote.json
{
    "parent": "item/handheld",
    "textures": {
        "layer0": "nuke:item/remote"
    }
}

其中nuke:item/remote对应材质assets/nuke/textures/item/remote.png,也就是开启的状态的材质。

另一个模型文件同理。

为了获取物品的方便,我们使用战利品表来预定义物品。此处以关闭的遥控器为例。

nuke:remote_off.json
{
    "pools": [
        {
            "rolls": 1,
            "entries": [
                {
                    "type": "minecraft:item",
                    "name": "minecraft:carrot_on_a_stick",
                    "functions": [
                        {
                            "function": "minecraft:set_nbt",
                            "tag": "{id:'nuke:remote_off',display:{Name:'{\"translate\":\"item.nuke.remote_off\"}'},CustomModelData:13400001}"
                        }
                    ]
                }
            ]
        }
    ]
}

掉落一份该战利品表就会获得关闭状态的遥控器。除了定义tag中的id,我们也自定义了物品的CustomModelData和显示名称。显示名称和实例:蜜蜂助手的多语言一样去写就行。此处在简体中文中显示的名称为“遥控器 (关闭)”。

同理,定义一份开启的。

现在请您再次回顾一遍上面的代码。现在能明白了吗?

基本思路是,循环检测钓鱼竿,如果有人用了遥控器就切换遥控器的状态,并且根据遥控器的状态决定是开始爆炸还是停止爆炸。

切换遥控器的状态,可以直接替换玩家对应的栏位,比如像上方一样使用/loot replace,然后调用定义好的战利品表,十分方便。

上方还预留了一个“offhand”,用于副手。除了使用和主手一样的使用目标选择器的nbt参数以外(但是由于副手没有提供SelectedItem这么方便的标签,我们需要读取玩家背包并且指定栏位),我们也可以使用1.15加入的(也就是实例:蜜蜂助手所使用的)谓词文件去判断。这个谓词的编写就让你自己尝试写吧,绝对不是因为这玩意是在1.14写的所以我懒得写谓词。

至此,编写完毕。

另见

Advertisement