Minecraftとタートルと僕

PCゲームMinecraftのMOD「ComputerCraft」の情報を集めたニッチなブログです。

こちらのページは更新が滞っており、情報が古くなりつつあります。新しいCC情報サイトをはじめましたので、もしよければご参照ください。今後ともよろしくお願い申し上げます。

「百億のマインクラフトと千億のタートル」(https://hevo2.hatenablog.com/)

APIを作ろう(4)-h2peripheral API の実装を解説

はじめに

h2peripheral API 詳細 - Minecraftとタートルと僕
で挙げた「h2peripheral API」を実装したので、そのソースコードを公開し内容を簡単に説明します。

解説なんていらない、ただインストールだけしたい、ということであれば以下のようにpastebinコマンドを使うのが手軽だと思います。
APIは実装の中身を知らなくても使えることが重要ですしw

-- "h2peripheral"という名前でインストールする
> pastebin get ck6QZ2CS h2peripheral

このAPIを使いたいプログラムファイルの先頭に以下を書き込む

os.loadAPI("h2peripheral")

これ何の役に立つの?

いまいちピンとこない人の為に使い方の説明。
CCの仕様により、プログラムファイルをstartupという名前にすればコンピュータ設置と同時にそのプログラムを実行できます。
しかし、設置した瞬間には周辺機器は装着されていないため、そのプログラム内で周辺機器を使おうとしてperipheral.wrap()しても失敗します。
だから通常は、コンピュータ設置→周辺機器装着→周辺機器を使うプログラムを手動で実行、という段階を踏まなくてはなりません。

しかし、今回のh2peripheral.waitForDetect()関数を使うことで、周辺機器を装着するまでその場所でプログラムを一時停止してくれるため、
コンピュータ設置→(startupでプログラム自動実行&一時停止)→周辺機器装着→(プログラムを継続実行)、という手順が可能になり、プログラムを手動で実行する手間がはぶけます。
コンピュータやタートルを設置したら、必要な周辺機器をつけるだけでいきなりプログラムが動くのでかなり便利です。
しかも、機器種別名で自動認識してくれるため周辺機器をつける方向を問いません。

ソース解説

念のための前提APIを確認

  • L8: 前提APIである「Peripheral API」を強制的に読み込み。*1
  • L10: 前提APIである「os」「peripheral」「rs(redstone)」がすでに使えることを確認。

たいていの場合は、これらがなくても大丈夫だとは思いますが、念のための記述です。

文字列、キーワードの定義

機器種別名と方向という文字列を使います。

  • L10-20: プログラム内で使うことができる機器種別名を定義。以下では、これをホワイトリストとして使っています。
  • L25: コンピュータの方向を表す文字列は、rs.getSides()関数を使って(動的に)入手しています。

3つの関数を定義

wrapByName() 、L22-45
  • L23: ホワイトリストを見て、おかしな引数の入力をはじく。
  • L25: この関数の返し値を一時的に保存する変数。「f_tbl」は「functions table」の略。
  • L26: rs.getSides()関数で方向リストを入手し、順番に検索する
  • L27: peripheral.getType(side)で、その方向にある周辺機器のタイプ名を入手。
  • L30、L34、L38: ゲットした機器タイプ名と、引数で指定した機器種別名を付き合わせて正しい機器を特定。
    • L34: Advanced Monitor(金色モニタ) は、タイプ名として"monitor"としか返ってこないので、「is.Color()」関数(色が使えるか)を使うことで特定。
    • L38: Wireless Modem(無線モデム)は、タイプ名として"modem"としか返ってこないので、「isWireless()」関数(ワイヤレスかどうか)を使うことで特定。
  • L32、L36、L40: 返す値「f_tbl」の中に方向情報を追加する。
wrap() 、L47-56

「wrapByNmae(機器種別名)」関数と「peripheral.wrap(方向)」関数を、引数が機器種別か方向かで切り替える関数です。

  • L49: 機器種別名ホワイトリストに引っかかったら、wrapByName()を実行。そうでなければ、peripheral.wrap()
  • L53: peripheral.wrap()は指定方向に周辺機器がなかったらnilを返すことに注意。nilでなければ(周辺機器がみつかったら)、例のごとくside値を追加。
waitForDetect() 、L58-66

「wrap()」関数と「os.pullEvent("peripheral")」関数を使って、周辺機器が見つからなければ装着されるまで待つという動作を実現しました。

  • L62: 「os.pullEvent("peripheral")」は、何か周辺機器が装着されたときに発生する"peripheral"イベントを検出するまで待つ関数です。
    • つまり、まずwrap()で希望する周辺機器がないか探し、なければ装着されるまで待つ、装着されたらそれが希望するものか再度検索という動作を繰り返します。
    • "peripheral"イベントは装着した方向まで返してくれるので効率を考えるとその方向だけ調査すればよいのですが、プログラムのわかりやすさと短さを考えてこのような手抜きをしています。

その他

コメントアウトしてあるL70-77はただのテスト用コードですが、念のため残しています。

ソースコード

http://pastebin.com/ck6QZ2CS

*1:なお、「os」「rs」は「/rom/apis/」にないため、システム組み込みであり個別プログラムではないと思われます(推測)。