(ページ作成) |
(attach()/detach()での競合について追記) |
||
155行目: | 155行目: | ||
} | } | ||
</source> | </source> | ||
− | ↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach() | + | ↑attach()で接続されたComputerやTurtleのIComputerAccessインスタンスをリストへ追加、detach()で取り外されたComputerやTurtleのComputerAccessインスタンスをリストから削除。attach()とdetach()はComputerCraftのLuaスレッドから呼び出されている。このリストはMinecraftスレッドから呼び出されるclick()からもアクセスされるのでsynchronizedで排他制御している。 |
<source lang = "java"> | <source lang = "java"> | ||
public void click() { | public void click() { |
2014年10月22日 (水) 22:48時点における版
この記事は執筆中です。加筆してくださる人を募集しています。 |
この記事は"Minecraft Forge Universal 10.13.0.x~"及び"ComputerCraft 1.65~"を前提MODとしています。 |
目次
周辺機器からイベントを発生させる
クリックされたとき、接続されたComputerやTurtleに対してイベントを発生させる周辺機器ブロックを追加する。
ソースコード
「周辺機器の追加」のソースコードを元にして、変更部分のみを解説する。
- BlockSamplePeripheral.java
package mods.sample.peripheral; import net.minecraft.block.BlockContainer; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; 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.rock); setBlockName("blockSamplePeripheral"); setCreativeTab(CreativeTabs.tabBlock); } 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 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
周辺機器のブロックがクリックされた時の処理を追加する。
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()} ); } } }
↑周辺機器ブロックがクリックされた時に、ブロックのクラスから呼び出される。IComputerAccessインスタンスのリストにある全てのComputerやTurtleへIComputerAccess.queueEvent()で"sample_click"イベントを発生させる。前述の通り、リストへは排他制御でアクセスしている。
- イベント
イベントの内容が分かりやすいように、イベント名は"[周辺機器の種類]_[イベントの内容]"の形にする事が推奨されている。
ComputerやTurtleがどの周辺機器から発生したイベントなのか分かるように、IComputerAccess.queueEvent()の第二引数のオブジェクト型配列argumentsの一番目にはIComputerAccess.getAttachmentName()を返すとよい。
os.pullEvent関数に対してargumentsは最大で5つの値を返すことができ、値の型はcallMethod()と同様に適切なLuaの型へと変換される。argumentsに空の配列を渡すとos.pullEvent関数はイベント名以外は何も返さない。