提供: Minecraft Modding Wiki
移動先: 案内検索

警告: ログインしていません。編集を行うと、あなたの IP アドレスが公開されます。ログインまたはアカウントを作成すれば、あなたの編集はその利用者名とともに表示されるほか、その他の利点もあります。

この編集を取り消せます。 下記の差分を確認して、本当に取り消していいか検証してください。よろしければ変更を保存して取り消しを完了してください。
最新版 編集中の文章
1行目: 1行目:
[[ComputerCraft_API|ComputerCraft API]] >
+
{{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にイベントを発生させる周辺機器ブロックを追加します。
+
クリックされたとき、接続されたComputerやTurtleに対してイベントを発生させる周辺機器ブロックを追加する。
 
 
*IComputerAccessインスタンスの管理
 
*IComputerAccess.queueEvent()によるイベントの発生
 
  
 
=== ソースコード ===
 
=== ソースコード ===
「[[ComputerCraft_API/1.65/周辺機器の追加|MC1.7 周辺機器の追加]]」のソースコードを元にして、変更部分のみを解説します。
+
「[[ComputerCraft_API/周辺機器の追加|周辺機器の追加]]」のソースコードを元にして、変更部分のみを解説する。
  
 
*BlockSamplePeripheral.java
 
*BlockSamplePeripheral.java
17行目: 14行目:
 
import net.minecraft.block.BlockContainer;
 
import net.minecraft.block.BlockContainer;
 
import net.minecraft.block.material.Material;
 
import net.minecraft.block.material.Material;
 +
import net.minecraft.creativetab.CreativeTabs;
 
import net.minecraft.entity.player.EntityPlayer;
 
import net.minecraft.entity.player.EntityPlayer;
 
import net.minecraft.tileentity.TileEntity;
 
import net.minecraft.tileentity.TileEntity;
24行目: 22行目:
  
 
public BlockSamplePeripheral() {
 
public BlockSamplePeripheral() {
super(Material.ground);
+
super(Material.rock);
 +
setBlockName("blockSamplePeripheral");
 +
setCreativeTab(CreativeTabs.tabBlock);
 
}
 
}
  
@Override
 
 
public boolean onBlockActivated(World world, int x, int y, int z,
 
public boolean onBlockActivated(World world, int x, int y, int z,
 
EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
 
EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
49行目: 48行目:
 
package mods.sample.peripheral;
 
package mods.sample.peripheral;
  
import java.util.HashMap;
 
 
import java.util.HashSet;
 
import java.util.HashSet;
import java.util.Map;
 
 
import java.util.Set;
 
import java.util.Set;
  
87行目: 84行目:
 
@Override
 
@Override
 
public void attach(IComputerAccess computer) {
 
public void attach(IComputerAccess computer) {
synchronized (this) {
+
synchronized (this.m_computers) {
m_computers.add(computer);
+
this.m_computers.add(computer);
 
}
 
}
 
}
 
}
94行目: 91行目:
 
@Override
 
@Override
 
public void detach(IComputerAccess computer) {
 
public void detach(IComputerAccess computer) {
synchronized (this) {
+
synchronized (this.m_computers) {
m_computers.remove(computer);
+
this.m_computers.remove(computer);
 
}
 
}
 
}
 
}
108行目: 105行目:
  
 
public void click() {
 
public void click() {
Map<String, Integer> pos = new HashMap<String, Integer>();
+
synchronized (this.m_computers) {
pos.put("x", this.xCoord);
+
for (IComputerAccess computer : this.m_computers) {
pos.put("y", this.yCoord);
+
computer.queueEvent("sample_click", new Object[] {computer.getAttachmentName()} );
pos.put("z", this.zCoord);
 
 
 
synchronized(this) {
 
for (IComputerAccess computer : m_computers) {
 
computer.queueEvent("sample_click",
 
new Object[] {computer.getAttachmentName(), pos} );
 
 
}
 
}
 
}
 
}
126行目: 117行目:
 
=== 解説 ===
 
=== 解説 ===
 
==== BlockSamplePeripheral.java ====
 
==== BlockSamplePeripheral.java ====
周辺機器ブロックが右クリックされたときの処理を追加します。
+
周辺機器のブロックがクリックされた時の処理を追加する。
 
<source lang = "java">
 
<source lang = "java">
@Override
 
 
public boolean onBlockActivated(World world, int x, int y, int z,
 
public boolean onBlockActivated(World world, int x, int y, int z,
 
EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
 
EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) {
138行目: 128行目:
 
}
 
}
 
</source>
 
</source>
ブロックが右クリックされたら周辺機器のTileEntityを取得してTileSamplePeripheral.click()を呼び出しています。
+
ブロックがクリックされたらTileEntity(周辺機器)を取得してclick()を呼び出す。
  
 
==== TileSamplePeripheral.java ====
 
==== TileSamplePeripheral.java ====
接続されているComputerのリストを管理する処理と、そのComputerにイベントを発生させる処理を追加します。
+
イベント発生の処理と、イベントを発生させるための接続されたComputerやTurtleのリストの管理を追加する。
 
 
*Computerリストの初期化
 
 
<source lang = "java">
 
<source lang = "java">
 
private final Set<IComputerAccess> m_computers;
 
private final Set<IComputerAccess> m_computers;
151行目: 139行目:
 
}
 
}
 
</source>
 
</source>
接続されているComputerのIComputerAccessインスタンスはHashSetのm_computersに格納します。<br>
+
↑コンストラクタで接続されたComputerやTurtleへイベントを発生させるのに必要なIComputerAccessインスタンスのリストを初期化する。
m_computersをコンストラクタで初期化します。
 
 
 
*IComputerAccessインスタンスの追加と削除
 
 
<source lang = "java">
 
<source lang = "java">
 
@Override
 
@Override
 
public void attach(IComputerAccess computer) {
 
public void attach(IComputerAccess computer) {
synchronized(this) {
+
synchronized(this.m_computers) {
m_computers.add(computer);
+
this.m_computers.add(computer);
 
}
 
}
 
}
 
}
165行目: 150行目:
 
@Override
 
@Override
 
public void detach(IComputerAccess computer) {
 
public void detach(IComputerAccess computer) {
synchronized(this) {
+
synchronized(this.m_computers) {
m_computers.remove(computer);
+
this.m_computers.remove(computer);
 
}
 
}
 
}
 
}
 
</source>
 
</source>
attach()で接続されたComputerのIComputerAccessインスタンスをm_computersへ追加、detach()で取り外されたComputerのComputerAccessインスタンスをm_computersから削除します。こうすることによってm_computersには常に接続されているComputerだけが登録されているようになっています。<br>
+
↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach()で取り外されたComputerやTurtleのComputerAccessインスタンスをリストから削除。このリストはMinecraftスレッドから呼び出されるclick()からもアクセスされるのでsynchronizedで排他制御している。
 
 
(synchronizedによる排他制御については後述)
 
 
 
*click()
 
周辺機器ブロックが右クリックされたときにBlockSamplePeripheralから呼び出されます。
 
 
<source lang = "java">
 
<source lang = "java">
 
public void click() {
 
public void click() {
Map<String, Integer> pos = new HashMap<String, Integer>();
+
synchronized (this.m_computers) {
pos.put("x", this.xCoord);
+
for (IComputerAccess computer : this.m_computers) {
pos.put("y", this.yCoord);
+
computer.queueEvent("sample_click", new Object[] {computer.getAttachmentName()} );
pos.put("z", this.zCoord);
 
 
 
synchronized(this) {
 
for (IComputerAccess computer : m_computers) {
 
computer.queueEvent("sample_click",
 
new Object[] {computer.getAttachmentName(), pos} );
 
 
}
 
}
 
}
 
}
 
}
 
}
 
</source>
 
</source>
m_computersに登録されているすべてのComputerへIComputerAccess.queueEvent()で"sample_click"イベントを発生させます。イベントのパラメータとして、一番目に周辺機器の接続名(文字列型)、二番目に周辺機器ブロックの座標(テーブル型)を渡しています。
+
↑周辺機器ブロックがクリックされた時に、ブロックのクラスから呼び出される。IComputerAccessインスタンスのリストにある全てのComputerやTurtleへIComputerAccess.queueEvent()で"sample_click"イベントを発生させる。前述の通り、リストへは排他制御でアクセスしている。
 
 
(synchronizedによる排他制御については後述)
 
 
 
==== イベントの名前とパラメータ ====
 
イベント名は、発生したイベントの内容が分かりやすいように"'''周辺機器の種類_イベントの内容'''"のような形にすることが'''推奨'''されています(APIのjavadoc参照)。
 
 
 
queueEvent()の引数はComputerのos.queueEvent()と同様です。ただし、イベントのパラメータはオブジェクト型の配列として渡します。値の型は[[ComputerCraft_API/メソッドの追加#引数や戻り値の型|callMethod()の戻り値と同様]]に適切なLuaの型へと自動的に変換されます。
 
 
 
==== Minecraftとの競合 ====
 
callMethod()と同様に、attach()とdetach()もComputerCraftのLuaスレッドから呼び出されているため、attach()やdetach()の処理中に、Minecraftのスレッドからアクセスされる可能性のあるフィールドへアクセスすると競合が発生する可能性があります。従って、そのような処理では適宜synchronizedなどで排他制御する必要があります。
 
  
今回のサンプルでは、ComputerCraftのLuaスレッドから呼び出されるattach()/detach()のm_computersへの変更と、Minecraftのスレッドから呼び出されるclick()のm_computersからの取得が競合してしまう可能性があります。そのため、それぞれのm_computersへのアクセスはsynchronizedブロック内で排他的に行っています。
+
*イベント
 +
イベントの内容が分かりやすいように、イベント名は"[周辺機器の種類]_[イベントの内容]"の形にする事が推奨されている。<br>
 +
ComputerやTurtleがどの周辺機器から発生したイベントなのか分かるように、IComputerAccess.queueEvent()の第二引数のオブジェクト型配列argumentsの一番目にはIComputerAccess.getAttachmentName()を返すとよい。<br>
 +
os.pullEvent関数に対してargumentsは最大で5つの値を返すことができ、値の型はcallMethod()と同様に適切なLuaの型へと変換される。argumentsに空の配列を渡すとos.pullEvent関数はイベント名以外は何も返さない。

Minecraft Modding Wikiへの投稿はすべて、他の投稿者によって編集、変更、除去される場合があります。 自分が書いたものが他の人に容赦なく編集されるのを望まない場合は、ここに投稿しないでください。
また、投稿するのは、自分で書いたものか、パブリック ドメインまたはそれに類するフリーな資料からの複製であることを約束してください(詳細はMinecraft Modding Wiki:著作権を参照)。 著作権保護されている作品は、許諾なしに投稿しないでください!

このページを編集するには、下記の確認用の質問に回答してください (詳細):

取り消し 編集の仕方 (新しいウィンドウで開きます)

このページで使用されているテンプレート: