提供: Minecraft Modding Wiki
2014年5月20日 (火) 22:26時点におけるShift (トーク | 投稿記録)による版
移動先: 案内検索

この記事は"Minecraft Forge Universal 9.10.0.871~, CodeCheckenLib 1.0.0, CodeCheckenCore, NotEnoughItems"を前提MODとしています。

Iron pickaxe.png
上級者向けのチュートリアルです。

NEIのAPIを利用したチュートリアルです。 NEIのレシピ表示機能に独自のレシピを追加出来るようにします。

NEIに独自レシピを表示させる

ここでは、NEIへの表示用に用意したダミーレシピを用いての例を記載します。
ダミーレシピのため、独自のクラフトレシピ(追加マシンなど)の作成方法は含まれていません。
実際にゲーム中では使用されていない、インプットとアウトプットを表示するだけのダミー用レシピを使用した単純な例としています。

ソースコード

RegisterNEISample.java

  • Modの基幹クラス
package mods.tutorial.common;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.SidedProxy;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.Mod.Instance;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.network.NetworkMod;

/*
  modid = このMODのIDです。他のMODと重複しない名前にします
  name = このMODの名前です。好きな名前をつけよう
  version = これも任意でOK。
  dependencies = このMODが要求する・要求はしないが読み込み順を調整したいMODを記入します。
  "required"と入れると、そのMOD(ここでは9.10.~以降のForge、6.2.~以降のFML)が未導入だとクラッシュします*/
@Mod(
		modid = "RegisterNEISample",
		name = "RegisterNEISampleMod",
		version = "1.6.2_1.0",
		dependencies = "required-after:Forge@[9.10,);required-after:FML@[6.2,)"
		)

@NetworkMod(
		clientSideRequired = true,
		serverSideRequired = false
		)

public class RegisterNEISample {
	
		/*NEIへの登録をクライアントサイドのみで行うため、プロキシクラスを登録します。*/
		@SidedProxy(clientSide = "mods.tutorial.client.ClientProxy", serverSide ="mods.tutorial.common.CommonProxy")
		public static CommonProxy proxy;
		
		@Instance("RegisterNEISample")
	         public static RegisterNEISample instance;
		
		/*何かブロックやレシピ等を追加するわけではないので、postInitのみ。
		  実際に利用する場合は、ご自身のMODの必要に応じてpreInit、initメソッドを用意して下さい。
		  */
		@EventHandler
	        public void postInit(FMLPostInitializationEvent event)
		{
			/*注意点として、バニラのクラフトレシピや精錬レシピ、他MODのクラフティングシステムを利用したレシピは
			  わざわざ追加する必要がないことが多いです。
			  クラフティング自体を独自に実装したり、右クリックでの変化など、
                          そのままではNEIに対応されないものについて登録します。*/
			
			/*独自レシピの登録メソッドを呼び出しています。
			  表示させるだけのダミーレシピです。
			  実際に使用する場合は、ご自身で追加した独自クラフトのレシピのリストを作って下さい。*/

			(new NewRecipeRegister()).setRecipeList();
			
			/*NEIへの登録は、プロキシクラスを利用することでクライアントサイドのみで行います。*/

			proxy.LoadNEI();
			
		}

}

CommonProxy.java

  • サーバサイド用のクラス
package mods.tutorial.common;

public class CommonProxy {
	
	/*サーバ側は何もしません*/
	public void LoadNEI() {}
}

ClientProxy.java

  • クライアントサイド用のクラス
package mods.tutorial.client;

import cpw.mods.fml.common.Loader;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import mods.tutorial.common.CommonProxy;
import mods.tutorial.common.LoadNEIConfigSample;

@SideOnly(Side.CLIENT)
public class ClientProxy extends CommonProxy{
	
