(attach()/detach()での競合について追記) |
(Blockのソース、Tileの解説を修正) |
||
3行目: | 3行目: | ||
== 周辺機器からイベントを発生させる == | == 周辺機器からイベントを発生させる == | ||
− | + | 右クリックされたとき、接続されたComputerやTurtleに対してイベントを発生させる周辺機器ブロックを追加する。 | |
=== ソースコード === | === ソースコード === | ||
11行目: | 11行目: | ||
<source lang = "java"> | <source lang = "java"> | ||
package mods.sample.peripheral; | package mods.sample.peripheral; | ||
+ | |||
+ | import java.util.Random; | ||
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.entity.player.EntityPlayer; | import net.minecraft.entity.player.EntityPlayer; | ||
import net.minecraft.tileentity.TileEntity; | import net.minecraft.tileentity.TileEntity; | ||
22行目: | 23行目: | ||
public BlockSamplePeripheral() { | public BlockSamplePeripheral() { | ||
− | super(Material. | + | super(Material.ground); |
− | |||
− | |||
} | } | ||
+ | @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) { | ||
34行目: | 34行目: | ||
} | } | ||
return true; | return true; | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public int quantityDropped(int meta, int fortune, Random random){ | ||
+ | return quantityDroppedWithBonus(fortune, random); | ||
+ | } | ||
+ | |||
+ | @Override | ||
+ | public int quantityDropped(Random random){ | ||
+ | return 1; | ||
} | } | ||
117行目: | 127行目: | ||
=== 解説 === | === 解説 === | ||
==== 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) { | ||
128行目: | 139行目: | ||
} | } | ||
</source> | </source> | ||
− | + | ブロックが右クリックされたらTileEntity(周辺機器)を取得してclick()を呼び出す。 | |
==== TileSamplePeripheral.java ==== | ==== TileSamplePeripheral.java ==== | ||
155行目: | 166行目: | ||
} | } | ||
</source> | </source> | ||
− | ↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach() | + | ↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach()で取り外されたComputerやTurtleのComputerAccessインスタンスをリストから削除。<br> |
+ | attach()とdetach()はComputerCraftのLuaスレッドから呼び出されている。このリストはMinecraftスレッドから呼び出されるclick()からもアクセスされるのでsynchronizedで排他制御している。 | ||
<source lang = "java"> | <source lang = "java"> | ||
public void click() { | public void click() { | ||
165行目: | 177行目: | ||
} | } | ||
</source> | </source> | ||
− | + | ↑周辺機器ブロックが右クリックされた時に、BlockSamplePeripheralから呼び出される。IComputerAccessインスタンスのリストにある全てのComputerやTurtleへIComputerAccess.queueEvent()で"sample_click"イベントを発生させる。前述の通り、リストへのアクセスは排他的に行っている。 | |
*イベント | *イベント | ||
− | + | イベント名は、発生したイベントの内容が分かりやすいように"'''周辺機器の種類_イベントの内容'''"のような形にする事が'''推奨'''されている。(APIのjavadoc参照)<br> | |
− | + | queueEvent()の引数はos.queueEvent関数と同様。ただし、イベントのパラメータはオブジェクト型配列として渡す。値の型はcallMethod()の戻り値と同様に適切なLuaの型へと変換される。イベントのパラメータの一番目には、ComputerやTurtleからどの周辺機器で発生したイベントなのかが分かるように、IComputerAccess.getAttachmentName()を渡すとよい。 | |
− |
2014年10月23日 (木) 11:29時点における版
この記事は執筆中です。加筆してくださる人を募集しています。 |
この記事は"Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"を前提MODとしています。 |
目次
周辺機器からイベントを発生させる
右クリックされたとき、接続されたComputerやTurtleに対してイベントを発生させる周辺機器ブロックを追加する。
ソースコード
「周辺機器の追加」のソースコードを元にして、変更部分のみを解説する。
- BlockSamplePeripheral.java
package mods.sample.peripheral; import java.util.Random; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class BlockSamplePeripheral extends BlockContainer { public BlockSamplePeripheral() { super(Material.ground); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) { TileEntity tile = world.getTileEntity(x, y, z); if (!world.isRemote && tile != null && tile instanceof TileSamplePeripheral) { ((TileSamplePeripheral)tile).click(); } return true; } @Override public int quantityDropped(int meta, int fortune, Random random){ return quantityDroppedWithBonus(fortune, random); } @Override public int quantityDropped(Random random){ return 1; } @Override public TileEntity createNewTileEntity(World world, int a) { return new TileSamplePeripheral(); } }
- TileSamplePeripheral.java
package mods.sample.peripheral; import java.util.HashSet; import java.util.Set; 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 { private final Set<IComputerAccess> m_computers; public TileSamplePeripheral() { m_computers = new HashSet(); } @Override public String getType() { return "sample"; } @Override public String[] getMethodNames() { return new String[] {}; } @Override public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws LuaException, InterruptedException { return null; } @Override public void attach(IComputerAccess computer) { synchronized (this.m_computers) { this.m_computers.add(computer); } } @Override public void detach(IComputerAccess computer) { synchronized (this.m_computers) { this.m_computers.remove(computer); } } @Override public boolean equals(IPeripheral other) { if ((other != null) && (other instanceof TileSamplePeripheral)) { return other == this; } return false; } public void click() { synchronized (this.m_computers) { for (IComputerAccess computer : this.m_computers) { computer.queueEvent("sample_click", new Object[] {computer.getAttachmentName()} ); } } } }
解説
BlockSamplePeripheral.java
周辺機器ブロックが右クリックされた時の処理を追加する。
@Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer entityPlayer, int side, float hitX, float hitY, float hitZ) { TileEntity tile = world.getTileEntity(x, y, z); if (!world.isRemote && tile != null && tile instanceof TileSamplePeripheral) { ((TileSamplePeripheral)tile).click(); } return true; }
ブロックが右クリックされたらTileEntity(周辺機器)を取得してclick()を呼び出す。
TileSamplePeripheral.java
イベント発生の処理と、イベントを発生させるための接続されたComputerやTurtleのリストの管理を追加する。
private final Set<IComputerAccess> m_computers; public TileSamplePeripheral() { m_computers = new HashSet(); }
↑コンストラクタで接続されたComputerやTurtleへイベントを発生させるのに必要なIComputerAccessインスタンスのリストを初期化する。
@Override public void attach(IComputerAccess computer) { synchronized(this.m_computers) { this.m_computers.add(computer); } } @Override public void detach(IComputerAccess computer) { synchronized(this.m_computers) { this.m_computers.remove(computer); } }
↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach()で取り外されたComputerやTurtleのComputerAccessインスタンスをリストから削除。
attach()とdetach()はComputerCraftのLuaスレッドから呼び出されている。このリストはMinecraftスレッドから呼び出されるclick()からもアクセスされるのでsynchronizedで排他制御している。
public void click() { synchronized (this.m_computers) { for (IComputerAccess computer : this.m_computers) { computer.queueEvent("sample_click", new Object[] {computer.getAttachmentName()} ); } } }
↑周辺機器ブロックが右クリックされた時に、BlockSamplePeripheralから呼び出される。IComputerAccessインスタンスのリストにある全てのComputerやTurtleへIComputerAccess.queueEvent()で"sample_click"イベントを発生させる。前述の通り、リストへのアクセスは排他的に行っている。
- イベント
イベント名は、発生したイベントの内容が分かりやすいように"周辺機器の種類_イベントの内容"のような形にする事が推奨されている。(APIのjavadoc参照)
queueEvent()の引数はos.queueEvent関数と同様。ただし、イベントのパラメータはオブジェクト型配列として渡す。値の型はcallMethod()の戻り値と同様に適切なLuaの型へと変換される。イベントのパラメータの一番目には、ComputerやTurtleからどの周辺機器で発生したイベントなのかが分かるように、IComputerAccess.getAttachmentName()を渡すとよい。