User:Luoboju0/Sandbox:修订间差异

来自Minecraft Wiki
跳转到导航 跳转到搜索
添加的内容 删除的内容
无编辑摘要
 
第1行: 第1行:
== 数据存储 ==
本章将讨论或解决如下问题:
* 获取任意命令的反馈参数。
* 在退出游戏或卸载数据包后数据仍然存在并可恢复。
* 添加自定义的数据。

对于任意命令,都可以使用{{cmd|execute store}}存储其某个反馈参数值。但要注意,对于同一个命令,并不是其所有参数都能被获取。具体能够被存储的参数内容应该参考相应命令页面的“输出”章节。

比如,对于命令{{cmd|random}},你可以通过{{cd|execute store}}存储其抽取的随机值。获取到参数值后,你可以存储到某个实体或虚拟玩家的记分项中,也可以存储到[[命令存储]]中。
* 如果你接下来即将对获取到的值进行大量运算,一般选择存储到记分项中。
* 如果是为了备用或者传递到宏函数中,则应存储到命令存储。

值得注意的是,所反馈的参数值将先被向下取整后再进行存储——这将导致浮点数的小数位丢失。比如,对于以下的命令存储:
{{snbt|bg=block|<nowiki>{test: 123.123456d, v: 0}</nowiki>}}

以下命令执行后:
<syntaxhighlight lang="mcfunction">
execute store result storage generic:test v double 1.0 run data get storage generic:test test
</syntaxhighlight>

命令存储将变为:
{{snbt|bg=block|<nowiki>{test: 123.123456d, v: 123.0d}</nowiki>}}

显然,如果想保留数据的完整形式,最好直接使用{{cmd|data modify}}命令:
<syntaxhighlight lang="mcfunction">
data modify storage generic:test v set from storage generic:test test
</syntaxhighlight>
{{snbt|bg=block|<nowiki>{test: 123.123456d, v: 123.123456d}</nowiki>}}

你可能想到,{{cmd|execute store}}可以对获取的结果数据按倍数放大或缩小,那么为何不能执行如下命令:
<syntaxhighlight lang="mcfunction">
execute store result storage generic:test v double 0.000001 run data get storage generic:test test 1000000
</syntaxhighlight>

如上所示,表面上看起来是:先放大到原来的1000000倍,这样能够取到整数123123456,然后再缩小相应倍数,理应得到123.123456,但是由于浮点数再计算机内的存储并非是精确的,其总是可能在尾数部分产生误差,所以实际得到的结果可能为:
{{snbt|bg=block|<nowiki>{test: 123.123456d, v: 123.12345599999999d}</nowiki>}}

总的来说,对于浮点数,如果希望保留原始精度,最好使用{{cd|data}}命令。当然,如果你希望使用一条命令对获取到的NBT数据进行缩放并存储,那么用{{cd|execute store}}也没什么问题。

其实,如果你认真接触过{{cd|data ... storage}}命令,你会发现命令存储很容易实现我们开头提到的第二个问题。对于命令存储中的数据,你可以将其当成属于存档的“全局数据”。在保存游戏后,它将以.dat文件的形式存储在存档的{{filepath|data}}目录中,你也可以使用一些软件来查看其中的数据。

有时候,我们在一个命令存储中存储了大量数据,想要全部删除,那么你可以通过打开存档的.dat文件并直接删除对应命令存储的子标签。具体的文件格式可以参考{{slink|命令存储存储格式}}。只要存档是完整的,那么你就可以通过{{cmd|data ... storage}}命令来访问命令存储的数据。

全局数据是容易操作的,但是如果把全部数据都存在命令存储中,这无疑会造成空间浪费以及数据管理上的困难。很多时候,我们希望对指定的游戏对象添加数据,比如,我们在游戏中使用铁锭模拟一个特殊的货币,但存在一个问题:玩家可以直接合成铁锭。为了让原版的铁锭特殊化,我们可以利用{{cd|custom_data}}组件来存储一系列自定义的数据。

比如,执行如下命令后:
<syntaxhighlight lang="mcfunction">
/give @s minecraft:iron_ingot[minecraft:custom_data={id:"test:iron_twist_egg_coin"}]
</syntaxhighlight>

