ターミナルでGodotを使おう。



GUIアプリケーションというものは、Headlessモードを搭載しているモノが多くあります。

例えば、Google Chrome の Headlessモード。
ちょっとした自動化、CI/CD、テスト、デバッグなんかを実行するのに便利だし、
グラフィック処理がない分高速です。
ディスプレイのないサーバーでも動作させることができます。



OSSなゲームエンジン **Godot** もいくつかの操作をコマンドライン上で実行することができます。
特に、オンライン用のサーバーサイドを書くときに結構便利そうなので、使い方をメモっておきます。



> [コマンドラインチュートリアル — Godot Engine latest ドキュメント](https://docs.godotengine.org/ja/latest/getting_started/editor/command_line_tutorial.html)

↑に色々書いてあります！



# Godot をコマンドとして実行できるようにする

※macOS + zsh です。別環境の人は適宜読み替えてください。


Macの`/Applications`フォルダにGodotをインストールした人は、
`Godot.app` を 右クリックして、「コンテンツを表示」とやるとこんな感じになってるはず。
![スクリーンショット 2020-02-19 21.57.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192562/5ba0ad6c-92bd-8ebe-0a56-cf919e18e861.png)


`/Applications/Godot.app/Contents/MacOS/Godot`
これがGodotの実行ファイルパスです。
Finderからダブルクリックしてやると、Godotエディタが起動します。

これをターミナルのコマンドとして実行できるように、`.zshrc`に`alias`を定義してやります。

```zsh:.zshrc
# Godot bin
alias godot="/Applications/Godot.app/Contents/MacOS/Godot"
```

これで準備OKです！




# `-e` ターミナルからGodot Editorを起動する。

`-e` = `--editor`

ターミナルからGodotを始めたい人も結構いるはず。
Godotのプロジェクトファイル(`project.godot`)があるディレクトリで、
`godot -e`を実行すると、そのディレクトリ内のプロジェクトを開きます。

ただし、macの場合は、`open`コマンドで開いた方が、バックグラウンド実行されて
ターミナルを占領されないのでそっちのがいいかもしれない。

```zsh
cd path/to/project
godot -e

# macならこっちのがいいかも
open project.godot 
```



# `-s` GDScriptを実行

`-s` = `--script`

```zsh
godot -s --headless file.gd
```
上のコマンドを実行すると、
以下の2つのどちらかのClassを継承した`.gd`ファイルを、Headlessで実行できます。

- `MainLoop`
- `SceneTree`

`MainLoop` は `SceneTree` のスーパークラスなのですが、
全てのメソッドが仮想メソッドで、実処理が実装されていなくて使いづらいので、
Headlessで使う場合は`SceneTree`の方がおすすめだと思います。

Hello Worldを書くとこんな感じです。

```gd:hello.gd
extends SceneTree

func _init():
	print("Hello, world!")
	quit()
```

スクリプトを実行する。

```zsh
> godot -s hello.gd
# Hello, world!
```

ちょっとした計算機にするとか、pythonっぽい使い方ができそうです。

ちなみに、本番環境でスクリプトモード実行するのはやめときましょう。
ヘッドレスサーバー向けにバイナリをビルドできるので、そっちの方が高速です。

そのときは、`--export`フラグを付けます

```zsh
# プロジェクトフォルダ内で実行する
# godot --export <target> <out_path>
godot --export "Linux/X11" /var/builds/project
```


# `-d` シーンをデバッグ実行する

`-d` = `--debug`

Godotエディタの右上についてるボタンと同じ挙動です。
![スクリーンショット 2020-02-19 22.32.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192562/f978da9d-3302-b123-67f1-72fedd76adc4.png)
メインシーンを実行したり、個別シーンを実行したりできます。

```zsh
godot -d
# .tscnファイルを指定して実行
godot -d SubScene.tscn
# headless モードで実行
godot -d --headless SubScene.tscn
```

個人的に、ターミナルからGodotを使う一番の動機となります。

Godot Editorからのデバッグ実行では**1つのシーンしか同時に起動できません**
これは、マルチプレイゲームのServer/Clientシーンを同時に起動して
デバッグしたい場合に不便です。

しかし、ターミナルのタブを複数開いてCLIから実行すれば、
**同時に複数のシーンを実行する**ことができます。


# おまけ : UDPサーバーデモ


> [Godot 3 Tutorial– Networking](https://www.gamefromscratch.com/page/Godot-3-Tutorial-Networking.aspx)


`godot -s` のスクリプト実行で、簡単なUDPサーバー/クライアントを
実行してみます。

```gd:Server.gd
extends SceneTree

func _init():
	var done = false
	
	# host=127.0.0.1, port=4242 でUDP通信を待受
	var socket = PacketPeerUDP.new()
	if(socket.listen(4242, "127.0.0.1") != OK):
		print("server error")
		done = true
	else:
		print("listening on port 4242 on localhost")
		
	# utf8 で "quit" パケットが来たら終了
	while (!done):
		if(socket.get_available_packet_count() > 0):
			var data = socket.get_packet().get_string_from_utf8()
			if (data == "quit"):
				done = true
			else:
				print("recieve data is {%s}" %data)
	
	socket.close()
	print("Exit App")
	self.quit()
```

```gd:Client.gd
extends SceneTree

func _init():
	# Serverに接続して、"Hello"を送る
	var socket = PacketPeerUDP.new()
	socket.set_dest_address("127.0.0.1", 4242)
	socket.put_packet("Hello".to_utf8())
	
	quit()
```

スクリプト実行

```zsh
godot -s --headless Server.gd
# 別タブ
godot -s --headless Client.gd

# recieve data is {Hello}
```

ちなみに、UDPのテストはMac/Linuxであれば`nc`(netcat)コマンドでも簡単にできます。

```zsh
# nc {host} {port}
# -u : UDPモード
nc -u 127.0.0.1 4242
Hello^D
quit^D

# -l : Listen = サーバーモード
nc -lu 127.0.0.1 4242
```
Macの場合、
Ctrl + D = EOF