提供: Minecraft Modding Wiki
移動先: 案内検索

この記事は"Minecraft Forge 1.7.10-10.13.0.1207"を前提MODとしています。

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

土の天井に植える苗木と逆さまに生える木を追加します。

逆さまの木の追加

ソースコード

  • ReverseTree.java
package reversetree;

import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLInitializationEvent;
import cpw.mods.fml.common.event.FMLPostInitializationEvent;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.block.Block;

@Mod(modid = ReverseTree.MODID, name = ReverseTree.MODNAME, version = ReverseTree.VERSION)
public class ReverseTree {
    public static final String MODID = "ReverseTree";
    public static final String MODNAME = "ReverseTree";
    public static final String VERSION = "1.0.0";

    public static Block reverseSapling = new BlockReverseSapling().setHardness(0.0F).setStepSound(Block.soundTypeGrass).setBlockName("ReverseTree:sapling").setBlockTextureName("ReverseTree:sapling");

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        GameRegistry.registerBlock(reverseSapling, "ReverseTree:sapling");
    }

    @EventHandler
    public void init(FMLInitializationEvent event) {
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event) {
    }
}
  • BlockReverseSapling.java
package reversetree;

import net.minecraft.block.Block;
import net.minecraft.block.IGrowable;
import net.minecraft.block.material.Material;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;

import java.util.Random;

// 最小限のメソッドのみ実装。苗木を完成させるにはBlockSaplingクラスを参照のこと
public class BlockReverseSapling extends Block implements IGrowable {
    protected BlockReverseSapling(Material material) {
        super(material);
        this.setTickRandomly(true);
        float f = 0.4F;
        this.setBlockBounds(0.5F - f, 0.0F, 0.5F - f, 0.5F + f, f * 2.0F, 0.5F + f);
        this.setCreativeTab(CreativeTabs.tabDecorations);
    }

    public BlockReverseSapling() {
        this(Material.plants);
    }

    @Override
    public void updateTick(World world, int x, int y, int z, Random random) {
        if (!world.isRemote) {
            // BlockSaplingの親クラスBlockBushのupdateTickでは真下のブロックが適切か調べているが、
            // 逆さの木の苗は真上のブロックをチェックするので自前でチェックメソッドを用意する。
            //super.updateTick(world, x, y, z, random);
            checkAndDropBlock(world, x, y, z, random);

            if (world.getBlockLightValue(x, y + 1, z) >= 9 && random.nextInt(7) == 0) {
                // BlockSaplingではブロックのメタデータで木の種類を判別していたが、
                // 逆さの木は1種類だけなので判定メソッドは用意しない。
                // また、逆さの木は既存の木を発生させるメソッドが使えないので自分の好きな名前でメソッドを作って使う。
                //this.func_149879_c(world, x, y, z, random);
                growTree(world, x, y, z, random);
            }
        }
    }

    // 苗木を成長させて木を生成する
    private void growTree(World world, int x, int y, int z, Random random) {
        int l = world.getBlockMetadata(x, y, z);

        if ((l & 8) == 0) {
            world.setBlockMetadataWithNotify(x, y, z, l | 8, 4);
        } else {
            world.setBlock(x, y, z, Blocks.air, 0, 4);

            if (!(new WorldGenReverseTree(true)).generate(world, random, x, y, z)) {
                world.setBlock(x, y, z, this, 0, 4);
            }
        }
    }

    // 真上のブロックが土じゃなければ苗木をドロップさせる処理。めんどくさいので空実装
    private void checkAndDropBlock(World world, int x, int y, int z, Random random) {

    }

    // 以下骨粉用のメソッド。めんどくさいので空実装
    @Override
    public boolean func_149851_a(World p_149851_1_, int p_149851_2_, int p_149851_3_, int p_149851_4_, boolean p_149851_5_) {
        return false;
    }

    @Override
    public boolean func_149852_a(World p_149852_1_, Random p_149852_2_, int p_149852_3_, int p_149852_4_, int p_149852_5_) {
        return false;
    }

    @Override
    public void func_149853_b(World p_149853_1_, Random p_149853_2_, int p_149853_3_, int p_149853_4_, int p_149853_5_) {

    }
}
  • WorldGenReverseTree.java
package reversetree;

import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.block.BlockSapling;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import net.minecraft.world.gen.feature.WorldGenAbstractTree;
import net.minecraftforge.common.util.ForgeDirection;

// WorldGenTreesをコピペ改変
public class WorldGenReverseTree extends WorldGenAbstractTree {

    // 木の高さ。このサンプルでは固定だけどWorldGenTreesのまま利用している
    private final int minTreeHeight;