该铁锭的{{cd|minecraft:custom_data}}组件中便拥有一个新增的{{nbt|string|id}}字段。

在数据包中,可以使用物品修饰器将数据定义分离出来:
<syntaxhighlight lang="mcfunction">
[
{
"function": "set_components",
"components": {
"custom_data": {
"custom_item": true,
"id": "lbj:straw_hat"
},
"item_model": "lbj:straw_hat",
"item_name": "草帽",
"equippable": {
"slot": "head"
}
}
}
]
</syntaxhighlight>

== 数据传递 ==
; 宏函数的参数传递
宏函数允许接收传入的数据,并直接转换为命令的影响和作用。从这个方面来说,宏函数中的命令也可以被称为“动态命令”。

在1.21.5引入SNBT的16进制等新形式后,其实传递到宏函数的结果并没有改变——数值型数据依然以十进制数被传递到宏行参数。

比如,有以下宏函数:
{{file display|test:test|mcfunction|<nowiki>
$say $(value)
</nowiki>}}

执行以下命令:
<syntaxhighlight lang="mcfunction">
/function test:test {value:0xABCL}
</syntaxhighlight>

输出的结果为2748,非所期望的十六进制形式。

对于新手,需要注意所传递的数据并非是所看到的SNBT形式(例如上例中并没有保留{{nbt|long}}类型尾缀)。以下为传递字符串和传递复合标签结构的例子。先执行如下命令:
<syntaxhighlight lang="mcfunction">
/function test:test {value:"test"}
</syntaxhighlight>

字符串的左右引号并不会被保留。而如果改为:

<syntaxhighlight lang="mcfunction">
/function test:test {value:{a: 1, b:"hi"}}
</syntaxhighlight>

则会保留左右花括号,输出“{a: 1, b:"hi"}”。

; 传递物品数据信息到资源包
[[物品模型映射]]类型{{cd|range_dispatch}}可以为{{cd|custom_model_data}}中的不同值分配不同的模型,这可以用来实现物品模型动画帧。

物品模型映射也可调用数据组件谓词来条件性地筛选组件数据并显示不同模型。

另外,对于一些命令无法操作和访问的数据(比如物品的模型变换位置)也能通过物品模型映射进行判断和选定。

; 传递物品信息到实体
刷怪蛋、生物桶等能够生成实体的物品,会在被使用时复制一些数据到所生成的生物。利用这个特点,我们可以将物品的自定义数据复制到实体的自定义数据中,随后通过其他方式变换到实体上下文,并在函数中继承该上下文。

== 数据操纵 ==
数据的基本操作:增加、修改、可以通过命令{{cmd|data modify}}和{{cmd|data merge}}实现,数据的删除可以通过{{cmd|data remove}}实现。

从数据结构的角度来说,这些操作无非是对于SNBT背后的抽象NBT结构树的节点的修改的删除。

对于2类基本的数据操纵对象:实体、物品,有不同的数据操纵方式。

; 实体
实体可以大致分为
* 玩家实体。
* 除玩家实体以外的实体。

玩家实体的特殊性在于,玩家本身的NBT操作是受限的,一般只能通过其他命令来间接实现数据操纵。以下列出几种常见情况:
* {{cmd|tp}}、{{cmd|rotate}}命令可以实现类似于对玩家{{nbt|double|Pos}}和{{nbt|float|Rotation}}的直接修改操作。
* 在玩家脚部创造爆炸可以模拟对玩家{{nbt|double|Motion}}的修改操作。
* {{cmd|item}}命令可以实现对玩家背包数据{{nbt|compound|Inventory}}的修改。

; 物品
一般地,无论是存在于实体还是方块容器内的物品,都可以通过{{cmd|item}}进行修改。
* 可以调用提前制定的物品修饰器进行修改。
* 也可以配合宏函数,调用内联SNBT形式的物品修饰器,传入需要动态修改的数据。