	/*NEIのロードの確認を行い、登録のメソッドを呼び出しています。*/
	@Override
	public void LoadNEI()
	{
		if (Loader.isModLoaded("NotEnoughItems"))
		{
			try
	        {
	    		LoadNEIConfigSample.load();
	        }
	        catch (Exception e)
	        {
	        	e.printStackTrace(System.err);
	        }
		}
	}
}

NewRecipeRegister.java

  • レシピ管理用のクラス
package mods.tutorial.common;

import java.util.HashMap;

import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;


/*このクラスでは、素材アイテム、完成品アイテムの組み合わせをHashMap形式で登録している。
  <br>実際にココで追加した組み合わせはレシピとしてMinecraft内で利用されることはない、架空のレシピである。
  <br>このように、NEIへの登録はクラフティングレシピのような体裁を保つ必要はなく、
  実際にゲーム内に使われていないものでも登録は可能である。
  (もちろん、追加はしたが隠しアイテムにしたい…という場合も、ここで登録しないことで対応できる。)*/
public class NewRecipeRegister {
	
	public static HashMap<ItemStack, ItemStack> newRecipeList = new HashMap<ItemStack, ItemStack>();
	
	/*架空のレシピを登録*/
	public void setRecipeList()
	{
		newRecipeList.put(new ItemStack(Item.appleRed, 1, 0), new ItemStack(Item.appleGold, 1, 0));
	}
}

LoadNEIConfigSample.java

  • APIへの登録を管理しているクラス
package mods.tutorial.common;

import mods.tutorial.client.GuiDummy;
import codechicken.nei.api.API;

/*NEIへの登録部分*/
public class LoadNEIConfigSample {
	
	/*別クラスで作るレシピ表示用インターフェースの取得*/
	public static CatchRecipeHandler catchRecipe;
	
	public static void load()
	{
		catchRecipe = new CatchRecipeHandler();
		
		API.registerRecipeHandler(catchRecipe);
		API.registerUsageHandler(catchRecipe);
		API.registerGuiOverlay(GuiDummy.class, catchRecipe.getOverlayIdentifier(), 0, 0);
	}

}

CatchRecipeHandler.java

  • 表示するレシピの設定をしているクラス
package mods.tutorial.common;

import java.awt.Rectangle;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import mods.tutorial.client.GuiDummy;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.item.ItemStack;
import codechicken.nei.NEIServerUtils;
import codechicken.nei.PositionedStack;
import codechicken.nei.recipe.TemplateRecipeHandler;


/*NEIにて、レシピ表示ボタンを押した際の処理の追加部分。
  NEI対応のメイン部分です。
  TemplateRecipeHamdlerを継承します。*/
public class CatchRecipeHandler extends TemplateRecipeHandler {
	
	/*表示用のレシピをHashMap型で用意します。*/
	private HashMap<ItemStack, ItemStack> newRecipe;
	
	/*表示用のHashMapの取得。
	  ここでは、NewRecipeRegister.classで用意しておいた架空のレシピを取得します。
	  (独自レシピの作成については割愛します。)*/
	private HashMap<ItemStack, ItemStack> recipeLoader() {
		if (NewRecipeRegister.newRecipeList != null && !NewRecipeRegister.newRecipeList.isEmpty()) {
			this.newRecipe = NewRecipeRegister.newRecipeList;
		}
		return this.newRecipe;
	}
	
	public class recipeCacher extends CachedRecipe {
		
		/*インプット、アウトプットそれぞれの表示用ItemStackです。
		  表示させる位置などの情報を持たせることが出来ます。*/
		private PositionedStack input;
		private PositionedStack result;

		/*表示用のItemStackの、画面上の座標を登録しています。
		  この座標がずれると、レシピ表示画面に表示されるアイコンがズレるので気をつけましょう。*/
		public recipeCacher(ItemStack in, ItemStack out) {
			in.stackSize = 1;
			this.input = new PositionedStack(in, 48, 21);
			this.result= new PositionedStack(out, 102, 21);
		}

		@Override
		public PositionedStack getResult() {
			return this.result;
		}
		
