この記事は執筆中です。加筆してくださる人を募集しています。 |
この記事は"Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"を前提MODとしています。 |
イベントの追加
ComputerやTurtleからperipheral.call関数でメソッドを呼び出せる周辺機器ブロックを追加する。
ソースコード
「周辺機器の追加」のソースコードを元にして、変更部分のみを解説する。
- TileSamplePeripheral.java
package mods.sample.peripheral; import net.minecraft.tileentity.TileEntity; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.peripheral.IComputerAccess; import dan200.computercraft.api.peripheral.IPeripheral; public class TileSamplePeripheral extends TileEntity implements IPeripheral { @Override public String getType() { return "sample"; } @Override public String[] getMethodNames() { return new String[] {"fn1","fn2"}; } @Override public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException { switch(method) { case 0: // fn1 return new Object[] {"fn1 called!"}; case 1: // fn2 if ( arguments.length < 1 ) { throw new LuaException("Expected argument"); } if ( arguments[0] == null ) { throw new LuaException("Illegal argument"); } return new Object[] {arguments[0], arguments[0].getClass().getName()}; } return null; } @Override public void attach(IComputerAccess computer) { } @Override public void detach(IComputerAccess computer) { } @Override public boolean equals(IPeripheral other) { if ((other != null) && (other instanceof TileSamplePeripheral)) { return other == this; } return false; } }
解説
TileSamplePeripheral.java
まず、接続されたComputerやTurtleへ呼出し可能なメソッドの名前を渡すためにIPeripheral.getMethodNames()を実装する。
@Override public String[] getMethodNames() { return new String[] {"fn1","fn2"}; }
↑呼出し可能なメソッド名をString型配列として返す。この戻り値はゲーム中、常に同じ内容を返すようにする。
ComputerやTurtleがメソッドを呼び出した時の処理はIPeripheral.callMethod()で実装する。
@Override public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException { switch(method) { case 0: // fn1が呼び出された時の処理 case 1: // fn2が呼び出された時の処理 } return null; }
↑ここではどのメソッドが呼び出されたのかを示すmothodの値がポイントで、これはgetMethodNames()の戻り値のString型配列のインデックスに対応している。この例では、"fn1"が呼び出された時にはmethod = 0、"fn2"が呼び出された時にはmethod = 1となる。methodの値をswitch文で分岐させれば簡潔に各メソッドの処理を書く事が出来る。
メソッドの戻り値はオブジェクト型の配列。返すべき値が無い時は空のオブジェクト型配列を返せばよい。
case 0: // fn1 return new Object[] {"fn1 called!"};
↑サンプルのfn1では、単純に"fn1 called!"という文字列を返している。
サンプルのfn2では引数の取得、例外のthrow、変数のreturnを行っている。
case 1: // fn2 if ( arguments.length < 1 ) { throw new LuaException("Expected argument"); } if ( arguments[0] == null ) { throw new LuaException("Illegal argument"); } return new Object[] {arguments[0], arguments[0].getClass().getName()};
↑引数なしでメソッドが呼び出されたなら例外LuaException("Expected argument")を発生、第一引数にJava側で受け取れない値が指定されていたら例外LuaException("Illegal argument")を発生させている。戻り値は指定した第一引数そのものと、そのJava側でのクラス名を返している。
- 引数や戻り値の型
メソッド呼出し時の引数はオブジェクト型配列argumentsで渡される。引数や戻り値の型は自動的に変換される。
Lua→Java、Java→Luaでの型変換は以下の通り。
呼出し | 戻り値 | ||
---|---|---|---|
Lua | Java | Java | Lua |
boolean | Boolean | Boolean | boolean |
number | Double | Integer Float Double |
number |
string | String | String | string |
table | HashMap | HashMap | table |
その他 | null | その他 | nil |
- 例外 LuaException
callMethod()の処理中で例外LuaExceptionをthrowすると、そこで処理を中止してComputerやTurtleの画面にエラーメッセージを表示する。ComputerCraftの周辺機器では主にメソッドの引数の不備を指摘する時に用いられているようだ。
throw new LuaException("Expected argument");
↑サンプルのfn2で、引数が何も指定されずに呼び出された時に発生させている例外。ComputerやTurtleの画面上には、
lua:1: Expected argument
のように表示される。lua:の後ろの数字はLuaスクリプトの行番号。
- Minecraftとの競合
今回の例では問題ないが、callMethod()はComputerCraftのLuaスレッドから呼び出されているため、callMethod()からの一連の処理中において、Minecraftスレッドから変更され得るフィールドへのアクセスは競合が発生する可能性がある。従ってそのような処理では適宜synchronized等で排他制御する必要がある。