【丁寧に解説】Skriptをはじめよう　1：簡単なスクリプトを書いてみよう

:::note alert
諸事情により、記事をこれ以降更新することができなくなってしまいました。
今まで投稿した本シリーズの記事はそのまま残しておきますが、新しく記事が追加されることはありません。
:::
:::note warn
この記事はマインクラフトのプラグインである Skript の解説記事ですが、筆者はこのプラグインを触り始めたばかりなので間違った記述がある可能性があります。また、質問に必ず回答できるとは限りません。以上を踏まえたうえでこの記事をお読みください。
:::
【前回】

https://qiita.com/Logtain/items/fa984e97c7e6cc38962c
## 大事な前作業（必読）
皆さんこんにちは、ろぐと申します。
前回は Skript をより効率的に利用するための準備をしました。今回は早速スクリプトの作成に入っていきます！
ただ、**実は最後にもう１つだけ、やらなくてはいけないことがある**んです。

「えぇ...まだあんのかよ...。」

と思ったそこのあなた！この作業は早ければ１分程度で終わります。どうかお付き合いください...！

:::note alert
これから記述する作業を行わないと、**Skript のバージョンが上がったときにスクリプトが動かなくなる可能性があります。** そうなってから手作業で修正することもできますが、かなりの手間です。ぜひこの項はスキップせず、最後まで読んでください！
:::
### ```config.sk``` ファイルの設定
<details><summary>config.sk ファイルとは？</summary>

> ```config.sk``` ファイルは、**プラグインの詳細な設定をするためのファイルです！** ほとんどすべてのプラグインにあります。（ただし他のプラグインでは拡張子が ```.yml``` です）これを編集することによってプラグインを自分好みにカスタマイズできたり、挙動を変更したりできるのでサーバー管理者にはおなじみのファイルです！
</details>

今回は Skript の ```config.sk``` ファイルを編集していきます。といっても何も難しいことは無いので、身構えなくても大丈夫です！