		@Override
		public PositionedStack getIngredient()
        {
            return this.input;
        }
		
	}
	
	public PositionedStack getResult() {
	    return null;
	}

	/*ここではダミー用のGUIを登録していますが、
	  独自クラフトシステム用に用意したGUIがあれば流用できます。
	  <br>ここで登録をしたguiからレシピ画面に飛ぶことが出来るようになります。
	  <br>もちろん、(魔術系MODのように)可愛らしいイラストなどを用意して表示させることも出来ます。*/
	@Override
	public Class<? extends GuiContainer> getGuiClass() {
	    return GuiDummy.class;
	}
	
	/*登録用の文字列です*/
	@Override
	public String getOverlayIdentifier() {
	  return "SampleRecipe";
	}

	//ここで登録をした範囲内をGUIでクリックすると文字列のレシピ画面を表示します.
	@Override
	public void loadTransferRects() {
	    transferRects.add(new TemplateRecipeHandler.RecipeTransferRect(new Rectangle(65, 25, 20, 20), "SampleRecipe"));
	}
	
	/*以下のメソッドは、NEIのGUI画面上でアイコンをクリックしたり、
	  プログレスバーの部分をクリックした時に呼び出されるメソッド*/

    @Override
    public void loadCraftingRecipes(String outputId, Object... results)
    {
        if(outputId.equals("SampleRecipe"))
        {
            HashMap<ItemStack, ItemStack> recipes = (HashMap<ItemStack, ItemStack>) this.recipeLoader();

            if(recipes == null || recipes.isEmpty())return;
            for(Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
            {
                ItemStack item = recipe.getValue();
                ItemStack in = recipe.getKey();
                arecipes.add(new recipeCacher(in, item));
            }
        }
        else
        {
            super.loadCraftingRecipes(outputId, results);
        }
    }
	
    @Override
    public void loadCraftingRecipes(ItemStack result)
    {

	HashMap<ItemStack, ItemStack> recipes = (HashMap<ItemStack, ItemStack>) this.recipeLoader();

        if(recipes == null || recipes.isEmpty())return;
        for(Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
        {
            ItemStack item = recipe.getValue();
            ItemStack in = recipe.getKey();
            if(NEIServerUtils.areStacksSameType(item, result))
            {
                arecipes.add(new recipeCacher(in, item));
            }
        }
    }
	
    @Override
    public void loadUsageRecipes(ItemStack ingredient)
    {

	HashMap<ItemStack, ItemStack> recipes = (HashMap<ItemStack, ItemStack>) this.recipeLoader();

        if(recipes == null || recipes.isEmpty())return;
        for(Entry<ItemStack, ItemStack> recipe : recipes.entrySet())
        {
            ItemStack item = recipe.getValue();
            ItemStack in = recipe.getKey();
            if(ingredient.itemID == in.itemID && ingredient.getItemDamage() == in.getItemDamage())
            {
                arecipes.add(new recipeCacher(ingredient, item));
            }
        }
    }

	/*レシピ画面に表示される名前です。*/
	@Override
	public String getRecipeName() {
		return "This is Dummy Recipe for Tutorial.";
	}

	/*レシピ画面に使われる背景画像の場所です。*/
	@Override
	public String getGuiTexture() {
		return "tutorial:textures/gui/dummygui.png";
	}

}

GuiDummy.class

  • GUIのクラス
package mods.tutorial.client;

import org.lwjgl.opengl.GL11;

import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.inventory.Container;
import net.minecraft.util.ResourceLocation;

public class GuiDummy extends GuiContainer{

	public GuiDummy(Container par1Container) {
		super(par1Container);
		
	}

	@Override
	protected void drawGuiContainerBackgroundLayer(float f, int i, int j) {
		GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
		this.mc.getTextureManager().bindTexture(new ResourceLocation("tutorial", "textures/gui/dummygui.png"));
	}

}