提供: Minecraft Modding Wiki
2014年8月19日 (火) 23:55時点におけるDefeatedcrow (トーク | 投稿記録)による版
移動先: 案内検索

この記事は"Minecraft Forge Universal 10.13.0.1197~"を前提MODとしています。

このページではInterModCommsの利用について記載します。 チュートリアル作成バージョンは1.7.10ですが、1.7.2や、1.6でも同じ要領で作成できます。

1.7のInterModCommsの利用

IMC(InterModComms)とは、 MOD間で相互に送受信することで、自分のMODの開発環境に相手のMODソースを導入せずに簡単に連携要素を追加できるものです。 代表的な使用例として、BuildCraftの装飾板レシピやリファイナリーレシピの追加機能があります。

受信用のイベント(IMCEvent)がinitとpostInitの間に発生するので、 送信側は相手のIMCEventよりも前に送信処理を行います。 (initまでに送信しておくと確実かと思います。)

今回は一例として、同じMOD内で送信、受信を行っていますが、 例えばこのチュートリアルMODを導入している環境であれば、このMODのID宛にIMCを送ることで、 どのMODからでもこのMODの受信メソッドを利用してレシピを追加できるようになります。

ソースコード

  • IMCTutorialCore.java
package tutorial.common;

import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLInterModComms;
import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent;


/*
 * IMC送受信の使い方です。
 * 
 * コアクラスのみでも動作しますが、今回はIMC受信側のメソッドを別クラスに分けています。
 */
@Mod(
		modid = "IMCTutorial",
		name = "IMCTutorial",
		version = "1.7.10_1.0a",
		dependencies = "required-after:Forge@[10.13.0.1197,)"
		)
public class IMCTutorialCore {
	
	/*インスタンス生成*/
	@Instance("IMCTutorial")
	public static IMCTutorialCore instance;
	
	/*ロガー生成*/
	public static Logger logger = LogManager.getLogger("IMCTutorial");
	
	/*
	 * IMC送信をここで行っています。
	 * なお、不要のためpreInitメソッドは省略。
	 */
	@EventHandler
	public void init(FMLInitializationEvent event)
	{
		/*まずNBTTagCompoundを生成*/
		NBTTagCompound toSend = new NBTTagCompound();
		toSend.setTag("input", new NBTTagCompound());
		toSend.setTag("output", new NBTTagCompound());
		
		/*
		 * このMODの受信イベントでは、
		 * 1."input"のタグのItemStack(カマドレシピの材料)
		 * 2."output"タグのItemStack(カマドレシピの完成品)
		 * 3."DamageSensitive"タグのboolean(trueでinputのダメージ値指定レシピ、falseでダメージ値によらないレシピ)
		 * 上記3点を用意して、このMODのIDである"IMCTutorial"あてに"addFurnaceRecipe"というキーでNBTTagを送信します。
		 * 
		 * 今回送ったのは、ダメージ値によらず、鉄シャベルから鉄インゴットに精錬するレシピです。
		 * つまり、使い古したシャベルをインゴットに還元するレシピですね。
		 */
		new ItemStack(Items.iron_shovel, 1, 0).writeToNBT(toSend.getCompoundTag("input"));
		new ItemStack(Items.iron_ingot, 1, 0).writeToNBT(toSend.getCompoundTag("output"));
		toSend.setBoolean("DamageSensitive", false);
		FMLInterModComms.sendMessage("IMCTutorial", "addFurnaceRecipe", toSend);
	}
	
	@EventHandler
	public void receiveIMC(IMCEvent event)
	{
		/*受信処理は別のクラスで行います。*/
		ReceiveIMCEvent.receiveIMC(event);
	}

}
  • IMCTutorialCore.java
package tutorial.common;

import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.nbt.NBTTagCompound;
import cpw.mods.fml.common.event.FMLInterModComms.IMCEvent;
import cpw.mods.fml.common.event.FMLInterModComms.IMCMessage;
import cpw.mods.fml.common.registry.GameRegistry;

/*IMC受信をここで行っています。 */
public class ReceiveIMCEvent {
	
	private ReceiveIMCEvent(){}
	
	/*メインクラスのIMCEventで呼ばれるメソッド。*/
	public static void receiveIMC(IMCEvent event)
	{
		/*このMODのModID宛に来ているメッセージの数だけ、処理を繰り返します。*/
		for (IMCMessage message : event.getMessages())
		{
			/*レシピ追加に必要な"addFurnaceRecipe"キーを持っているか*/
			if (message.key.equals("addFurnaceRecipe"))
			{
				receiveAddRecipe(event, message);
			}
			/*
			 * キーが違うので、ロガークラスを通して警告メッセージを出力しています。
			 * IMC送受信はイマイチ何も出さずにやりとりされてしまうので、成否判定のログを出しておいたほうが安全。
			 */
			else
			{
				IMCTutorialCore.logger.warn("Received IMC message with unknown key : " + message.key);
			}
		}
	}
	
	/*レシピ追加に必要な"addFurnaceRecipe"キーを持っていた場合に呼ぶ処理*/
	private static void receiveAddRecipe(IMCEvent event, IMCMessage message)
	{
		boolean flag = false;
		/*NBTTagを持ったメッセージである*/
		if (message.isNBTMessage())
		{
			NBTTagCompound tag = message.getNBTValue();
			/*input、output、"DamageSensitive"のbooleanが揃っているのを確認*/
			if (tag.hasKey("input", 10) && tag.hasKey("output", 10) && tag.hasKey("DamageSensitive"))
			{
				/*ItemStack、booleanを読み取り*/
				ItemStack input = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("input"));
				ItemStack output = ItemStack.loadItemStackFromNBT(tag.getCompoundTag("output"));
				boolean sensitive = tag.getBoolean("DamageSensitive");
				
				if (input != null && output != null)
				{
					/*booleanの結果により、2通りの方法で精錬レシピを追加*/
					if (sensitive)
					{
						FurnaceRecipes.smelting().func_151394_a(input, output, 0.0F);	
					}
					else
					{
						FurnaceRecipes.smelting().func_151394_a(new ItemStack(input.getItem(), 1, 32767), output, 0.0F);
					}
					/*成功フラグ*/
					flag = true;
				}
			}
		}
		/*失敗時、失敗メッセージを出しておく*/
		if (!flag)
		{
			IMCTutorialCore.logger.warn("Failed to register new Furnace recipe with IMCMassage from " + message.getSender());
		}
	}
}