【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.8 ソース付属

クライアント/サーバーMODの開発に関する話題、技術交換はこちらで。質問は質問フォーラムへお願いします。
  • (PostNo.74902)

【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.8 ソース付属

投稿記事by takanasayo » 2013年1月21日(月) 14:29

MinecraftForgeを使用して、RedPowerのノコギリのように、クラフト時に耐久値が減るアイテムの作り方を解説します。
ここでは例として、丸石を丸石ハーフブロック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する際には変更されるであろう観点から、修正はしない事にします。
添付ファイル
mod_StoneCutter1.2.5.2.zip
コード修正&コメント追記&エンチャント対応版
(4.31 KiB) ダウンロード数: 28 回
mod_StoneCatter1.5.2.zip
(3.29 KiB) ダウンロード数: 71 回
mod_StoneCatter1.5.0.zip
(3.29 KiB) ダウンロード数: 27 回
mod_StoneCatter1.4.7.zip
(2.99 KiB) ダウンロード数: 56 回
mod_StoneCatter1.2.5.zip
(2.78 KiB) ダウンロード数: 27 回
最後に編集したユーザー takanasayo [ 2014年12月09日(火) 21:28 ], 累計 28 回
アバター
takanasayo
ID:24a0e3f4
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.75264)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.4.7

投稿記事by FirstSpring » 2013年1月23日(水) 18:39

takanasayo さんが書きました:

アイテムにsetNoRepair()をつけてやらないと修理レシピの関係で増殖してしまうので訂正お願いします。
FirstSpring
ID:5ab9d9c0
レッドストーン掘り
 
記事: 517
登録日時: 2012年10月12日(金) 23:14
お住まい: null

  • (PostNo.75302)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.4.7

投稿記事by takanasayo » 2013年1月23日(水) 20:56

FirstSpring さんが書きました:アイテムにsetNoRepair()をつけてやらないと修理レシピの関係で増殖してしまうので訂正お願いします。

増殖?テスト中はそのような挙動はありませんでしたが、どういう状況で増殖するんですか?
アバター
takanasayo
ID:3f0e136a
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.75306)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.4.7

投稿記事by FirstSpring » 2013年1月23日(水) 21:13

takanasayo さんが書きました:

石ハサミ同士をクラフトするとバニラのツール修理レシピにより増殖するようです。
一応参考画像を添付しておきます。
添付ファイル
2013-01-23_21.12.36.png
FirstSpring
ID:5ab9d9c0
レッドストーン掘り
 
記事: 517
登録日時: 2012年10月12日(金) 23:14
お住まい: null

  • (PostNo.75308)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.4.7

投稿記事by takanasayo » 2013年1月23日(水) 21:24

FirstSpring さんが書きました:
takanasayo さんが書きました:

石ハサミ同士をクラフトするとバニラのツール修理レシピにより増殖するようです。
一応参考画像を添付しておきます。

なるほど。
ふむ、ちょっと興味が出たので、修理可能にする方法を探ってみます。
アバター
takanasayo
ID:3f0e136a
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.75323)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.4.7

投稿記事by takanasayo » 2013年1月23日(水) 22:59

思ったより簡単だったので、修理可能になるようにソースと添付ファイル修正しておきました。
よければ確認してみてください。
報告どうもでした。
nico_012.png
nico_012.png (5.15 KiB) 表示数: 8485 回
nico_011.png
nico_011.png (4.3 KiB) 表示数: 8485 回
最後に編集したユーザー takanasayo [ 2013年5月03日(金) 23:17 ], 累計 1 回
アバター
takanasayo
ID:3f0e136a
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.90380)

1.5対応

投稿記事by takanasayo » 2013年3月31日(日) 11:08

1.5対応コード掲載しました。
添付MODにソースも付属してます。
アバター
takanasayo
ID:13deabca
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.97463)

1.5.2対応

投稿記事by takanasayo » 2013年5月03日(金) 23:26

1.5.2対応コードとファイル追加しました。
アバター
takanasayo
ID:3b5f2435
ラピスラズリ収集家
 
記事: 954
登録日時: 2012年7月26日(木) 04:00
お住まい: 石の中にいる

  • (PostNo.114146)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.5.2 ソース付属

投稿記事by A.K. » 2013年7月15日(月) 00:53

1.6.2用のStoneCutterとソースです.
テクスチャの指定方法の変更以外に変わった箇所はありません.
添付ファイル
StoneCutter162.zip
(3.74 KiB) ダウンロード数: 87 回
もじんぐしたい。。。。
アバター
A.K.
ID:1e285010
ラピスラズリ収集家
 
