ここでは例として、丸石を丸石ハーフブロック2個にクラフトできるハサミを作成します。
構成ファイル
- mod_StoneCutter.java
- ItemStoneCutter.java
※1.6以降はA.K.さんに引き継ぎ。トピックの最新記事を参照。
─────────────────────────────────────────────────────────────────────────────
1.3.2~1.4.7の場合(Forge#172以降)
1.3.x以降ではItemクラスにgetContainerItemStack(ItemStack itemStack)が追加されているので、これをオーバーライドすれば簡単に作成できます。
mod_StoneCutter.java
- コード: 全て選択
public class mod_StoneCutter extends BaseMod {
public void load(){
ItemStoneCutter cutter = new ItemStoneCutter(cutterItemID-256);
GameRegistry.registerCraftingHandler(cutter);
ModLoader.addShapelessRecipe(new ItemStack(44, 2, 3),
Block.cobblestone, new ItemStack(cutter,1,-1));
}
}
GameRegistry.registerCraftingHandler で、ICrafthingHandler を実装したクラスを登録します。
登録するためのクラスはICrafthingHandlerを実装している必要があるため、Item型 ではなく ItemStoneCutter型でフィールドを宣言する必要があることに注意して下さい。
レシピの登録時にはダメージ値-1を指定し、ダメージを受けた状態でもクラフトできるようにします。
ItemStoneCutter.jaca
- コード: 全て選択
public class ItemStoneCutter extends Item implements ICraftingHandler{
private boolean repair; //修理判定
//アイテムがクラフト後に戻らないようにする
public boolean doesContainerItemLeaveCraftingGrid(ItemStack par1ItemStack){
return false;
}
@Override //レシピが修理がどうかをチェック
public void onCrafting(EntityPlayer player, ItemStack item, IInventory craftMatrix){
repair = this.itemID == item.itemID;
}
//修理でなければクラフト後にgetContainerItemStackを呼び出すように設定
public boolean hasContainerItem(){
return !repair;
}
//クラフト後のアイテムを、ダメージを与えて返す
public ItemStack getContainerItemStack(ItemStack itemStack){
if (itemStack != null && itemStack.itemID == this.itemID){
itemStack.setItemDamage(itemStack.getItemDamage()+1);
}
return itemStack;
}
}
ダメージ値を持つアイテムは同じアイテム同士で修理可能なので、修理時にアイテムが残らないように、レシピが修理かどうかを判定しています。
クラフト時のレシピを参照するために、ForgeのICraftingHandlerインターフェイスを使用しています。
修理できない仕様にするのであれば、コンストラクタで、this.setNoRepair(); を加えてください。
─────────────────────────────────────────────────────────────────────────────
1.5.0以降の場合(Forge#559以降)
基本的には1.4.7と同じです。
1.5ではテクスチャの指定、名前の設定、レシピのダメージ値指定が変わっているのでそこだけ変更します。
mod_StoneCutter.java
- コード: 全て選択
ItemStoneCutter cutter = (ItemStoneCutter)(new ItemStoneCutter(cutterItemID-256)).setUnlocalizedName("cutter");
//~略~//
ModLoader.addShapelessRecipe(new ItemStack(44, 2, 3),
Block.cobblestone, new ItemStack(cutter,1,32767)); //ダメージ値に32767を設定
名前の指定方法が setUnlocalizedName になっているので変更します。
テクスチャはItemStoneCutterで指定します。
ダメージ無視のクラフトに設定するダメージ値が -1 から 32767 に変更になったので変更します。
ItemStoneCutter.jaca
- コード: 全て選択
//1.5のテクスチャ指定
@SideOnly(Side.CLIENT)
public void updateIcons(IconRegister par1IconRegister)
{
this.iconIndex = Item.shears.getIconFromDamage(0);
}
既存のハサミのテクスチャを設定しています。
独自のテクスチャを設定したい場合は、このコードは不要です。
テクスチャとしてcatter.pngを用意すれば、自動でその画像に設定されます。
詳しくは1.5テクスチャチュートリアルを参照
─────────────────────────────────────────────────────────────────────────────
1.5.2以降の場合(Forge#684以降)
基本的には1.5.0と同じです。
アイコンのフィールド名が変更になっているのでそこだけ変更します。
ItemStoneCutter.jaca
- コード: 全て選択
//1.5.2のテクスチャ指定
@SideOnly(Side.CLIENT)
public void registerIcons(IconRegister par1IconRegister)
{
this.itemIcon = Item.shears.getIconFromDamage(0);
}
─────────────────────────────────────────────────────────────────────────────
1.2.5の場合(Forge#135~171)
1.2.5ではgetContainerItemでダメージ値を返せないため、ForgeのICraftingHandlerインターフェイスを使用して、クラフト時のインベントリを操作する必要があります。
mod_StoneCutter.java
- コード: 全て選択
public class mod_StoneCutter extends BaseMod {
MinecraftForge.registerCraftingHandler(cutter);
}
registerCraftingHandler を実行するクラスが違う以外は1.3.x以降と同じです。
ItemStoneCutter.jaca
- コード: 全て選択
public class ItemStoneCutter extends Item implements ICraftingHandler{
//クラフト後の材料アイテム減少処理前に呼ばれる
public void onTakenFromCrafting(EntityPlayer player, ItemStack stack, IInventory craftMatrix){
if(stack.itemID == this.shiftedIndex) return; //レシピが修理ならそのまま終了
for (int var2 = 0; var2 < craftMatrix.getSizeInventory(); ++var2){
ItemStack var3 = craftMatrix.getStackInSlot(var2);
if (var3 != null && var3.itemID == this.shiftedIndex){
ItemStack var4 = new ItemStack(this, var3.stackSize+1, var3.getItemDamage()+1);
if(var3.getItemDamage() >= var3.getMaxDamage()) var4 = null;
craftMatrix.setInventorySlotContents(var2, var4);
}
}
}
}
ICraftHanhlerで実装するメソッドが異なる以外は、ほぼ1.3.x以降と同じです。
しかし1.2.5ではクラフト後にダメージを与える処理を自分で実装する必要があります。
修理関係の判定もこの中で同時に行います。
処理内容は、作業台のインベントリを走査して自分と同じIDのアイテムを見つけたら、ダメージ値を1増やしています。
またダメージ値がMaxDamageを超えたらnullを返します。
このあと材料アイテム全てに対してstackSizeが-1されるので、対策としてstackSizeを+1にしてから、インベントリにセットし直しています。
─────────────────────────────────────────────────────────────────────────────
Stepup 改造のポイント:
1.4.2以降やpsEnchantを導入した1.2.5なら、金床で全ツールに耐久力エンチャントを付与できます。
そこで、クラフト時にもエンチャントの効果が反映されるように改造してみてはどうでしょう?
ポイントはエンチャント効果の判別方法と、耐久力の減らし方です。
ItemStackの耐久力エンチャントのレベルは以下のコードで取得できます。
- コード: 全て選択
int elv = EnchantmentHelper.getEnchantmentLevel(Enchantment.unbreaking.effectId, ItemStack);
耐久力の効果は、耐久の減る確率が 1÷(エンチャントレベル+1) になるというものです。
ここまで分かればあとは簡単ですね?
ぜひ実装にチャレンジしてみてください。
─────────────────────────────────────────────────────────────────────────────
以前1.2.5ではやり方がわからず、getContainerItemStackを実装するMODを作って配布していましたが、今回やり方を見つけてしまったので意味がなくなってしまいましたね^^
サンプルで作ったMODを添付しておきますので、参考にしてください。
zip内にソースファイルも同梱してあります。
上記のソースは一部省略してありますので、実際のコードはソースファイルで確認してください。
※添付のMODは、それぞれ下記の環境でテストしてあります。
Minecraft 1.2.5 + MinecraftForge3.4.9.171
Minecraft 1.4.7 + MinecraftForge6.6.0.499
Minecraft 1.5.0 + MinecraftForge7.7.0.569
Minecraft 1.5.1 + MinecraftForge7.7.0.602(1.5.0のソースがそのまま使用可能)
Minecraft 1.5.2 + MinecraftForge7.8.0.684
※注意:
1.2.5~1.5.2の添付ファイルに大量の誤字(cutterがcatterになってる・・orz)がありますが、便宜読み替えてください。再コンパイルのための環境準備が面倒なのと、固有名は実際にModdingする際には変更されるであろう観点から、修正はしない事にします。