「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:不可以匯出和載入,僅網路同步

  • 應用對象:地圖。
  • 同步地圖的縮放等級和鎖定資訊。