**手順**
> 「plugins」フォルダ → 「Skript」フォルダ → ```config.sk``` ファイルを開いてください。(テキストエディタはなんでもOKですが、行数が分かるものがよいです）
※前回の記事で Sublime Text を「常に使う」に指定した場合は、そちらで開かれます。

```config.sk``` の中身はこのようになっていると思います。
```config.sk
#     __________________________________________________________
#    / /                                                   / /\ \
#    \_\___________________________________________________\_\/ /
#        / /    _____    __            __                    / /
#       / /    / ____\  / /           /_/          /\       / /
#      / /    / /__    / /___  ___   __  ______ __/ /_     / /
#     / /     \___ \  /   __/ / __\ / / / __  //_  __/    / /
#    / /     ____/ / / /\ \  / /   / / / /_/ /  / /      / /
#   / /     \_____/ /_/ /_/ /_/   /_/ / ____/  /_/      / /__
#  / /    ========================== / / ==========    / / \ \
# | |                               /_/               | |   | |
#  \_\_________________________________________________\_\_/_/
#
# == Introduction ==
# This file contains Skript's general options. To write scripts, create a new .sk file in the scripts folder or edit any existing one.
#
# Script files prefixed with a hyphen (-) will not be loaded, e.g. renaming 'plant with hoe.sk' to '-plant with hoe.sk' will disable the whole file.
# This can e.g. be used to temporarily disable scripts and is also used for Skript's example scripts.

（うんたらかんたら...）
```
なかなかすごいアスキーアートだな...

おっと、話がそれました。このファイルを開いたら、**91行目まで移動してください！**
すると、こんな文章があると思います。（バージョンによって多少行番は前後するかもしれません）
```config.sk 91行目
use player UUIDs in variable names: false
```
今は意味は分からなくていいので、とりあえず ```false``` **と書いてある部分を** ```true``` **に変更してください。**
```config.sk 91行目 変更後
use player UUIDs in variable names: true
```
（もちろん上書き保存もしてくださいね）

これで作業は終了です！めちゃくちゃ簡単でしたよね？
```config.sk``` ファイルはもう使わないので閉じてしまって大丈夫です～！
<details><summary>【発展】この作業が意味するもの（長文注意）</summary>

> ※ここに記してあることは非常に難解です。変数についての理解を深めてから読むことをおすすめします。

> 先ほど変更した設定を日本語訳すると
```変数名でプレイヤーUUIDを使用する：はい```
> となります。UUIDはプレイヤーごとに与えられる個別の識別子です。
また最初の記事で少し説明しましたが、Skript には変数という「自分で好きな値を入れられる箱」を作れる機能があります。変数は ```{Name}``` のようなフォーマットで定義します。```Name``` と書かれた部分が変数名です。
実はこの変数、名前の内部にエクスプレッションを挿入することが可能です。例えば ```{Name.%player%}``` とすると、仮にこの変数が置かれたスクリプトが実行された場合、変数名は現時点では ```{Name.実行したユーザー名}``` となります。これはプレイヤーごとに変数を用意することができるとても便利な機能です。
しかし、ここでひとつの問題が生じます。同じ名前（ID）を有するプレイヤーが存在した場合、変数名が被ってしまい区別がつかなくなってしまうのです。そこで Skript はこれを回避するために、近い将来変数内の ```player``` エクスプレッション（つまり ```%player%``` ）をすべてUUIDに変換するようにすると明言しています。先に述べた通りUUIDはプレイヤーごとに与えられるので、被ることはありません。これで変数をより安定して使用することができますが、**仮にこの変換アップデートが実装された場合、既に作成されているプレイヤー名入りの変数とは完全に別の名前の変数が生成されます。** つまり ```%player%``` 部分がユーザー名の変数とUUIDの変数が共存する形になり、またユーザー名変数の値はUUID変数には引き継がれないためスクリプトに深刻なバグが生じる可能性があるというわけです。
これを未然に防ぐために行ったのが先の設定変更です。項目を ```true``` にすることによって始めから変数内部の ```player``` をUUIDに変換するようになります。（デフォルトではユーザー名に変換）これでいつアップデートが来ても安心です。

</details>

## はじめの一歩
ついに、スクリプトを書く段階まで来ることができました...！
早速 ```.sk``` ファイルを作りますが、その前に **「scripts」フォルダの中に「study」というフォルダを作成しましょう！**

:::note
前回でもちょこっと説明しましたが、この **「study」というフォルダが、このシリーズでの作業場になります。** なので、今後「○○っていうファイルを作ってね～」という指示があったら、すべて「study」フォルダの中に作成するものと考えてください！
※知識がある方は、ここ以外にファイルを作成しても構いません。
:::
![Screenshot 2024-04-15 130200.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/2e7b9eb0-13c6-4385-e844-4e08493840b0.png)
（「scripts」フォルダ内の様子　※ ```-- Files prefixed...``` ファイルは削除しています）

なおこれ以降の記事では、もう「-examples」フォルダの中の ```.sk``` ファイルは使いません。なので、必要なければ「-examples」フォルダごと削除してしまっても大丈夫です！

:::note warn
**【ファイルの呼称名について】**
今まで、拡張子が ```.sk``` のファイルはすべて「 ```.sk``` ファイル」と呼んできましたが、これだと文が長くなり煩わしいので、**これ以降の記事では「** ```.sk``` **ファイル」は単純に「ファイル」と呼称します。**（これ以外の拡張子の場合は都度注釈を入れます）
:::

下地も整ったので、早速「study」フォルダの中に ```Part1.sk``` というファイルを作成し、テキストエディタで開きましょう！（**マイクラサーバーは起動せずに**作業してください）

![Screenshot 2024-04-15 131912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/2512e3e9-3ad1-f98d-1b8f-7fe4fd968c55.png)
（作業画面の例）

### １．ログインメッセージを変えよう
では早速ですが、この中に
```Part1.sk
on join:
    set the join message to "Hello World!"
```
と書き、（もちろん上書き保存して）マイクラサーバーを起動してください。（起動または再起動でスクリプトが読み込まれます）
そして、起動したサーバーに参加してみると...

![2024-04-15_13.33.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/dd73af7c-911b-f64f-d447-08d5775b1686.png)

**参加したときのメッセージが変わってる！！**

...まあ、これは最初の記事で紹介したので、驚かなかった人の方が多いかと思いますが...。
では早速このスクリプトの解説をしていきましょう！

まず、このスクリプトを一般化してみると...
```Part1.sk 一般化
イベント:
(TAB)エフェクト
```
となります。ただ、いきなり専門用語を出されても分かりませんよね。順番に見ていきましょう！

#### 【イベント】
イベント（Event）は、「○○が起こったら」「○○が○○になったら」など、**ゲーム内で何かしらの動きがあったかどうかチェックする**ものです。先ほどのイベントは ```on join``` であり、これを日本語訳すると **「参加した時」** という意味になります。
**イベントは Skript の根幹といってもいいものです。** これがないと、先ほどのスクリプトは動きません。
イベントは本当にたくさんの種類があり、ここではすべてを紹介することはできません...。
参考程度ですが、一部を紹介しましょう！

|イベント名|日本語訳|意味|
|---|---|---|
|```on join```|参加した時|プレイヤーがサーバーに参加した時|
|```on quit```|退出した時|プレイヤーがサーバーから退出した時|
|```on place```|設置した時|任意のブロックが設置された時|
|```on break```|参加した時|任意のブロックが破壊された時|
|```on chat```|チャットした時|任意のプレイヤーがメッセージを送信した時|
|```on damage```|ダメージの時|任意のエンティティがダメージを 受けた / 与えた 時|

まだまだたくさんのイベントがあります！ぜひ調べてみてください！

#### 【エフェクト】
エフェクト（Effect）は、**イベントが発動した時、その動作を行う**ものです。
つまりイベントとエフェクトを組み合わせることによって、「○○が起こった時、○○する」といったスクリプトが書けるわけです！
組み合わせはまさに無限大。Skript の可能性を感じますね！
こちらも参考程度に一部を紹介します。

|エフェクト名|日本語訳|意味|
|---|---|---|
|```set```|設定する|任意の値を設定する|
|```send```|送る|任意のプレイヤーにメッセージを送信する|
|```broadcast```|放送する|プレイヤー全員にメッセージを送信する|
|```delete```|消去する|任意の値を削除する|
|```execute```|実行する|任意のコマンドを実行者を指定して実行する|
|```add```|加える|任意の値を加える|
<details><summary>【補足】「任意」とは</summary>

> 数学の授業で聞いたことがある人もいるかもしれませんが、「任意」というのは「その人の判断にゆだねる」、つまり **「なんでもいいですよ～」という意味**です！
例えば、「任意の値」と言われたら、それは「自分で選べる好きな値」という意味です。
</details>

:::note
**Q：**```(TAB)``` **って何？**

**A：キーボードの左の方にある「Tabキー」を押すと打てる空白です。**
```(TAB)``` は、半角スペース４つ分と同じ大きさの空白です。ただ、```(TAB)``` と半角スペースは違うものなので注意してください。（**半角スペース４つ ≠** ```(TAB)``` ）そのため、```(TAB)``` **の代わりに半角スペースを入力するとエラーが発生することがあります。** 必ず ```(TAB)``` を使用するようにしてください。

また、```(TAB)``` を使用した行先頭の空白のことを、プログラミング用語で**インデント**と言います。今後の記事でこの表現を用いる場合もあるので、頭の片隅に入れておいてください！
:::

### ２．記述ルールをおさえよう
Skript のルールとして、**イベントの後には** ```:```**（半角コロン）を、エフェクトの前には** ```(TAB)``` **を入力する**ことが定められています。これを入力しないと、Skript がイベントとエフェクトを区別できず、エラーとなってしまうのでご注意ください...！

```Part1.sk ダメな例１
# 半角コロンや(TAB)が入っていない

on join
set the join message to "Hello World!"
```
また、```"``` **（ダブルクォーテーション）の中や、変数名・関数名**（のちの記事で解説します）**以外の場所は、すべて小文字**で記述してください。そして、**イベントとエフェクトの間は必ず改行**してください！

```Part1.sk ダメな例２
# 大文字が入っている

On Join:
    Set the Join Message to "Hello World!"
```

```Part1.sk ダメな例３
# 改行されていない

on join:    set the join message to "Hello World!"
```
禁止事項をいろいろと並べてしまいましたが、以下に示す形に従えば大丈夫です！
```
イベント:
(TAB)エフェクト
```
Skript の基本形はすべてこれです！**これ以外の形になることはほぼあり得ない**ので、まずはこの形を覚えましょう！

:::note
```#``` がはじめについている行は**コメント**と呼ばれます。この行はスクリプト実行時には無視されます。
今後長くて複雑なコードを書く場面が出てきますが、どれがどんな役割だったか忘れてしまうこともしばしば。（特に久しぶりに見るコードはちんぷんかんぷんです...）**メモのように使える**ので、特に初心者の方は積極的に使ってきましょう！
また、このシリーズでもコードをより分かりやすくするためにコメントを用いることがあります。真似してコードを書くときはコメントは除いていただいて結構です。
:::

:::note warn
ここまでは、Tabキーを使用した空白を ```(TAB)``` と表現してきましたが、これ以降のスクリプトには示さないのでご注意ください。
:::
### ３．イベントやエフェクトの「引数」とは？
先ほどのスクリプトは、こんな感じでした。
```Part1.sk
on join:
    set the join message to "Hello World!"
```
ここで、あなたは **「ブロックを設置した時」** に **「そのブロックの設置をキャンセルする」** スクリプトを作ってみることにしました。

先ほどのリストを参照すると、「ブロックを設置した時」というイベントは ```on place``` を、「設置をキャンセルする」エフェクトは ```cancel``` を使えば良さそうだな...ということが分かります。
（ ```cancel``` はリストには書かれていませんでしたが、意味を考えても「これを書けばよさそう...」と分かると思います。このように**知らない処理もなんとなく感覚で書ける**のが Skript のいいところです！）

ということで、こんなコードを書いてみました！
```Part1.sk
on join:
    set the join message to "Hello World!"

on place:
    cancel
```
（下の２行が追加した部分）

これを Skript に読み込ませるために、上書き保存してサーバーを再起動すると...

![Screenshot 2024-04-15 171246.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/e0f933c0-3543-8190-02d6-7dce0380cd72.png)
（コンソールより）

**...あれ？**

エラーが出てしまいました。おかしい、これで合っているはずなのに...。どうやら、このスクリプトの５行目、```cancel``` でエラーが発生したようです。
では原因を紐解くため、```on place: ~``` の部分を日本語訳してみましょう。
```
設置した時:
    キャンセルする
```

特に間違いはないように見えますが、よ～く見てみると...

**...「何を」キャンセルするんだ？**

そうです。**「何を」キャンセルするか示していなかったため、エラーが発生した**のです。
人間なら、文脈から「ああ、設置をキャンセルすればいいのね」と分かります。しかし、Skript 君にそこまでの柔軟性はありません。**「何を」** キャンセルするのか、教えてあげないといけなかったのです。
では、手直ししてみましょう！今回キャンセルしたいのは「ブロックの設置」、つまりイベントそのものをキャンセルすればよさそうです。よって、間違えた部分を書き直すと...

```Part1.sk
on join:
    set the join message to "Hello World!"

on place:
    cancel event 
    
    #「event」を付け加えた
```

こんな感じになります。サーバーを再起動して、試しにブロックを設置してみると...？

**やった！設置できない！**

これで成功です！
#### 結局何が言いたかったのか
つまり、イベントやエフェクトには、「何を」「どんな」「どこで」のように、**追加の情報が必要な場合がある**、ということです。```on place:``` も、**「何を」** 設置したときなのか指定していないため、自動的にすべてのブロックが対象になりました。このように、イベントやエフェクトに対して追加の情報を与えるためのものを **引数（ひきすう**、英語表記：**Argument）** と呼びます。
引数を使用することで、イベントやエフェクトはその真価を発揮します！例えば ```send``` は...

```send message```：ふつうのメッセージを送信
```send action bar```：アクションバータイトルを送信
```send <player> title```：タイトルを送信

ここでは「何を」送信するかしか指定していませんが、実際はこの後に「内容」「対象」「表示時間」などが続きます。実際に使用するときには
```
    send message "こんにちは！" to player
    
#   送る   何を       内容         対象
```

のような感じになります。```send``` 以降はすべて引数です。
引数については次回詳しく解説します！実は、Skript の引数って一般的なプログラミング言語と比べて少し難しいんです...。今回は「引数ってこんなものなんだ～」ということを分かっていただければOKです！
（実は ```message``` や ```to player``` は省略してもよかったりします。詳しいことは次回...）

:::note warn
実は、例で紹介した ```cancel event``` の ```event``` は引数ではなく、この２つを合わせてひとつのエフェクトです。（エラーメッセージからも分かると思います）
ただ、引数のイメージをより簡単に持っていただくために、このような説明をしました。誤解を招くような表現となってしまい申し訳ございません。
:::
## 補足：作業するうえで便利なコマンド
先ほどまでは、変更したスクリプトを Skript に読み込ませるために、いちいちサーバーを再起動していました。しかし毎回そんなことをするのは時間がかかるしヤダ！という方もいると思います。
そこで、便利なコマンドを紹介しましょう！
```
/sk reload scripts
```
このコマンドは、**「Skript のすべてのスクリプトを再読み込みする」** コマンドです。短いので打つのもそれほど苦になりません。この先もっと構文が複雑になってきたとき、おそらく頻繁に動作確認をしたくなると思います。このコマンドを使えば変更をすぐに反映できるので、今後の作業ではぜひこのコマンドを使ってみてください！
ちなみに、再読み込みに成功すると

![Screenshot 2024-05-26 130318.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/3a4b20c6-781c-2889-8d72-75f1256f9257.png)

このように表示されます。（カッコ内は再読み込みにかかった時間）
失敗すると

![Screenshot 2024-05-26 130547.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3663399/39732bd6-c831-1e92-51dd-f10581d36061.png)

このようになり、エラーが起きた行とスクリプト、そしてエラーの種類と数を教えてくれます。（コンソールから実行したときと同じです）
上の例では、```on join:``` のスペルが ```on joi:``` になっていることによってエラーが発生したということが分かりますね！

:::note
```scripts``` の部分を ```\study\``` に変更すると「study」フォルダ内のすべてのスクリプトを、更にその後にファイル名を記述することによって該当ファイルのみを再読み込みするようになります。
例えば、「study」フォルダの ```Part1.sk``` ファイルのみを再読み込みする場合には
```
/sk reload \study\Part1.sk
```
と記述します。
ただし、スクリプトの読み込みはすぐ終わるので、よほどのことがない限りは補足で紹介したコマンドを使用するのがよいでしょう。

なお、フォルダに入っていないファイル（「scripts」直下のファイル）はフォルダ名を記述する必要はありません。つまり
```
/sk reload <ファイル名>
```
で読み込めます。
:::
今回は以上になります！うまくまとめるのが難しかったため、少々分かりづらい部分もあると思います...。


【前回】

https://qiita.com/Logtain/items/fa984e97c7e6cc38962c