提供: Minecraft Modding Wiki
移動先: 案内検索
(例外メッセージについて修正)
(解説を見やすく編集)
1行目: 1行目:
 +
[[ComputerCraft_API|ComputerCraft API]] >
 
{{Stb}}
 
{{Stb}}
 
{{前提MOD|reqmod="Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"}}
 
{{前提MOD|reqmod="Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"}}
  
== イベントの追加 ==
+
== 周辺機器メソッドの追加 ==
ComputerやTurtleからperipheral.call関数でメソッドを呼び出せる周辺機器ブロックを追加する。
+
Computerからperipheral.call()でメソッドを呼び出せる周辺機器ブロックを追加します。
 +
 
 +
*IPeripheral.getMethodNames()とIPeripheral.callMethod()の実装
  
 
=== ソースコード ===
 
=== ソースコード ===
「[[ComputerCraft_API/周辺機器の追加|周辺機器の追加]]」のソースコードを元にして、変更部分のみを解説する。
+
「[[ComputerCraft_API/周辺機器の追加|周辺機器の追加]]」のソースコードを元にして、変更部分のみを解説します。
  
 
*TileSamplePeripheral.java
 
*TileSamplePeripheral.java
27行目: 30行目:
 
@Override
 
@Override
 
public String[] getMethodNames() {
 
public String[] getMethodNames() {
return new String[] {"fn1","fn2"};
+
return new String[] {"fn1", "fn2"};
 
}
 
}
  
35行目: 38行目:
 
