提供: Minecraft Modding Wiki
2015年3月24日 (火) 16:39時点におけるModderKina (トーク | 投稿記録)による版 (ModelLoader.setCustomModelResourceLocationを利用するように変更)
移動先: 案内検索

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

Wood pickaxe.png
初心者向けのチュートリアルです。
C block.png
Blockに関係のあるチュートリアルです。

ワールド上に設置できる簡単なブロックの追加方法

ブロックの追加

注意:一度入れたMODを外すと、再び入れてもテクスチャが反映されなくなります。デバッグ時にご注意を。

ソースコード

  • SampleMod.java
package等省略

@Mod(modid = "SampleMod", name = "SampleMod", version = "1.0", dependencies = "required-after:Forge@[1.8-11.14.0.1239,)", useMetadata = true)
public class SampleMod {
    public static final String MOD_ID = "SampleMod";

    @Mod.Instance("SampleMod")
    public static SampleMod INSTANCE;

    public static Block sampleBlock;

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        sampleBlock = new SampleBlock();
        //ブロックの登録。登録文字列はMOD内で被らなければ何でも良い。

        GameRegistry.registerBlock(sampleBlock, SampleItemBlock.class, "sampleblock");

        //テクスチャ・モデル指定JSONファイル名の登録。
        if (event.getSide().isClient()) {
            //モデルJSONファイルのファイル名を登録。1IDで1つだけなら、登録名はGameRegistryでの登録名と同じものにする。
            //ItemStackのmetadataで種類を分けて描画させたい場合。登録名を予め登録する。
            ModelBakery.addVariantName(Item.getItemFromBlock(sampleBlock), MOD_ID + ":" + "sampleblock0", MOD_ID + ":" + "sampleblock1");
            //1IDで複数モデルを登録するなら、上のメソッドで登録した登録名を指定する。
            ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(sampleBlock), 0, new ModelResourceLocation(MOD_ID + ":" + "sampleblock0", "inventory"));
            ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(sampleBlock), 1, new ModelResourceLocation(MOD_ID + ":" + "sampleblock1", "inventory"));
        }
    }
}
  • SampleBlock.java
package等省略

public class SampleBlock extends Block {
    //BlockState用Property変数。今回はmetadataと同じようなPropertyIntegerを用いる。
    public static final PropertyInteger METADATA = PropertyInteger.create("meta", 0, 1);

    public SampleBlock() {
        super(Material.rock);
        setCreativeTab(CreativeTabs.tabBlock);/*クリエイティブタブの選択*/
        setUnlocalizedName("blockSample");/*システム名の設定*/
        /*以下のものは消しても結構です*/
        setHardness(1.5F);/*硬さ*/
        setResistance(1.0F);/*爆破耐性*/
        setStepSound(Block.soundTypeStone);/*ブロックの上を歩いた時の音*/
	/*setBlockUnbreakable();*//*ブロックを破壊不可に設定*/
	/*setTickRandomly(true);*//*ブロックのtick処理をランダムに。デフォルトfalse*/
	/*disableStats();*//*ブロックの統計情報を保存しない*/
        setLightOpacity(1);/*ブロックの透過係数。デフォルト0(不透過)*/
        setLightLevel(1.0F);/*明るさ 1.0F = 15*/
        //初期BlockStateの設定
        this.setDefaultState(this.blockState.getBaseState().withProperty(METADATA, 0));
    }

    //ItemStackのmetadataからIBlockStateを生成。設置時に呼ばれる。
    @Override
    public IBlockState getStateFromMeta(int meta) {
        return this.getDefaultState().withProperty(METADATA, meta);
    }

    //IBlockStateからItemStackのmetadataを生成。ドロップ時とテクスチャ・モデル参照時に呼ばれる。
    @Override
    public int getMetaFromState(IBlockState state) {
        return (Integer)state.getValue(METADATA);
    }

    //初期BlockStateの生成。
    @Override
    protected BlockState createBlockState() {
        return new BlockState(this, METADATA);
    }

    //複数種類のブロックをクリエイティブタブに登録するためのメソッド
    @Override
    public void getSubBlocks(Item itemIn, CreativeTabs tab, List list) {
        super.getSubBlocks(itemIn, tab, list);
        list.add(new ItemStack(itemIn, 1, 1));
    }

