提供: defeatedcrow mod wiki
移動先: 案内検索

<目次に戻る>

レシピの追加

作ったアイテムに、サバイバルでの入手手段を作らなければサバイバルで使用できません。
安易な手段はクラフトレシピを追加してアイテムの組み合わせから作成できるようにすることです。(それ以外にも、ダンジョンルートへの追加、村人からの購入、釣りや農作物、ブロックからのドロップ追加、ブロックの場合は自然生成など、色々な方法があります。)

クラフトレシピの作成

今回はクラフトで全て入手可能にします。かまどなど複数の材料を使えない物は中間素材が必要になりやすく煩雑であることと、他MOD装置に頼るとそのMODが必須になってしまうため。
レシピクラスはFlameCore内ではなく、別クラスに分離させます。

  • RegisterRecipe.class
package defeatedcrow.flamethrower;

import java.util.ArrayList;

import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraftforge.oredict.ShapedOreRecipe;
import net.minecraftforge.oredict.ShapelessOreRecipe;
import cpw.mods.fml.common.registry.GameRegistry;

public class RegisterRecipe {

	public static void addRecipe() {

		GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(FlameCore.flamethrower, 1, 0), new Object[] {
				"XXX",
				" YZ",
				Character.valueOf('X'),
				"ingotIron",
				Character.valueOf('Y'),
				new ItemStack(FlameCore.magazine, 1, 0),
				Character.valueOf('Z'),
				new ItemStack(Items.flint_and_steel, 1, 32767) }));

		GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(FlameCore.magazine, 1, 0), new Object[] {
				"XX",
				"XX",
				Character.valueOf('X'),
				new ItemStack(FlameCore.smallAmpoule, 1, 0) }));

		GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(Items.arrow, 1, 0), new Object[] {
				"XX",
				"XX",
				Character.valueOf('X'),
				new ItemStack(FlameCore.smallAmpoule, 1, 1) }));
               }

	}

レシピは鉱石辞書対応したいので、ShapedOreRecipeを使用します。

		GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(FlameCore.flamethrower, 1, 0), new Object[] {
				"XXX",
				" YZ",
				Character.valueOf('X'),
				"ingotIron",
				Character.valueOf('Y'),
				new ItemStack(FlameCore.magazine, 1, 0),
				Character.valueOf('Z'),
				new ItemStack(Items.flint_and_steel, 1, 32767) }));

GameRegistryのレシピ追加用メソッド、

GameRegistry.addRecipe(IRecipe recipe)

ここにIRecipe実装クラスとしてShapedOreRecipenのインスタンスを入れます。辞書名はStringとして使用できます。上記の場合は"ingtoIron"部分。

他MOD液体を銃倉レシピに使う

液体をレシピにどう使うか、という部分です。
クラフトレシピなのでアイテムしか使用できませんが、他MODの液体容器をMODごとに開発環境に組み込んでアイテムを取得して…というのも、findItemでアイテム名を手動で取得して…というのも取りこぼしが多すぎて大変そうです。ですので、Forgeの液体容器登録機能を使います。

登録された液体容器は「液体」「液体入り容器」「空容器」のセットとして、FluidContainerRegistryに登録されています。なので、ここから逆引きできれば、液体名さえ分かっていれば得色々なMODで追加される液体容器に自動対応できます。

  • RegisterRecipe.class

まず、クラスに以下を追加

public class RegisterRecipe {

	private RegisterRecipe() {}

	private static boolean hasRecipe = false;

	private static Fluid camellia = null;
	private static ArrayList<ItemStack> camCont = new ArrayList<ItemStack>();
	private static Fluid vegi = null;
	private static ArrayList<ItemStack> vegiCont = new ArrayList<ItemStack>();
	private static Fluid fuelBC = null;
	private static ArrayList<ItemStack> fuelCont = new ArrayList<ItemStack>();
	private static Fluid fuelEIO = null;
	private static ArrayList<ItemStack> eioCont = new ArrayList<ItemStack>();
	private static Fluid biogasIC2 = null;
	private static ArrayList<ItemStack> ic2Cont = new ArrayList<ItemStack>();
	private static Fluid fuelFFM = null;
	private static ArrayList<ItemStack> bioCont = new ArrayList<ItemStack>();
	private static Fluid seedoilFFM = null;
	private static ArrayList<ItemStack> seedCont = new ArrayList<ItemStack>();
	private static Fluid creosoteRC = null;
	private static ArrayList<ItemStack> rcCont = new ArrayList<ItemStack>();
	private static Fluid redstoneTE = null;
	private static ArrayList<ItemStack> teCont = new ArrayList<ItemStack>();
	private static Fluid hellsoy = null;
	private static ArrayList<ItemStack> tofuCont = new ArrayList<ItemStack>();
	private static Fluid lifestream = null;
	private static ArrayList<ItemStack> lifeCont = new ArrayList<ItemStack>();

