デタパ初心者~中級者向けの使える小ネタ

:::note info
注意事項:初心者向けです。
:::

1.NBT参照
 ---------------------------------------
dataやexecute storeで使う＜path＞を使うとき

`〇:{◇:{△:x}}`
〇.◇.△とすると値をとれる

例:所持しているアイテムのカスタムデータ
```SelectedItem:{アイテムの情報,tag:{Custom_data:100}}```
の"100"をとりたい時
```data get entity @s SelectedItem.tag.Custom_data```
で値をとることができる。
基礎的なことだからかあまり書かれてない印象

他にも
`〇:[X,Y,Z]`
は〇.[0~2]でその場所の値をとれる。


2.マクロとStorage
---------------------------------------
 
```function 名前空間:実行するfunction with storage 使用するStorage 参照```
の参照のところはfunction内の
`参照:{アイテム,個数}`
となるようにする必要がある

``` ruby:function
$give @s $(アイテム) $(個数)
```
3.Randomコマンド追加前の乱数生成
---------------------------------------

``` ruby:事前スコアボード
scoreboard objectives add rng dummy
scoreboard players set #100 rng 100
```

``` ruby:乱数生成
summon minecraft:area_effect_cloud ~ ~ ~ {Tags:["random"]}
execute store result score @s rng run data get entity @e[tag=random,distance=..0.01,sort=nearest,limit=1] UUID[0]
scoreboard players operation $random Random_z %= #100 rng
```
詳細はまっしゅ氏が解説している[動画](https://www.youtube.com/watch?v=AjDvvOWVGOA "")がとても参考になるので気になる人はそっちを見てね

4.無敵時間を無視してダメージを与える方法
---------------------------------------
マイクラの仕様上、直前に受けたダメージより大きいダメージを受けるとその差分のダメージを与えるというもの

``` ruby:例
damage @s 1
damage @s 4
```
このfunctionを実行した場合 1+(4-1)で4ダメージ入ることになる
コンボ技とか作るときに知っておいたほうがいい

5.ダメージを与えずにダメージモーションをとらせる方法
---------------------------------------
 /damage実装前で特に使える方法
 
 ```
 普通のMOBはdamage
 アンデッド系はhealth
 effect give @e[type=アンデッド以外] instant_damage 1 29
 effect give @e[type=アンデッド] instant_health  1 29
 ```
 
 いま同じことをやるなら/damageの方がいいと思う。

6.軽量化について
---------------------------------------
同時に多くのfunctionが実行されないようにしておこう
また、一つにまとめられるfunctionはまとめたほうが処理が軽くなる

その他 @sを使うと軽いーとかセレクタの順番によって負荷が変わるー　
とか軽量化を極めるのは難しい。
軽量化に関しては突き詰めるとキリがないからあまり気を詰めすぎないようにしよう。
この例みたいな酷いものじゃなきゃ大抵は大丈夫だろう

``` ruby:例
execute as @a at @s run summon armor_stand ~ ~ ~ {Tags:["Fire"]}
execute as @a at @s run tp @e[tag=Fire,limit=1,sort=nearest] ~ ~ ~ ~ ~
execute as @a at @s run playsound minecraft:item.firecharge.use master @s ~ ~ ~ 1 1.5
execute as @e[tag=Fire] at @s run tp @s ^ ^ ^0.5
execute as @e[tag=Fire] at @s run damage @e[distance=..3,type=!player,tag=!Fire] 4
execute as @e[tag=Fire] at @s at @e[distance=..3,type=!player,tag=!Fire] run kill @s
```
ちなみにこれは自分が初めてデータパックを作ったときみたいな感じに書いたものです


::: note info
慣れてない人へ
気にするとよくわかんなくなる人は気にしないで上達してから気を付けたほうがいい
:::

7.高速で飛ばす魔法や銃弾の作り方
---------------------------------------
 
 ::: note info
中級者向け
:::
 ::: note warn
function THISの部分は条件指定しないとコマンドを最大数実行するので絶対に
ifなどで条件を付けよう
:::
tpコマンドなどで銃弾を飛ばすときに
executeで弾をasで@sにして
```tp @s ^ ^ ^A(適当な数字)```
で飛ばしたりするとき、Aを大きい数にするとその分の判定が抜けてしまうことがあります。
そういうときは
``` ruby:事前に実行
scoreboard objectives add Time dummy
```
ここのTimeはどんな名前でもいいです
```ruby:
tp @s ^ ^ ^B(0~1くらいまでの数字)

#ダメージ与えるとかの処理
#ブロックに当たるとかの処理

scoreboard players add @s Time 1
execute if entity @s[scores={Time=C}] positioned as @s run function THIS(このfunction自身)
scoreboard players reset @s Time
```
こんなかんじに書くとB×Cの距離分を1tickで移動させることができてBの距離移動する毎に処理が実行されるので便利です。

ただ、Bの値を小さくしたり、Cの値を大きくする、または#ダメージ・ブロックに当たる処理の部分を多くすると実行される回数が増え処理が重たくなるので注意


<details><summary>補足</summary>

---------------------------------------

```ruby:
tp @s ^ ^ ^0.5


execute positioned ~-0.5 ~-0.5 ~-0.5 if entity @e[dx=0.5,dy=0.5,dz=0.5,limit=1,sort=nearest,type=!#barst_couple:not_living_entity,type=!player] run tag @s add barst

execute positioned ~-0.5 ~-0.5 ~-0.5 if entity @e[dx=0.5,dy=0.5,dz=0.5,limit=1,sort=nearest,type=!#barst_couple:not_living_entity,type=!player] run damage @e[dx=0.5,dy=0.5,dz=0.5,limit=1,sort=nearest,type=!#barst_couple:not_living_entity] 3 explosion

execute unless block ^ ^ ^0.75 air run tag @s add barst

execute if entity @s[tag=barst] run kill @s
scoreboard players add @s Time 1
execute if entity @s[scores={Time=..5}] unless entity @s[tag=barst]
positioned as @s run function THIS
scoreboard players reset @s Time
```
<font color="red">**そしてダメージを与える時はタグをこんな感じで利用しないと重複するので注意**</font>

---------------------------------------
</details>

あと、Displayで表示しているものを動かしたいときは別の方法をとった方が無難かも…

また、Motion式や、displayのinterpolation_durationとかの方がいい場合もあるかもしれないので
用途に合わせて考えよう。
また、最新版1.20.4とかだとreturnコマンドで似たようなことができるかも…


8.Datapackを作るときに使えるソフト
---------------------------------------
 
[VSCode](https://code.visualstudio.com/ "")
[BlockBench](https://www.blockbench.net/ "")(+Animated Java)

とくにこだわりがなければVSCodeを使うことを推奨する。
他の方が紹介している拡張機能をつかえば楽に作業できる
普通のテキストソフトを使うとスペルミス探しで数時間つぶれたりする可能性があるし、
ものによっては変な癖がつくかもしれない。(自分はついた)

3Dモデル作りで重宝するソフト。アイテムや武器、そしてエンティティも作ることができる
BlockBenchのプラグインであるAnimated javaを使えばアニメーションさせることもできる。

9.Datapackを作るときに使えるサイト
---------------------------------------
 
[データパックジェネレーター](https://misode.github.io/ "")
[MCStacker](https://mcstacker.net/ "")

データパックジェネレーターはAdvancementやPredicateなど作るときに各項目を設定することで
面倒なjsonファイル作りを楽にできて
MCStackerはアイテムを作るときとかに設定することでコマンドを生成してくれるもの
ただ、execute ifとかは自分で書いた方が楽な時もあるから適度に使おう

10.なぜか動かない!!ってときにありがちなこと
---------------------------------------

このようなコマンドがあったとして
```execute if entity @s[scores={IQ=..0}] run tell @s バーカ```
テストワールドでは実行できててもべつのワールドで実行できないことがあります。
それはスコアボードの"0"と"設定されてない状態"は別になっているので
```scoreboard players set @s Time 0```
と一度0にする必要があります。

テストワールドでは設定されてても別では設定されてないことが多々あるので注意が必要です。


11.dx,dy,dzを用いた範囲指定の注意
 ---------------------------------------
dx,dy,dzを使って当たり判定を作ることで敵のヒットボックスで
判定することができるようになります。
distanceを使った場合、モブの中心(？)でしか判定が行われません。

つまり、魔法とか攻撃の当たり判定はdx,dy,dzを使えばいいということです


 distanceの範囲はこの上の青の円のように円形かつ、上下左右の中心ですが
 dx,dy,dzを利用した範囲指定をするとその場所からXYZ座標の+の方向が範囲になります。
そのため、dx,dy,dzの範囲指定の場合、ちょうど真ん中になるようにpositionedで調整する必要があります。
 ![2023-12-06_02.10.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3592343/bac03494-6697-5ef5-fa2c-bfff0b9570c7.png)
~~~ ruby:コマンドの内容
execute if entity @a[distance=..5]
execute if entity @a[dx=5,dy=5,dz=5]
~~~

```(0.5+a)/2 (aはdx,dy,dzの値)```
だいたい上の式で出た値をpositionedに入れるとこうなります
~~~ ruby
execute positioned ~-2.75 ~-2.75 ~-2.75 if entity @a[dx=5,dy=5,dz=5]
~~~

さらに本来dx,dy,dzではすべて0に設定しても1ブロックの判定ができていますが、
二重で検知させると、より小さい範囲も検知できます。

最後に…
 ---------------------------------
今回紹介したもの以外にももっと効率的だったりするのもあると思うので良ければコメント欄にでも情報記載してくれると嬉しいです。