LiteXLoader用のプラグインを自作する

# はじめに
前回はBDSサーバーでプラグインを導入するための準備としてLiteXLoader等を導入しました
まだ見てない方はこちらから
[Minecraft統合版公式サーバーでプラグインを使う方法【LiteXLoader】](https://qiita.com/nerrog/items/1e54ea7d74f9651ef97b)

今回はLiteXloader(以下LXL)用のプラグインを自作してみよう！っていう記事です
言語はJavascriptを使います(~~Luaは知らねぇ~~)
エディタは何でも良いですが、自分はVisual Studio Codeを使ってます
VSCode用のプラグインでLXLDevHelperというものあるみたいですが言語が中国語でプラグインなので翻訳しようがないので使ってません。
多すぎるので一部のみの紹介となります。公式ドキュメントに全ての情報が乗っているので気になる人は是非

# 対象
* Javascript触ったことがある人(プログラミングにある程度慣れている人)向け

# 文字を表示してみよう

1.適当になディテクトリにjavaScriptファイルを作りましょう
2.そのファイルに`log("Hello! LiteXLoader Plugin!")`を入力してBDSのPluginsディレクトリにコピーして起動
3.BDS起動時に`Hello! LiteXLoader Plugin!`と表示されるはずです！

おまけ：色付きの文字を表示する

`colorLog(red,"Hello!")`
と入力すると赤い文字でコンソールに出力されます！
他にもblueやgreen等が指定できます

# 自作コマンドを登録してみよう
コマンドの登録には`nc.regPlayerCmd()`を使います。

```
mc.regPlayerCmd("hello","say hello!",function(pl,args){
    pl.tell("Hello!");
```

## 解説
第1パラメーター(helloの部分)は実際に入力するコマンド(スラッシュは除く)

第2パラメーター(say hello!)は実際にプレイヤーがコマンドを打ったときに表示されるコマンドの説明(日本語でもOK)

第3パラメーター(function...)は実際に実行するコールバック関数
関数にはコマンドを実行したプレイヤーオブジェクトとコマンドの引数が格納された配列を渡すことができます

第4パラメーター(オプション)として実行できるパーミッションを指定することができます

* 0(デフォルト)→オペレーター以外でも使用することができる
* 1→オペレーターでないと実行することができない

### おまけ コンソールコマンドを登録する

```
mc.regConsoleCmd("hello","say hello!",function(args){
    log("Hello!");
```

regPlayerCmd関数と大体同じですが、コンソール用なのでPlayerオブジェクトがありません

### 例：オウム返しするコマンドを作ってみる

```
mc.regConsoleCmd("oumu","引数の言葉をオウム返しします",oncmd_oumu)

function oncmd_oumu(pl,args){
    if(args.length == 1){
        pl.tell(args[0])
    }else{
        pl.tell("引数を指定してください")
    }
}
```

# プレイヤーに関する情報を扱う

## プレイヤーオブジェクトについて
LXLにはプレイヤーオブジェクトというものがあり、いろいろなもので取得することができます
プレイヤーオブジェクトを使って以下のようなことができます

* プレイヤーの名前の取得
* 座標の取得
* xuidの取得
* パーミッションの取得
* ゲームモードの取得
* 体力の取得
* スニーク状態の取得
* などなど・・・

## プレイヤーオブジェクトを取得する方法

コマンドのコールバック関数の引数やイベントリスナーのコールバック関数の引数などから取得することが多いと思いますが、それ以外からも取得できます

### プレイヤー名やXUIDから取得する

`var Player = mc.getPlayer("プレイヤーの名前やXUID")`

### 全てのオンラインプレイヤー一覧

`var Players = mc.getOnlinePlayers()`

この関数の返り値は全てのプレイヤーのプレイヤーオブジェクトが入った配列なので1人ずつ何かしたいときは配列を1つずつ処理していく必要があります

```
    for (const player of players) {
        player.tell("Hey!")
    }
```

## プレイヤーオブジェクトの機能

各種情報を取得する方法は公式ドキュメントの表見たほうがいいと思います
[公式ドキュメント](https://lxl.litetitle.com/#/zh_CN/Development/GameAPI/Player?id=%e7%8e%a9%e5%ae%b6%e5%af%b9%e8%b1%a1-%e5%b1%9e%e6%80%a7)

### プレイヤーがオペレーターかどうか
オペレーター以外は処理を変えたい場面とかに使えます

```
if(Player.isOP()){
    log("OP!")
}else{
    log("not OP!")
}
```

### プレイヤーをキック

`player.kick()`

これでキックできますが、
`player.kick("サーバーからキックされました")`と引数に文字列を渡すとその文字列が切断されたクライアントに表示されます
また、`kick()`と`disconnect()`は同じらしいです

### 特定のプレイヤーにメッセージを送信する

`player.tell("hello!")`

前の解説でも使っているやつです。
第2引数にメッセージのタイプを指定できるみたいです
`tell()`でも`sendtext()`でも同じっぽい

### 全プレイヤーにメッセージを送信する
アナウンスとかに使えそう

`mc.broadcast("ﾊﾛｰ!")`

こちらもtellと同様、第2引数にタイプを設定できるみたいです

### プレイヤーをTPさせる
``player.teleport(100,200,-300)`

指定した座標にプレイヤーがテレポートします

### プレイヤーをキルする

`player.kill()`

キルするだけ

## プレイヤーのデバイス情報を取得する

`var device = player.getDevice()`

この返り値の`Device`オブジェクトにはこんな使い方ができます

```
device.ip   //IPアドレス
device.avgPing   //Ping(ms)
device.avgPacketLoss   //パケットロス(%)
device.os   //OS(iOSやAndroidやWindows10など)
device.clientId   //識別ID(?)
```

# ゲームイベントの取得
LXLにはイベントリスナーというものを使ってゲームに関するあらゆるイベントをキャッチして指定の関数を実行することができます。

## リスナーの使い方

`mc.listen("イベント名",callback)`

イベント名はこれから紹介するイベントを文字列として指定します
callbackは呼び出される関数です。
イベントによっては引数が取得できるものがあります。

## プレイヤーに関するイベント

### "onPreJoin"
プレイヤーが参加するときに呼び出されます
引数はプレイヤーオブジェクトを渡すことができます

### "onJoin"
`onPreJoin`と違うところはこのイベントはクライアントの読み込みが終わってからイベントが呼び出されます
引数はプレイヤーオブジェクトを渡すことができます

### "onLeft"
プレイヤーが退出するときに呼び出されます
引数はプレイヤーオブジェクトを渡すことができます

### "onRespawn"
プレイヤーがリスポーンするときに呼び出されます
引数はプレイヤーオブジェクトを渡すことができます

### "onPlayerDie"
プレイヤーが死亡したときに呼び出されます
引数はプレイヤーオブジェクトを渡すことができます

### "onPlayerCmd"
プレイヤーがコマンドを実行したときに呼び出されます
引数はプレイヤーオブジェクトと実行したコマンドの文字列を渡すことができます

### "onChat"
プレイヤーがチャットを送信したときに呼び出されます
引数はプレイヤーオブジェクトと送信したチャットの文字列を渡すことができます

## エンティティに関するイベント

### "onMobDie"
Mobが殺害されたときに呼び出されます
引数には死んだエンティティオブジェクトと死んだ原因となったエンティティオブジェクトを渡すことができます。

プレイヤーが死亡すると`onPlayerDie`イベントに加えこのイベントも実行されるので注意が必要

### "onExplode"
エンティティによって爆発が起きた場合に実行されます
引数には爆発の原因となったエンティティオブジェクトと爆発した座標を渡すことができます。

## その他のイベント

### "onServerStarted"
サーバーの起動が完了したときに実行されます

### "onConsoleCmd"
サーバーコンソールでコマンドが実行されたときに呼びだされます。
引数には実行されたコマンドの文字列を渡すことができます。

# フォームを使ったGUIの作り方

Hive鯖とかによくあるアレです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701723/1b0a267a-cc80-9909-559c-acd5a23b35cf.png)

## 適当なフォームを送信してみる

```
player.sendModalForm("タイトル","説明","ボタン1","ボタン2",callback)
```

このようにPlayerオブジェクトに対応したクライアントにフォームが送信されます。

callback用の関数では引数として`(player, result)`と受け取ることができ、
resultには整数型としてOKが1、キャンセルが0、フォームをキャンセル(多分右上の☓を押したとき？)はNullが入っています

## ボタンの数を増やしたり画像を表示させたりする方法

```
player.sendSimpleForm("タイトル","説明",["ボタン1", "ボタン2", "ボタン3"],["image1.png", "image2.png", "image3.png"],callback)
```

ボタンも文字列が入った配列と、表示させる画像のパスが入った配列を引数に渡してあげることでできます。
(多分BDSルートディレクトリからの相対パス指定だと思います)

callback用の関数では引数として`(player, id)`と受け取ることができ、
idは整数型でクリックしたボタンの番号が入っています。
0から始まり、キャンセルはnullです。

### クリックしたボタンを取得するサンプル

```
player.sendSimpleForm("タイトル","説明",["ボタン1", "ボタン2", "ボタン3"],["image1.png", "image2.png", "image3.png"],form_callback)

function form_callback(player, id){
    if (id == 0){
        player.tell("ボタン1")
    }else if (id == 1){
        player.tell("ボタン2")
    }else if (id == 2){
        player.tell("ボタン3")
    }else{
        player.tell("キャンセル")
    }
}

```

## ドロップダウンリスト等の項目を使った高度なフォームの作り方

自分もあまり使う機会なくてまだ試せてません・・・

[ドキュメント](https://lxl.litetitle.com/#/zh_CN/Development/GuiAPI/FormBuilder)によるといろいろ指定できるみたいです。


# システム系

## ファイルに書き込んだり読み込む

### ファイルの読み込み
```
file.readFrom(path)
```
BDSルートディレクトリから相対パスで指定します。
読み取った文字列が返り値として返されます。

### 書き込み
```
file.writeTo(path,text)
```
pathは相対パスで指定して、textは書き込む内容を文字列型で指定します

*書き込み先のファイルが存在しない場合には自動的に生成され、存在する場合は上書きされます*

### フォルダを作成する

```
file.createDir(dir)
```

### HTTP GETリクエストの送信

```
network.httpGet(url,callback)
```
urlにはGETするアドレスを文字列型で指定します。
callbackには`(status, result)`を取得でき、statusはHTTPステータスコード、resultはGETした結果が入っています。

# おわりに

使いそうな関数はここで紹介しましたが、他にもNBTデータを操作したりすることもできるようです。

LXLプラグインはGithubではあまり公開されておらず、中国の掲示板の[MineBBS](https://www.minebbs.com/)というところに殆どのプラグインが公開されているようです(DLには謎の金塊？が必要らしくあまり良くわかってない)

最近だとLiteLoaderBDSもLXLもGithubの更新頻度が高く日々新機能が追加されていっています。
なので公式ドキュメントも覗いてみてください。