InterruptedException {
 
InterruptedException {
 
switch(method) {
 
switch(method) {
 
 
case 0:  // fn1
 
case 0:  // fn1
 
return new Object[] {"fn1 called!"};
 
return new Object[] {"fn1 called!"};
75行目: 77行目:
 
=== 解説 ===
 
=== 解説 ===
 
==== TileSamplePeripheral.java ====
 
==== TileSamplePeripheral.java ====
 +
周辺機器のメソッドの名前を返すgetMethodNames()と、呼び出されたメソッドを実際に処理するcallMethod()を実装します。
  
まず、接続されたComputerやTurtleへ呼出し可能なメソッドの名前を渡すためにIPeripheral.getMethodNames()を実装する。
+
*getMethodNames()
 +
接続されたComputerから呼出し可能なメソッドの名前をString型の配列として返します。
 
<source lang = "java">
 
<source lang = "java">
 
@Override
 
@Override
 
public String[] getMethodNames() {
 
public String[] getMethodNames() {
return new String[] {"fn1","fn2"};
+
return new String[] {"fn1", "fn2"};
 
}
 
}
 
</source>
 
</source>
↑呼出し可能なメソッド名をString型配列として返す。この戻り値はゲーム中、常に同じ内容を返すようにする。
+
この配列内でのメソッド名の順番は、callMethod()で重要な意味を持ちます。また、この戻り値は常に同じ内容を返すようにします。<br>
 +
今回は'''fn1'''と'''fn2'''という2つのメソッドを実装します。
  
ComputerやTurtleがメソッドを呼び出した時の処理はIPeripheral.callMethod()で実装する。
+
*callMethod()
 +
Computerからメソッドが呼び出されたときの処理を実装します。
 
<source lang = "java">
 
<source lang = "java">
 
@Override
 
@Override
92行目: 98行目:
 
InterruptedException {
 
InterruptedException {
 
switch(method) {
 
switch(method) {
 
 
case 0:
 
case 0:
 
// fn1が呼び出された時の処理
 
// fn1が呼び出された時の処理
104行目: 109行目:
 
}
 
}
 
</source>
 
</source>
↑ここではどのメソッドが呼び出されたのかを示すmothodの値がポイントで、これはgetMethodNames()の戻り値のString型配列のインデックスに対応している。この例では、"fn1"が呼び出された時にはmethod = 0、"fn2"が呼び出された時にはmethod = 1となる。methodの値をswitch文で分岐させれば簡潔に各メソッドの処理を書く事が出来る。
+
引数computerにはメソッドを呼び出したComputerのIComputerAccessインスタンスが渡されます。<br>
 +
'''引数mothodは呼び出されたメソッドの番号で、これはgetMethodNames()で返した配列のインデックスに対応しています。'''<br>
 +
今回の例では、'''fn1'''が呼び出されたときにはmethod = 0、'''fn2'''が呼び出されたときにはmethod = 1となります。<br>
 +
methodの値をswitch文で分岐させれば各メソッドの処理を簡潔に書くことができます。<br>
 +
引数argumentsにはメソッド呼出し時に指定された引数がオブジェクト型配列で渡されます。<br>
 +
メソッドの戻り値はオブジェクト型の配列です。もしも返すべき値がなかった場合は空のオブジェクト型配列を返します。
  
メソッドの戻り値はオブジェクト型の配列。返すべき値が無い時は空のオブジェクト型配列を返せばよい。
+
サンプルの'''fn1'''では、単純に"fn1 called!"という文字列を返しています。
 
<source lang = "java">
 
<source lang = "java">
 
case 0:  // fn1
 
case 0:  // fn1
 
return new Object[] {"fn1 called!"};
 
return new Object[] {"fn1 called!"};
 
</source>
 
</source>
↑サンプルのfn1では、単純に"fn1 called!"という文字列を返している。
 
  
サンプルのfn2では引数の取得、例外のthrow、変数のreturnを行っている。
+
 
 +
サンプルの'''fn2'''では引数の取得、例外のthrow、変数のreturnを行っています。
 
<source lang = "java">
 
<source lang = "java">
 
case 1:  // fn2
 
case 1:  // fn2
124行目: 134行目:
 
return new Object[] {arguments[0], arguments[0].getClass().getName()};
 
return new Object[] {arguments[0], arguments[0].getClass().getName()};
 
</source>
 
</source>
↑引数なしでメソッドが呼び出されたなら例外LuaException("Expected argument")を発生、第一引数にJava側で受け取れない値が指定されていたら例外LuaException("Illegal argument")を発生させている。戻り値は指定した第一引数そのものと、そのJava側でのクラス名を返している。
+
まず、メソッドが引数なしで呼び出されたなら例外LuaException("Expected argument")を発生させ、第一引数にJava側で受け取れない値が指定されていたなら例外LuaException("Illegal argument")を発生させています。そして、戻り値として呼出し時に指定した第一引数と、その引数のJava側での型名を返しています。
 +
 
 +
==== 引数や戻り値の型 ====
 +
メソッドの引数や戻り値の型はComputerCraftによって自動的に変換されます。
  
*引数や戻り値の型
 
メソッド呼出し時の引数はオブジェクト型配列argumentsで渡される。引数や戻り値の型は自動的に変換される。<br>
 
Lua→Java、Java→Luaでの型変換は以下の通り。
 
 
{| class="wikitable"
 
{| class="wikitable"
!colspan="2"|呼出し
+
|+Lua⇔Javaでの型変換
 +
!colspan="2"|引数
 
!colspan="2"|戻り値
 
!colspan="2"|戻り値
 
|-
 
|-
164行目: 175行目:
 
|}
 
|}
  
*例外 LuaException
+
Luaのtable型はJava側ではHashMap<Object, Object>になります。キーおよび値の型もそれぞれ上表に従って変換されます。<br>
callMethod()の処理中で例外LuaExceptionをthrowすると、そこで'''処理を中止'''してComputerやTurtleの画面にエラーメッセージを表示する。ComputerCraftの周辺機器では主にメソッドの引数の不備を指摘する時に用いられているようだ。
+
Luaのtableを使った配列は1オリジンです。キー0に値を代入することは可能ですが、キー0はLuaのipairs()や#演算子の対象にはなりません。
 +
 
 +
==== 例外 LuaException ====
 +
callMethod()の処理中で例外LuaExceptionをthrowすると、そこで'''処理を中止'''してComputerやTurtleの画面にエラーメッセージを表示します。ComputerCraftの周辺機器では主にメソッドの引数の不備を指摘する時に用いられているようです。
 
<source lang = "java">
 
<source lang = "java">
 
throw new LuaException("Expected argument");
 
throw new LuaException("Expected argument");
 
</source>
 
</source>
↑サンプルのfn2で、引数が何も指定されずに呼び出された時に発生させている例外。ComputerやTurtleの画面上には、<br>
+
この例外が発生した場合、その時点でメソッドの処理は中止され、ComputerやTurtleの画面上には、<br>
 
<code style="color: red">'''lua:1: Expected argument'''</code><br>
 
<code style="color: red">'''lua:1: Expected argument'''</code><br>
のように表示される。フォーマットは、<code>プログラム名:行番号:内容</code>
+
のように表示されます。表示されるフォーマットは、'''<code>プログラム名:行番号:内容</code>''' です。<br>
 +
この例では"lua"というLuaプログラム内の1行目のperipheral.call()で呼ばれた周辺機器メソッドの処理中にLuaException("Expected argument")がthrowされたことを表します。
 +
 
 +
==== Minecraftとの競合 ====
 +
''※今回のサンプルでは問題ありません''
  
*Minecraftとの競合
+
callMethod()はComputerCraftのLuaスレッドから呼び出されているため、callMethod()の処理中にMinecraftのスレッドからアクセスされる可能性のあるフィールドへアクセスすると、競合が発生する可能性があります。従って、そのような処理では適宜synchronizedなどで排他制御する必要があります。
今回の例では問題ないが、callMethod()はComputerCraftのLuaスレッドから呼び出されているため、callMethod()からの一連の処理中において、Minecraftスレッドから変更され得るフィールドへのアクセスは競合が発生する可能性がある。従ってそのような処理では適宜synchronized等で排他制御する必要がある。
 

2014年11月14日 (金) 01:01時点における版

ComputerCraft API >

この記事は執筆中です。加筆してくださる人を募集しています。

この記事は"Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"を前提MODとしています。

周辺機器メソッドの追加

Computerからperipheral.call()でメソッドを呼び出せる周辺機器ブロックを追加します。

  • IPeripheral.getMethodNames()とIPeripheral.callMethod()の実装

ソースコード

周辺機器の追加」のソースコードを元にして、変更部分のみを解説します。

  • 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

周辺機器のメソッドの名前を返すgetMethodNames()と、呼び出されたメソッドを実際に処理するcallMethod()を実装します。

  • getMethodNames()

接続されたComputerから呼出し可能なメソッドの名前をString型の配列として返します。

@Override
public String[] getMethodNames() {
	return new String[] {"fn1", "fn2"};
}

この配列内でのメソッド名の順番は、callMethod()で重要な意味を持ちます。また、この戻り値は常に同じ内容を返すようにします。
今回はfn1fn2という2つのメソッドを実装します。

  • callMethod()

Computerからメソッドが呼び出されたときの処理を実装します。

@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;
}

引数computerにはメソッドを呼び出したComputerのIComputerAccessインスタンスが渡されます。
引数mothodは呼び出されたメソッドの番号で、これはgetMethodNames()で返した配列のインデックスに対応しています。
今回の例では、fn1が呼び出されたときにはmethod = 0、fn2が呼び出されたときにはmethod = 1となります。
methodの値をswitch文で分岐させれば各メソッドの処理を簡潔に書くことができます。
引数argumentsにはメソッド呼出し時に指定された引数がオブジェクト型配列で渡されます。
メソッドの戻り値はオブジェクト型の配列です。もしも返すべき値がなかった場合は空のオブジェクト型配列を返します。

サンプルのfn1では、単純に"fn1 called!"という文字列を返しています。

case 0:  // fn1
	return new Object[] {"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側での型名を返しています。

引数や戻り値の型

メソッドの引数や戻り値の型はComputerCraftによって自動的に変換されます。

Lua⇔Javaでの型変換
引数 戻り値
Lua Java Java Lua
boolean Boolean Boolean boolean
number Double Integer
Float
Double
number
string String String string
table HashMap HashMap table
その他 null その他 nil

Luaのtable型はJava側ではHashMap<Object, Object>になります。キーおよび値の型もそれぞれ上表に従って変換されます。
Luaのtableを使った配列は1オリジンです。キー0に値を代入することは可能ですが、キー0はLuaのipairs()や#演算子の対象にはなりません。

例外 LuaException

callMethod()の処理中で例外LuaExceptionをthrowすると、そこで処理を中止してComputerやTurtleの画面にエラーメッセージを表示します。ComputerCraftの周辺機器では主にメソッドの引数の不備を指摘する時に用いられているようです。

throw new LuaException("Expected argument");

この例外が発生した場合、その時点でメソッドの処理は中止され、ComputerやTurtleの画面上には、
lua:1: Expected argument
のように表示されます。表示されるフォーマットは、プログラム名:行番号:内容 です。
この例では"lua"というLuaプログラム内の1行目のperipheral.call()で呼ばれた周辺機器メソッドの処理中にLuaException("Expected argument")がthrowされたことを表します。

Minecraftとの競合

※今回のサンプルでは問題ありません

callMethod()はComputerCraftのLuaスレッドから呼び出されているため、callMethod()の処理中にMinecraftのスレッドからアクセスされる可能性のあるフィールドへアクセスすると、競合が発生する可能性があります。従って、そのような処理では適宜synchronizedなどで排他制御する必要があります。