    /**返しているのは「切り抜き」「ミップマップされた」である。*/
    @Override
    @SideOnly(Side.CLIENT)
    public EnumWorldBlockLayer getBlockLayer(){
        return EnumWorldBlockLayer.CUTOUT_MIPPED;
    }

    /**
     特に変えない
     */
    @SideOnly(Side.CLIENT)
    public int getBlockColor(){
        return 0xffffff;
    }

    /**
     BlockStateで色を変えている。 パーティクルは変えないようにする。
     */
    @SideOnly(Side.CLIENT)
    public int getRenderColor(IBlockState state){
        if(checkStackRoot()) return 0xffffff;
        return ItemDye.dyeColors[(Integer) state.getValue(METADATA)];
    }

    /**
     RenderPassを利用しないのでgetRenderColorと同じで良い
     RenderPassに渡される数値はJsonで指定したtintindexで、tintindexを指定しないとこのメソッドは呼ばれない。
     @see #getRenderColor
     */
    @SideOnly(Side.CLIENT)
    public int colorMultiplier(IBlockAccess worldIn, BlockPos pos, int renderPass){
        return getRenderColor(worldIn.getBlockState(pos));
    }

    /**
     StackTraceElementを使ってパーティクル生成時にメソッドが呼ばれているかチェック
     */
    public static boolean checkStackRoot(){
        StackTraceElement[] es = new Exception().getStackTrace();
        String particle = EntityDiggingFX.class.getCanonicalName()/*"net.minecraft.client.particle.EntityDiggingFX"*/;
        return es[2].getClassName().equals(particle) || es[4].getClassName().equals(particle);
    }
}
  • SampleItemBlock.java
package等省略

public class SampleItemBlock extends ItemColored {
    /**booleanとBooleanの違いか、GameRegistoryでItemColoredそのままを利用できないので第二引数を潰す*/
    public SampleItemBlock(Block block) {
        super(block,false);
    }
}
  • sampleblock.json(BlockState用)
{
    "variants": {
        "meta=0":  { "model": "samplemod:sampleblock0" },
        "meta=1":  { "model": "samplemod:sampleblock1" }
    }
}

</source>

  • samplebase.json
{
  "elements": [
    {
      "from": [0,0,0],
      "to": [16,16,16],
      "faces": {
        "down": {
          "uv": [0,0,16,16],
          "texture": "#bottom",
          "cullface": "down"
        },
        "up": {
          "uv": [ 0,0,16,16],
          "texture": "#top",
          "cullface": "up"
        },
        "north": {
          "uv": [0,0,16,16],
          "texture": "#north",
          "cullface": "north"
        },
        "south": {
          "uv": [0,0,16,16],
          "texture": "#south",
          "cullface": "south"
        },
        "west": {
          "uv": [0,0,16,16],
          "texture": "#west",
          "cullface": "west"
        },
        "east": {
          "uv": [0,0,16,16],
          "texture": "#east",
          "cullface": "east"
        }
      }
    },
    {
      "from": [0,0,0],
      "to": [16,16,16],
      "faces": {
        "down": {
          "uv": [0,0,16,16],
          "texture": "#overlaybottom",
          "tintindex": 0,
          "cullface": "down"
        },
        "up": {
          "uv": [0,0,16,16],
          "texture": "#overlaytop",
          "tintindex": 1,
          "cullface": "up"
        },
        "north": {
          "uv": [0,0,16,16],
          "texture": "#overlaynorth",
          "tintindex": 2,
          "cullface": "north"
        },
        "south": {
          "uv": [0,0,16,16
          ],
          "texture": "#overlaysouth",
          "tintindex": 3,
          "cullface": "south"
        },
        "west": {
          "uv": [0,0,16,16],
          "texture": "#overlaywest",
          "tintindex": 4,
          "cullface": "west"
        },
        "east": {
          "uv": [0,0,16,16],
          "texture": "#overlayeast",
          "tintindex": 5,
          "cullface": "east"
        }
      }
    }
  ]
}
  • samplebase_all.json
{
  "parent": "samplemod:block/samplebase",
  "textures": {
    "particle": "#all",
    "bottom": "#all",
    "top": "#all",
    "north": "#all",
    "east": "#all",
    "south": "#all",
    "west": "#all",
    "overlaybottom": "#overlayall",
    "overlaytop": "#overlayall",
    "overlaynorth": "#overlayall",
    "overlayeast": "#overlayall",
    "overlaysouth": "#overlayall",
    "overlaywest": "#overlayall"
  }
}
  • sampleblock0.json(Block Model用)
{
    "parent": "samplemod:block/samplebase_all",
    "textures": {
        "all": "blocks/stone",
        "overlayall": "blocks/grass_side_overlay"
    }
}
  • sampleblock0.json(Item Model用)
{
    "parent": "samplemod:block/sampleblock0",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}
  • sampleblock1.json(Block Model用)
{
    "parent": "samplemod:block/samplebase_all",
    "textures": {
        "all": "blocks/dirt",
        "overlayall": "items/potion_overlay"
    }
}
  • sampleblock1.json(Item Model用)
{
    "parent": "samplemod:block/sampleblock1",
    "display": {
        "thirdperson": {
            "rotation": [ 10, -45, 170 ],
            "translation": [ 0, 1.5, -2.75 ],
            "scale": [ 0.375, 0.375, 0.375 ]
        }
    }
}