	public static void addRecipe() { ...

	private RegisterRecipe() {}

コンストラクタ生成をprivate(他のクラスからの呼び出し不可)に。後述のListはstaticなのでインスタンスが複数出来てListの中身がうまく反映されない…というような悲劇は無いような気はしますが、念のための事故防止策。

	private static Fluid camellia = null;
	private static ArrayList<ItemStack> camCont = new ArrayList<ItemStack>();

これらは取得する液体や液体容器を入れるもの。万が一全てのFluidがnullのまま(どの液体も追加されていない環境)の場合は、

	private static boolean hasRecipe = false;

のhasRecipeフラグもfalseのままになるため、条件分岐を作ってバニラ用レシピを追加します。


次にaddRecipeメソッドにも内容追加

	public static void addRecipe() {

		...

                // 名称からFluidを取得
		camellia = FluidRegistry.getFluid("camellia_oil");
		vegi = FluidRegistry.getFluid("vegitable_oil");
		fuelBC = FluidRegistry.getFluid("fuel");
		fuelEIO = FluidRegistry.getFluid("rocket_fuel");
		biogasIC2 = FluidRegistry.getFluid("ic2biogas");
		fuelFFM = FluidRegistry.getFluid("bioethanol");
		seedoilFFM = FluidRegistry.getFluid("seedoil");
		creosoteRC = FluidRegistry.getFluid("creosote");
		redstoneTE = FluidRegistry.getFluid("redstone");
		hellsoy = FluidRegistry.getFluid("hell soy milk");
		lifestream = FluidRegistry.getFluid("lifestream");

		FluidContainerData[] data = FluidContainerRegistry.getRegisteredFluidContainerData();

		for (FluidContainerData f : data) {
			if (camellia != null && f.fluid.isFluidEqual(new FluidStack(camellia, 1000)) && f.filledContainer != null) {
				camCont.add(f.filledContainer);
				if (f.fluid.amount == 1000)
					fluidRecipe(f.filledContainer, 4);
				else
					fluidRecipe(f.filledContainer, 1);
				hasRecipe = true;
				continue;
			}
			if (vegi != null && f.fluid.isFluidEqual(new FluidStack(vegi, 1000)) && f.filledContainer != null) {
				vegiCont.add(f.filledContainer);
				camCont.add(f.filledContainer);
				if (f.fluid.amount == 1000)
					fluidRecipe(f.filledContainer, 2);
				hasRecipe = true;
				continue;
			}
			if (fuelBC != null && f.fluid.isFluidEqual(new FluidStack(fuelBC, 1000)) && f.filledContainer != null) {
				fuelCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}
			if (fuelEIO != null && f.fluid.isFluidEqual(new FluidStack(fuelEIO, 1000)) && f.filledContainer != null) {
				eioCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}
			if (biogasIC2 != null && f.fluid.isFluidEqual(new FluidStack(biogasIC2, 1000)) && f.filledContainer != null) {
				ic2Cont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}
			if (fuelFFM != null && f.fluid.isFluidEqual(new FluidStack(fuelFFM, 1000)) && f.filledContainer != null) {
				bioCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}
			if (seedoilFFM != null && f.fluid.isFluidEqual(new FluidStack(seedoilFFM, 1000))
					&& f.filledContainer != null) {
				seedCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 2);
				hasRecipe = true;
				continue;
			}
			if (creosoteRC != null && f.fluid.isFluidEqual(new FluidStack(creosoteRC, 1000))
					&& f.filledContainer != null) {
				rcCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 2);
				hasRecipe = true;
				continue;
			}
			if (redstoneTE != null && f.fluid.isFluidEqual(new FluidStack(redstoneTE, 1000))
					&& f.filledContainer != null) {
				teCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 2);
				hasRecipe = true;
				continue;
			}
			if (hellsoy != null && f.fluid.isFluidEqual(new FluidStack(hellsoy, 1000)) && f.filledContainer != null) {
				tofuCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 2);
				hasRecipe = true;
				continue;
			}
			if (lifestream != null && f.fluid.isFluidEqual(new FluidStack(lifestream, 1000))
					&& f.filledContainer != null) {
				lifeCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}
		}

		if (!hasRecipe) {
			GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(FlameCore.magazine, 1, 0), new Object[] {
					" Y ",
					"XZX",
					Character.valueOf('X'),
					new ItemStack(Items.slime_ball),
					Character.valueOf('Y'),
					new ItemStack(Items.gunpowder, 1),
					Character.valueOf('Z'),
					new ItemStack(Items.ghast_tear) }));
		}

	}
	static void fluidRecipe(ItemStack item, int amount) {

		GameRegistry.addRecipe(new ShapedOreRecipe(new ItemStack(FlameCore.magazine, amount, 0), new Object[] {
				" Y ",
				"XZX",
				Character.valueOf('X'),
				new ItemStack(Items.slime_ball),
				Character.valueOf('Y'),
				new ItemStack(Items.gunpowder, 1),
				Character.valueOf('Z'),
				item }));

	}

おそらくもうちょっと合理的な方法はある気がしますが、

camellia = FluidRegistry.getFluid("camellia_oil");

まずStringからFluidを取得、これを使いたい液体一通りに行う。名称は、NEIのdamp機能などで事前に調べています。
次に、力業気味に

		FluidContainerData[] data = FluidContainerRegistry.getRegisteredFluidContainerData();

		for (FluidContainerData f : data) {}

FluidContainerDataには全液体の全容器の登録状態が入っているので、forでぶん回します。
余談ですが、AMT2等では異なる方法を使っています。あちらでは、「液体容器が登録されたときに呼ばれるイベント」を使って、液体の種類ごとにコンテナを調べられるような独自の逆引き用リストを作っています。

			if (fuelBC != null && f.fluid.isFluidEqual(new FluidStack(fuelBC, 1000)) && f.filledContainer != null) {
				fuelCont.add(f.filledContainer);
				fluidRecipe(f.filledContainer, 4);
				hasRecipe = true;
				continue;
			}

目当ての液体の容器だった場合、念のためのnullチェックを経て用意した容器List(ここではfuelCont)に容器のItemStackを入れつつ、fluidRecipeメソッドでレシピ登録します。液体によって得られるエネルギー量や入手難度が違ったりするので、(独断と偏見で)Tierを設定して作成個数を増やしています。