    // 原木ブロックのメタデータ。このサンプルでは固定だけどWorldGenTreesのまま利用している
    private final int metaWood;

    // 葉ブロックのメタデータ。このサンプルでは固定だけどWorldGenTreesのまま利用している
    private final int metaLeaves;

    public WorldGenReverseTree(boolean doBlockNotify) {
        this(doBlockNotify, 4, 0, 0);
    }

    public WorldGenReverseTree(boolean doBlockNotify, int minTreeHeight, int metaWood, int metaLeaves) {
        super(doBlockNotify);
        this.minTreeHeight = minTreeHeight;
        this.metaWood = metaWood;
        this.metaLeaves = metaLeaves;
    }

    public boolean generate(World world, Random random, int x, int y, int z) {
        int treeHeight = random.nextInt(3) + this.minTreeHeight;
        // 木の上下がy座標1~255の範囲に収まらなければ生成失敗(y=0に岩盤があるはずなので)
        if(y - treeHeight < 1) return false;
        if(255 < y) return false;

        for (int i = y; i > y - treeHeight; --i) {
            // デフォルトではxz平面で±1ブロック範囲を確認する(幹)
            int d = 1;

            // y座標が苗木の場所の高さの場合は苗木の位置だけを確認する
            if (i == y) {
                d = 0;
            }

            // y座標が木の高さ-2より低ければxz平面で±2ブロック範囲を確認する(葉)
            if (i < y - treeHeight + 2) {
                d = 2;
            }

            for (int j = x - d; j <= x + d; ++j) {
                for (int k = z - d; k <= z + d; ++k) {
                    if (i >= 0 && i < 256) {
                        if (!this.isReplaceable(world, j, i, k)) {
                            // 範囲内に置換対象外のブロックがあったら生成失敗
                            return false;
                        }
                    } else {
                        // 範囲がy<0または255<yに突入したら生成失敗
                        return false;
                    }
                }
            }
        }

        Block block2 = world.getBlock(x, y + 1, z);

        boolean isSoil = block2.canSustainPlant(world, x, y + 1, z, ForgeDirection.UP, (BlockSapling) Blocks.sapling);
        // 起点座標の真上が苗木を植えられるブロックでなければ生成失敗
        if(isSoil == false) return false;
        // 高さ下限を突破するなら生成失敗
        if(y - treeHeight < 0) return false;

        // 起点座標の真下のブロックを土ブロックに置換する
        block2.onPlantGrow(world, x, y + 1, z, x, y, z);

        // 葉ブロックを配置
        // 木の高さから上3ブロックに四角錘状に配置する
        for(int h = -3; h <= 0; ++h) {
            int j = (y - treeHeight) - h;
            int d = 1 - h / 2;

            for (int i = x - d; i <= x + d; ++i) {
                int j2 = i - x;

                for (int k = z - d; k <= z + d; ++k) {
                    int l2 = k - z;

                    if (Math.abs(j2) != d || Math.abs(l2) != d || random.nextInt(2) != 0 && h != 0) {
                        Block block = world.getBlock(i, j, k);

                        if (block.isAir(world, i, j, k) || block.isLeaves(world, i, j, k)) {
                            this.setBlockAndNotifyAdequately(world, i, j, k, Blocks.leaves, this.metaLeaves);
                        }
                    }
                }
            }
        }

        // 原木ブロックを配置
        for (int j = 0; j < treeHeight; ++j) {
            Block block = world.getBlock(x, y - j, z);

            if (block.isAir(world, x, y - j, z) || block.isLeaves(world, x, y - j, z)) {
                this.setBlockAndNotifyAdequately(world, x, y - j, z, Blocks.log, this.metaWood);
            }
        }

        // 蔦やカカオを生成する処理も本来の木生成にはあるがばっさりカット

        return true;
    }

}

解説

ReverseTree.java

このMODのエントリポイント。 逆さまの木の苗木ブロックを登録している。

BlockReverseSapling.java

逆さまの木の苗木ブロック。 Tickイベントが呼ばれるたびに逆さまの木を生成する判定を行っている。 なお、苗木ブロックとしては不完全なため、実際に使用する場合にはBlockSaplingを参照して必要なメソッドを実装すること。


WorldGenReverseTree.java

逆さまの木を生成する。 通常の木生成では苗木の位置から上方に向けて木が成長できる空間があるかを確認してから幹・葉をある程度ランダムに配置しているが、 逆さまの木は苗木の位置から下方に向けて空間の確認と幹・葉の配置を行っている。

その他

骨粉による成長やワールド生成時に逆さまの木の配置は実装されていない。