解説

SampleMod.java

同様の処理なため1.8のブロック追加を参照のこと。

SampleBlock.java

/**返しているのは「切り抜き」「ミップマップされた」である。*/
    @Override
    @SideOnly(Side.CLIENT)
    public EnumWorldBlockLayer getBlockLayer(){
        return EnumWorldBlockLayer.CUTOUT_MIPPED;
    }

    /**
     特に変えない
     */
    @SideOnly(Side.CLIENT)
    public int getBlockColor(){
        return 0xffffff;
    }

    /**
     BlockStateで色を変えている。 パーティクルは変えないようにする。
     */
    @SideOnly(Side.CLIENT)
    public int getRenderColor(IBlockState state){
        if(checkStackRoot()) return 0xffffff;
        return ItemDye.dyeColors[(Integer) state.getValue(METADATA)];
    }

    /**
     RenderPassを利用しないのでgetRenderColorと同じで良い
     RenderPassに渡される数値はJsonで指定したtintindexで、tintindexを指定しないとこのメソッドは呼ばれない。
     @see #getRenderColor
     */
    @SideOnly(Side.CLIENT)
    public int colorMultiplier(IBlockAccess worldIn, BlockPos pos, int renderPass){
        return getRenderColor(worldIn.getBlockState(pos));
    }

    /**
     StackTraceElementを使ってパーティクル生成時にメソッドが呼ばれているかチェック
     */
    public static boolean checkStackRoot(){
        StackTraceElement[] es = new Exception().getStackTrace();
        String particle = EntityDiggingFX.class.getCanonicalName()/*"net.minecraft.client.particle.EntityDiggingFX"*/;
        return es[2].getClassName().equals(particle) || es[4].getClassName().equals(particle);
    }

基本的にコメントのとおりである。

SampleItemBlock.java

ItemColorを継承しているため、特に気にすべき点はない。

sampleblock0.json(BlockState用)

BlockState別のモデルJSONファイルの指定を行う。 このファイルは、
assets\<modid>\blockstates
ディレクトリに配置する。

meta=0:BlockStateの状態指定。"meta=0,bool=false"のように書く。BlockStatesが無い場合は、"normal"とする。

model:モデル用JSONファイルのファイル名を指定。"<modid>:ファイル名"という形式。

sampleblock0.json(Block Model用)

ブロックモデル用JSONファイルである。 このファイルは、
assets\<modid>\models\block
ディレクトリに配置する。

parent:親のモデルJSONファイルを指定。"samplemod:block/samplebase_all"で全面同一テクスチャの立方体モデルを指定。

texture:テクスチャのファイルパスを指定。この場合は、"all"と"overlayall"に指定。

sampleblock0.json(Item Model用)

アイテムモデル用JSONファイルである。 このファイルは、
assets\<modid>\models\item
ディレクトリに配置する。

parent:親のモデルJSONファイルを指定。ブロックの場合は、ブロックモデルのJSONファイルを指定。

display:描画時の回転、平行移動、拡大縮小の係数を指定。コピペ安定。

thirdperson:三人称視点での指定。

他のファイルの説明は省略。