記事: 1386
登録日時: 2012年9月03日(月) 19:34

  • (PostNo.152038)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.6.2 ソース付属

投稿記事by A.K. » 2014年1月13日(月) 17:49

1.6.4対応版、および、1.7.2対応版を更新。
1.7.2での変更点:
  • ICraftHandlerの廃止とItemCraftedEventの追加によるコーディングの変更
    GameRegistry.registerCraftingHandler(cutter);→FMLCommonHandler.instance().bus().register(cutter);
  • IDの廃止により、アイテムの比較をインスタンス比較に変更。
    本体への追加:GameRegistry.registerItem(cutter, "stone_cutter");
    第二引数はこのアイテムの固有文字列です。他のMODと被らない文字列を指定して下さい。
onCraftメソッドは以下のように変更されます。
コード: 全て選択
   //修理かどうかを判定する
   @SubscribeEvent
   public void onCrafting(ItemCraftedEvent event)
   {
      //IDが無くなったので、アイテムインスタンスで比較。
      repair = StoneCutter.cutter == event.crafting.getItem();
   }

@SubscribeEventアノーテーションが付いたメソッドを持つクラスのインスタンスを、
FMLCommonHandler.instance().bus().registerメソッドで登録します。
この場合、ItemStoneCutterクラス内に実装したので、インスタンスcutterを登録しています。
添付ファイル
StoneCutter172.zip
(4.79 KiB) ダウンロード数: 181 回
StoneCutter164srg.zip
(4.45 KiB) ダウンロード数: 54 回
もじんぐしたい。。。。
アバター
A.K.
ID:996a4c3d
ラピスラズリ収集家
 
記事: 1386
登録日時: 2012年9月03日(月) 19:34

  • (PostNo.206866)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.7.2 ソース付属

投稿記事by A.K. » 2014年12月09日(火) 21:12

1.8対応版を更新。
StoneCutter1.8v1(Mod)
StoneCutter-source
1.8での変更点:
  • アイテムのテクスチャ・モデル用のJSONが必要に(assets/<modid>/models/itemフォルダに配置)
  • doesContainerItemLeaveCraftingGridメソッドが廃止に
テクスチャ・モデル用JSONファイルは以下のようにしています。
コード: 全て選択
{
    "parent": "builtin/generated",
    "textures": {
        "layer0": "items/shears"
    },
    "display": {
        "thirdperson": {
            "rotation": [ -90, 0, 0 ],
            "translation": [ 0, 1, -3 ],
            "scale": [ 0.55, 0.55, 0.55 ]
        },
        "firstperson": {
            "rotation": [ 0, -135, 25 ],
            "translation": [ 0, 4, 2 ],
            "scale": [ 1.7, 1.7, 1.7 ]
        }
    }
}


また、このJSONを登録するために、ModクラスのInitializationメソッドは次のようにしています。
コード: 全て選択
   @Mod.EventHandler
   public void load(FMLInitializationEvent event)
   {
        //1.8以降はこのメソッドでテクスチャ/モデルJSONファイルを登録。クライアント側のみの処理
        if (event.getSide().isClient()) {
            Minecraft.getMinecraft().getRenderItem().getItemModelMesher().register(cutter, 0, new ModelResourceLocation(MOD_ID + ":" + "stone_cutter", "inventory"));
        }
      //onCraftingがイベント処理に変わったので、FMLに登録。
      FMLCommonHandler.instance().bus().register(cutter);
      GameRegistry.addShapelessRecipe(new ItemStack(Blocks.stone_slab, 2, 3),
            new ItemStack(Blocks.cobblestone), new ItemStack(cutter,1,32767));
   }
もじんぐしたい。。。。
アバター
A.K.
ID:56c9adf6
ラピスラズリ収集家
 
記事: 1386
登録日時: 2012年9月03日(月) 19:34

  • (PostNo.309441)

Re: 【Forgeチュートリアル】クラフトで耐久値が減るアイテムの作り方1.2.5~1.8 ソース付属

投稿記事by ho9tocraft » 2017年10月22日(日) 14:19

1.10.2環境では1.8のものが正常に動作しないみたいです・・・。アイテム追加、クラフトまでは可能(その後、耐久度こそ減るものの、スタック数0となって、アイテムロスト)
アバター
ho9tocraft
ID:216d90b4
水から上がったとこ
 
記事: 3
登録日時: 2017年8月24日(木) 17:01


Return to 開発関連

x