由于物品的很多行为都由数据组件定义,所以对于物品数据的动态操作,也可归结为使用宏函数动态执行{{cd|set_components}}物品修饰器的过程:
{{file display|generic:data/set_slot_components|mcfunction|<nowiki>
$item modify entity @s $(slot) {function:"set_components", components:$(components)}
</nowiki>}}

== 可用物品堆叠组件 ==
== 可用物品堆叠组件 ==
{{nbt collapsed source|test|no-remove=1|
{{nbt collapsed source|test|no-remove=1|

2025年3月9日 (日) 11:48的最新版本

数据存储[编辑 | 编辑源代码]

本章将讨论或解决如下问题:

  • 获取任意命令的反馈参数。
  • 在退出游戏或卸载数据包后数据仍然存在并可恢复。
  • 添加自定义的数据。

对于任意命令,都可以使用/execute store存储其某个反馈参数值。但要注意,对于同一个命令,并不是其所有参数都能被获取。具体能够被存储的参数内容应该参考相应命令页面的“输出”章节。

比如,对于命令/random,你可以通过execute store存储其抽取的随机值。获取到参数值后,你可以存储到某个实体或虚拟玩家的记分项中,也可以存储到命令存储中。

  • 如果你接下来即将对获取到的值进行大量运算,一般选择存储到记分项中。
  • 如果是为了备用或者传递到宏函数中,则应存储到命令存储。

值得注意的是,所反馈的参数值将先被向下取整后再进行存储——这将导致浮点数的小数位丢失。比如,对于以下的命令存储:

{test: 123.123456d, v: 0}

以下命令执行后:

execute store result storage generic:test v double 1.0 run data get storage generic:test test

命令存储将变为:

{test: 123.123456d, v: 123.0d}

显然,如果想保留数据的完整形式,最好直接使用/data modify命令:

data modify storage generic:test v set from storage generic:test test
{test: 123.123456d, v: 123.123456d}

你可能想到,/execute store可以对获取的结果数据按倍数放大或缩小,那么为何不能执行如下命令:

execute store result storage generic:test v double 0.000001 run data get storage generic:test test 1000000

如上所示,表面上看起来是:先放大到原来的1000000倍,这样能够取到整数123123456,然后再缩小相应倍数,理应得到123.123456,但是由于浮点数再计算机内的存储并非是精确的,其总是可能在尾数部分产生误差,所以实际得到的结果可能为:

{test: 123.123456d, v: 123.12345599999999d}

总的来说,对于浮点数,如果希望保留原始精度,最好使用data命令。当然,如果你希望使用一条命令对获取到的NBT数据进行缩放并存储,那么用execute store也没什么问题。

其实,如果你认真接触过data ... storage命令,你会发现命令存储很容易实现我们开头提到的第二个问题。对于命令存储中的数据,你可以将其当成属于存档的“全局数据”。在保存游戏后,它将以.dat文件的形式存储在存档的data目录中,你也可以使用一些软件来查看其中的数据。

有时候,我们在一个命令存储中存储了大量数据,想要全部删除,那么你可以通过打开存档的.dat文件并直接删除对应命令存储的子标签。具体的文件格式可以参考命令存储存储格式。只要存档是完整的,那么你就可以通过/data ... storage命令来访问命令存储的数据。

全局数据是容易操作的,但是如果把全部数据都存在命令存储中,这无疑会造成空间浪费以及数据管理上的困难。很多时候,我们希望对指定的游戏对象添加数据,比如,我们在游戏中使用铁锭模拟一个特殊的货币,但存在一个问题:玩家可以直接合成铁锭。为了让原版的铁锭特殊化,我们可以利用custom_data组件来存储一系列自定义的数据。

比如,执行如下命令后:

/give @s minecraft:iron_ingot[minecraft:custom_data={id:"test:iron_twist_egg_coin"}]

该铁锭的minecraft:custom_data组件中便拥有一个新增的字符串id字段。

在数据包中,可以使用物品修饰器将数据定义分离出来:

[
  {
    "function": "set_components",
    "components": {
      "custom_data": {
        "custom_item": true,
        "id": "lbj:straw_hat"
      },
      "item_model": "lbj:straw_hat",
      "item_name": "草帽",
      "equippable": {
        "slot": "head"
      }
    }
  }
]

数据传递[编辑 | 编辑源代码]

宏函数的参数传递

宏函数允许接收传入的数据,并直接转换为命令的影响和作用。从这个方面来说,宏函数中的命令也可以被称为“动态命令”。

在1.21.5引入SNBT的16进制等新形式后,其实传递到宏函数的结果并没有改变——数值型数据依然以十进制数被传递到宏行参数。

比如,有以下宏函数:

File file.png:Minecraft中file的精灵图 test:test
mcfunction
$say $(value)

执行以下命令:

/function test:test {value:0xABCL}

输出的结果为2748,非所期望的十六进制形式。

对于新手,需要注意所传递的数据并非是所看到的SNBT形式(例如上例中并没有保留长整型类型尾缀)。以下为传递字符串和传递复合标签结构的例子。先执行如下命令:

/function test:test {value:"test"}

字符串的左右引号并不会被保留。而如果改为:

/function test:test {value:{a: 1, b:"hi"}}

则会保留左右花括号,输出“{a: 1, b:"hi"}”。

传递物品数据信息到资源包

物品模型映射类型range_dispatch可以为custom_model_data中的不同值分配不同的模型,这可以用来实现物品模型动画帧。

物品模型映射也可调用数据组件谓词来条件性地筛选组件数据并显示不同模型。

另外,对于一些命令无法操作和访问的数据(比如物品的模型变换位置)也能通过物品模型映射进行判断和选定。

传递物品信息到实体

刷怪蛋、生物桶等能够生成实体的物品,会在被使用时复制一些数据到所生成的生物。利用这个特点,我们可以将物品的自定义数据复制到实体的自定义数据中,随后通过其他方式变换到实体上下文,并在函数中继承该上下文。

数据操纵[编辑 | 编辑源代码]

数据的基本操作:增加、修改、可以通过命令/data modify/data merge实现,数据的删除可以通过/data remove实现。

从数据结构的角度来说,这些操作无非是对于SNBT背后的抽象NBT结构树的节点的修改的删除。

对于2类基本的数据操纵对象:实体、物品,有不同的数据操纵方式。

实体

实体可以大致分为

  • 玩家实体。
  • 除玩家实体以外的实体。

玩家实体的特殊性在于,玩家本身的NBT操作是受限的,一般只能通过其他命令来间接实现数据操纵。以下列出几种常见情况:

  • /tp/rotate命令可以实现类似于对玩家双精度浮点数Pos单精度浮点数Rotation的直接修改操作。
  • 在玩家脚部创造爆炸可以模拟对玩家双精度浮点数Motion的修改操作。
  • /item命令可以实现对玩家背包数据NBT复合标签/JSON对象Inventory的修改。
物品

一般地,无论是存在于实体还是方块容器内的物品,都可以通过/item进行修改。

  • 可以调用提前制定的物品修饰器进行修改。
  • 也可以配合宏函数,调用内联SNBT形式的物品修饰器,传入需要动态修改的数据。

由于物品的很多行为都由数据组件定义,所以对于物品数据的动态操作,也可归结为使用宏函数动态执行set_components物品修饰器的过程:

File file.png:Minecraft中file的精灵图 generic:data/set_slot_components
mcfunction
$item modify entity @s $(slot) {function:"set_components", components:$(components)}

可用物品堆叠组件[编辑 | 编辑源代码]

在游戏中总共定义了下列物品堆叠组件:

基本
外观
附魔
使用
物品损伤、物品修复
杂项
数据存储
刷怪蛋、桶装生物
非持久化组件

creative_slot_lock:不可以导出和加载,仅网络同步

  • 应用对象:所有物品。
  • 在创造模式保存的物品栏中拥有此组件的物品将无法交互,但仍可通过快捷键存储或加载到快捷栏,除此之外与正常物品没有区别
    默认附加到“已保存的快捷栏”中代表没有快捷栏信息的

map_post_processing:不可以导出和加载,仅网络同步

  • 应用对象:地图。
  • 同步地图的缩放等级和锁定信息。