提供: Minecraft Modding Wiki
2014年10月22日 (水) 22:48時点におけるNMS (トーク | 投稿記録)による版 (attach()/detach()での競合について追記)
移動先: 案内検索
この記事は執筆中です。加筆してくださる人を募集しています。

この記事は"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関数はイベント名以外は何も返さない。