追加した鉱石ブロックをワールドに生成させて採掘出来るようにします。

自作の鉱石ブロックだけではなく、既存の鉱石ブロックなどもネザーやエンドの世界に

生成させることも出来ます。WorldGeneratorは他の物を生成させるときにも使いますが

今回は鉱石ブロックだけやります。

新しくクラスを作ります。クラス名は何でもいいですが自分がわかりやすいものにしておきましょう。コメントをしておいてもいいです。そろそろ同じjavaファイルに複数クラスがありすぎて

いる状態なのですが(-_-;)まだこのままいきます!

IworldGeneratorを継承させます。名前からわかるようにI~という名前のクラス名は

大抵インタフェースです。インタフェースを継承するときはImplementsをつけて継承します。

すると実装されていないメソッドの追加を促されますのでそれをクリックします。

IworldGeneratorのインタフェースクラスではこうなっています。

これの1個だけしかないメソッドを実装しろとeclipseは訴えているのです。

この注釈はさらっと見ておいた方がいいです。

さすがeclipseさん!自動でここまで入力してくれるので便利ですね。

なんでいきなりswitchなのか?!となるかもしれませんね。

実は条件分岐などしなくてもnewWorldGenMinable(Robby.ruby_ore.getDefaultState(),9).generate(world, random, new BlockPos(x, y, z));といれれば鉱石ブロック生成メソッドは成り立つのですが、

世界が3つあってワールドID 0がオーバーワールド(普通の世界) -1がネザー

1がエンド となっていて 世界を指定しないと普通の世界だけに生成してほしい場合でも

ネザーやエンドへ行ったときにチャンク生成するときにもこのメソッドが呼び出されて

指定回数ランダムしたりしてなんかいちいち無駄に重くなったりします。

コンソールで繰り返し処理のを見れれるようにしたらこんな風にチャンク生成が行われる

たびにこの処理が流れるのです。ちょっと必要じゃない世界ではうっとおしいですよね。

普通世界ではStoneとの置き換えで指定した鉱石が生成される仕組みとなっているのでネザーやエンドでは置き換わるstoneがないので生成されませんけどメソッドの内容はロードされて

一応生成しようとするのです。なので普通の世界以外ではロードしないように条件をつけるのです。

ちゃんと条件付きにすると違う次元へ行っても処理が行われなくなります。

プレイヤーが現在いる世界のID番号を所得して0なら~する-1なら何もしないとか

いう風にしていきます。

randomとworldとchunkXとchunkZなど以外の変数の宣言をしておきます。

int chance = 40;  forで繰り返す回数高い数字ほど発生率が高くなる。

int minHeight = 10; 最低標高 最低地層は0 岩盤が0~3くらい

int maxHeight =70;  最高標高 256以上は設定できない。

鉄鉱石が0~63で頻出範囲が2~58らしいです。

int heightDiff = maxHeight - minHeight +1; y座標の引数の変数 これは直接数値をいれるならなくてもいいです。

座標yは高低ここでは10~70(地表が64でしたっけ?)の間くらいで

座標zと座標xはチャンク内の少し内側でランダム、指定した回数そのランダムを

回す式を記述して 変数xyzにそれぞれチャンクの数値を代入させます。

ランダム生成作業を繰り返させたいのでfor文を使用します。 繰り返し回数は変数cahnceに代入させた値分です。 なんでランダムで決まった数値をたしているのかというと 指定ブロックの生成をチャンクの内側にしたいためだと思います。 たぶん(-_-;)チャンクの生成に詳しくないのですが チャンクの端っこだとランダムの数字によっては次のチャンクの端にかかる場合があるのでそうすると現在生成させようとしているブロックが まだ生成されていない次のチャンクにブロックを生成しようとして負荷がかかるみたいです。エラーにはならないみたいなのですが負荷が かかって重たくなるみたいです。

チャンクは16×16×256で構成されているみたいなのでそれで16をかけているのかな~?とかぼんやり思ってたけど変数chunkZなどににはいっている数値が座標ではなくチャンクらしいので16をかけて座標にして代入させているということらしいです。この辺の式はwikiのをまねた だけなのですが意味が分かれば後ろに足す数字はランダムで決めなくても直接数字をいれてもいいのかもしれません。

この座標のランダム数値の代入式はこの後のposを指定する時に必要になります。

newをつけて候補を出します。WorldGenMinable(IBlockState state, int blockCount)を選択します。

赤枠のコンストラクタメソッドの方ですね。これは指定したブロックをストーンブロックと置き換えるメソッドこれもコンストラクタなのかな?を呼び出すメソッドになっていると思われますたぶん(;´∀`)

シード値やら色々絡んできますが要はシード値で決まっているストーンブロックの場所に

ランダムで決まった数値の場所に指定したブロックを割り込ませているという感じです。

生成させたいブロックを指定します。後ろの数値は固めて生成させたい数値です。

その数値どうりのブロック数が固まって生成されるわけではないですが数値が大きいほど

たくさんかたまって生成されます。

なぜ後ろにgetDefaulStateをつけるのかはバニラがそうなってるからということしか

わからない(´・ω・`)IBlockStateでブロックの基本情報というかプロパティ的なもの?

が必要なんだと思う・・・。

次に後ろにさらにどこのposに割り込ませるかを指定します。

このメソッドです。

posは先ほどxyzに代入させているのでそのまま使えます。

break;をいれて次のcaseへ内容がなければ何も入れなくてもいいですがbreak;は

入れてください。break;を入れないと条件が違っても次の条件までジャンプしないで内容を

実行してしまいます。最後のcaseはbreak;をいれても入れなくてもたぶん大丈夫。

classを作っただけでは当然反映されません・・・もう慣れてきましたね?

またレジストリーに登録する作業が待っています。

preInt(FMLPreInitializationEvent event)メソッド内に登録文を記述します。

( init(FMLInitializationEvent event)でも出来ると思います。)

候補を出しながら・・

newの後は先ほど作成したクラスを指定クラスというかなんというか・・コンストラクタ?

まあ同じ名前なのでなんでもいいです(;´∀`)

後ろの引数の数値は世界に生成させるために対するウエイトらしいです。

英語で説明が書いてあります。数値が大きいほど後回しにされるので確認しやすくするために0にしてあります。自作のブロックのなかで優先順位をつけたりするならここの

数値を変えたらいいのではないでしょうか。

第一引数はIWorldGeneratorを継承したクラス名()です。ワールド生成中にコールバックされます。第二引数は ジェネレーターに割り当てられる重み。重いウェイトほどワールドジェレレーターリストの下に沈む傾向がある、つまり後で実行される。みたいなことが書かれていると

思います・・・たぶん(;´∀`)

一度チャンクが生成された場所には割り込まないのでワールドを新規作成してから

確認します。遠くまで行くのは面倒ですしね。

ランダムのところも希少性を上げるなら数値を変更して調整します。

レアすぎると確認が大変なので今は頻度が高く設定しています。

シード値によって生成場所が決まるので、同じシード値なら同じ場所に生成されています。なんど世界を作り直しても同じ場所に生成されます。ランダムの数値を変えればストーンブロックの置き換え頻度が変わるのでそこは変わります。

ちゃんと採掘できることも確認して終了です。

Silver_oreを追加してみました。

ruby_oreがあった位置にsilver_oreが・・・。位置的には変わらないけど半分ずつくらいで

なんとなく生成されているような感じですかね~?全部みてないから何とも言えませんが。

 

普通の世界の鉱石等はたぶん大体ストーンブロックの置き換えだと思いますが、

ではネザーやエンドに鉱石ブロックを生成させたいときはどうするのかと気になりますよね?

ネザーのチャンクジェネレーターのクラスではこんな風になっていてネザークォーツの

生成がどうなっているのか見れるのでこれをまねればいいのです。

ネザー鉱石?で置き換えを行っているみたいですね。

こんどは赤枠の方のコンストラクタを使用します。

case-1: ここにネザーに生成したいブロックの記述を書いて最後にbreak;を入れます。

生成させたい鉱石ブロック、固まってほしい数、置き換える元のブロック.pos

不自然な色が混じってますねw

ちゃんと生成されることを確認して終了です。

同じクラス内に記述していますので新しく登録はしていません。

違うクラスで記述した場合はGameRegistry~をしないといけません。

 

エンドではエンドストーンで置き換えを行います。

まあ・・空気ブロックかエンドストーンくらいしか主なブロックがありませんしね。

グロウストーンを空気ブロックと置き換えてみた。グロウストーンは個別にネザーに発生させるクラスが2つ存在しているのですがそれを利用してみたりして色々試したけど

うまくいかなかったのです・・・(´・ω・`)でも直に置き換えたら延々と置き換わってるし

この島周辺だけにしたいのですが~( ノД`)シクシク…。

 

~やはりおまけに苦労する~

イベントメソッドで鉱石を生成させる方法(今のところ普通の世界のみしかわからない)

まずORE_GEN_BUSの登録がまだならしておきます。

3つ全部しておくといいと思います。(init(FMLInitializationEvent event)メソッド内に)

modidを登録したクラス内にメソッドを2つ作成します。

ちょっと記述を略した感はありますがこれで完成です。

生成されていました。

 

さて・・・なぜ上記のようなメソッドの記述の仕方になるかといいますと、

バニラがそうだから・・・としか言いようがないのです(;´∀`)

またまたバニラの真似っこしただけです。

色々なクラスがあってあれですが一部だけ・・・

これはこれでストーンブロックとの置き換えなのですけどもね。

 

無機能アイテムの追加からここまでなるべく丁寧に?やってきたつもりですが・・・いかがでしょうか?現在までのコードを載せておきます。(研究中というかお試し中のコードも

含まれています。)画像ファイルやjsonファイルなども絡んでくるのでソースコードだけ

コピペしてもあれなんですが(-_-;)どうやったら全部見せられるんだろう?GitHub?

package moon.moonrose.moonrosemod;
import java.util.Random;

import com.google.common.collect.Multimap;

import net.minecraft.block.Block;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.pattern.BlockMatcher;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.ModelResourceLocation;
import net.minecraft.client.renderer.color.IItemColor;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentData;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.IMerchant;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.ai.attributes.IAttribute;
import net.minecraft.entity.ai.attributes.RangedAttribute;
import net.minecraft.entity.passive.EntityPig;
import net.minecraft.entity.passive.EntityVillager.ITradeList;
import net.minecraft.entity.passive.EntityVillager.PriceInfo;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Bootstrap;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.Item;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemAppleGold;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemEnchantedBook;
import net.minecraft.item.ItemFood;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.crafting.IRecipe;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntityChest;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.NonNullList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.village.MerchantRecipe;
import net.minecraft.village.MerchantRecipeList;
import net.minecraft.world.World;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.gen.IChunkGenerator;
import net.minecraft.world.gen.feature.WorldGenMinable;
import net.minecraft.world.gen.feature.WorldGenerator;
import net.minecraft.world.storage.loot.LootEntry;
import net.minecraft.world.storage.loot.LootEntryTable;
import net.minecraft.world.storage.loot.LootPool;
import net.minecraft.world.storage.loot.LootTableList;
import net.minecraft.world.storage.loot.RandomValueRange;
import net.minecraft.world.storage.loot.conditions.LootCondition;
import net.minecraftforge.client.model.ModelLoader;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.EnumHelper;
import net.minecraftforge.event.LootTableLoadEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.terraingen.OreGenEvent;
import net.minecraftforge.event.terraingen.TerrainGen;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.fml.common.IFuelHandler;
import net.minecraftforge.fml.common.IWorldGenerator;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import net.minecraftforge.fml.common.registry.ForgeRegistries;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.oredict.OreDictionary;
import net.minecraftforge.oredict.ShapedOreRecipe;
	@Mod.EventBusSubscriber
	@Mod(modid = Robby.MODID,name = Robby.NAME,version = Robby.VERSION,acceptedMinecraftVersions = Robby.MCVER)
public class Robby
{
    public static final String MODID = "moonrosemod";
    public static final String NAME = "MoonroseMod";
    public static final String VERSION = "1.0";
    public static final String MCVER = "1.12";

    public static Item ruby;
    public static Item amethyst;
    public static Item greenapple;
    public static Item silver_ingot;
    public static Item silverapple;
    public static Item platinumapple;
    public static Item platinum_ingot;
    public static Block ruby_ore;
    public static Block silver_ore;
    public static Block silver_block;
    public static Block platinum_block;
    public static Block platinum_ore;
    public static Block greenglow;
    public static Block magiastone;
    public static Item rubyrod;
    public static Item rubysword;

    @EventHandler
    public void init(FMLInitializationEvent event)
    {
        // some example code
        System.out.println("DIRT BLOCK >> "+Blocks.DIRT.getUnlocalizedName());
        
        //The core Forge EventBusses. Forgeの全てのイベントはこれらで発生します。
        //すべてのリスナーを登録するには、これを使用する必要があります。
        //これは、古いバージョンのForgeのすべてのregister Handler()関数を置き換えます。
        
        //地形イベントに必要
        MinecraftForge.TERRAIN_GEN_BUS.register(this);
        //鉱石イベントに必要
        MinecraftForge.ORE_GEN_BUS.register(this);
        //他のイベントすべてに必要
        MinecraftForge.EVENT_BUS.register(this);
      
           
        
        //色を変えるメソッド
        Minecraft.getMinecraft().getItemColors().registerItemColorHandler(new IItemColor()
        {
        	@Override
			public int getColorFromItemstack(ItemStack stack, int tintIndex)
        	{
				return 0xFF00CB;
        	}
        }
        	,amethyst);
    }
    
    //ログイン時チャットログにメッセージを流すイベントメソッド
   @SubscribeEvent
    public void  playerLogIn(PlayerEvent.PlayerLoggedInEvent event)
    {
    	String pla = event.player.getName();
    	BlockPos pos = event.player.getPosition();
    	event.player.sendMessage(new TextComponentString("test"));
    	event.player.sendMessage(new TextComponentString("日本語もおkなはず " + event.player.getName() + "!"));
    	event.player.sendMessage(new TextComponentString(pla));
    	event.player.sendMessage(new TextComponentString("" + pos));
    	event.player.sendMessage(new TextComponentString("" +  event.player));
    }

   //既存の葉ブロックにgreenappleをドロップさせるイベントメソッド
   	private static Random rand = new Random();
	private static int chance = 10;
	@SubscribeEvent
	public  void leaveDrop(BlockEvent.HarvestDropsEvent event)
	{

		   if(event.getState() == Blocks.LEAVES)

		   {
			   event.getDrops();
		   }

		   if (rand.nextInt(100) < chance)
		   {
		   		event.getDrops().add(new ItemStack(greenapple,5,0));
		   }
	}
	
	//モブ(豚)を倒したときにgreenappleをドロップさせるイベントメソッド
	@SubscribeEvent
		public  void mobDrop(LivingDeathEvent event)
	{

		 if(event.getEntityLiving() instanceof EntityPig)
		 {

			if(event.getEntityLiving().isServerWorld())
			 {

				event.getEntityLiving().dropItem(greenapple,3);
				event.getEntityLiving().dropItemWithOffset(greenapple,1,0);
				event.getEntityLiving().entityDropItem(new ItemStack(greenapple,1,0), 0);

			 }
		 	}
	}
	
	//鉱石ブロックを世界に生成させるイベントメソッド
	@SubscribeEvent
	public void generateOrePre(OreGenEvent.Pre event)
	{
		WorldGenerator platinumOreGen = new WorldGenMinable(platinum_ore.getDefaultState(), 9);
		if(TerrainGen.generateOre(event.getWorld(), event.getRand(),platinumOreGen,event.getPos(),
				OreGenEvent.GenerateMinable.EventType.CUSTOM))genStandardOre(event.getWorld(), event.getPos(), 40, platinumOreGen, 10, 70, event.getRand());
	}

    private void genStandardOre(World world, BlockPos pos, int count, WorldGenerator  platinumOreGen, int minY, int maxY,Random rand) 
    {
    	for(int i = 0;  i< count; ++i){
			BlockPos blockpos = pos.add(rand.nextInt(16), rand.nextInt(maxY - minY) + minY, rand.nextInt(16));
			platinumOreGen.generate(world, rand, blockpos);
		}
		
	}

    //レシピの登録イベントメソッド
    @SubscribeEvent
    public static void registerRecipes(RegistryEvent.Register event)
    {
    	OreDictionary.registerOre("apples",Items.APPLE);
        OreDictionary.registerOre("apples",greenapple);
    	        event.getRegistry().registerAll
    	        (
    	        		new ShapedOreRecipe(new ResourceLocation(MODID, "rubyrod"), rubyrod,
    	                        "  X",
    	                        " # ",
    	                        "#  ",
    	                        'X', ruby,
    	                        '#', platinum_ingot     
    	                ).setRegistryName(MODID, "rubyrod"),
    	        
    	        		(new ShapedOreRecipe(new ResourceLocation(MODID, "rubysword"), new ItemStack(rubysword), 
    	        		new Object[]
    	        				{true, new Object[]
    	        						{
    	        						"  Y",
    	        						"XY ",
    	        						"ZX ", 
    	        						'Z', "apples" ,
    	        						'Y', "logWood",
    	        						'X',"treeLeaves"
    	        						}
    	        				})).setRegistryName(MODID, "rubysword"),
    	        		new ShapedOreRecipe(ReN("ame"),new ItemStack(amethyst),
    	        		new Object[]
    	        				{
    	        						"  #",
    	     	                        " # ",
    	     	                        "#  ",	
    	     	                        '#' , ruby   
    	        				}
    	         
    	                ).setRegistryName(ReN("ame"))
    	        	);
    }
    
    private static ResourceLocation ReN(String string)
    {
		
		return new ResourceLocation("moonrosemod:" + string);
	}

	//既存の宝箱(スポーンボーナスチェスト)のルートテーブルに追加するイベントメソッド
    @SubscribeEvent
	 public void lootLoad(LootTableLoadEvent evt)
    {
	     if (evt.getName().toString().equals("minecraft:chests/spawn_bonus_chest"))
	     {
	        
	    	LootEntry entry = new LootEntryTable(new ResourceLocation("moonrosemod:inject/test2"), 10, 3, new LootCondition[0], "moonrosemod_inject_test2");
	     	LootPool pool = new LootPool(new LootEntry[] {entry},new LootCondition[0] , new RandomValueRange(3), new RandomValueRange(1, 3), "moonrosemod_inject_test2"); 
	    	 evt.getTable().addPool(pool);
	     }
	 }
    
	@EventHandler
    public void preInt(FMLPreInitializationEvent event)
    {
    	String variantIn ="inventory" ;

    	ruby = new Item()
    			.setUnlocalizedName("ruby")
    			.setMaxStackSize(64)
    			.setCreativeTab(Tab.MOONROSE)
    			.setRegistryName(new ResourceLocation(MODID,"ruby"));

    	ForgeRegistries.ITEMS.register(ruby);
    	ModelLoader.setCustomModelResourceLocation(ruby, 0, new ModelResourceLocation(ruby.getRegistryName(),"inventory"));

    	amethyst = new Item()
    			.setUnlocalizedName("amethyst")
    			.setMaxStackSize(64)
    			.setCreativeTab(CreativeTabs.MISC)

    			.setRegistryName(new ResourceLocation(MODID,"amethyst"));

    	ForgeRegistries.ITEMS.register(amethyst);
    	ModelLoader.setCustomModelResourceLocation(amethyst, 0, new ModelResourceLocation(MODID + ":amethyst","inventory"));

    		greenapple = new ItemFood(10,10,false)
    				.setAlwaysEdible()
    				.setCreativeTab(CreativeTabs.FOOD)
    				.setMaxStackSize(64)
    				.setUnlocalizedName("greenapple")
    				.setRegistryName(new ResourceLocation(MODID,"greenapple"));
    		ForgeRegistries.ITEMS.register(greenapple);
    		ModelLoader.setCustomModelResourceLocation(greenapple, 0, new ModelResourceLocation(MODID + ":greenapple","inventory"));

    		silverapple = new SilverApple(20,10,false)
    				.setAlwaysEdible()
    				.setCreativeTab(CreativeTabs.FOOD)
    				.setMaxStackSize(64)
    				.setUnlocalizedName("silverapple")
    				.setRegistryName(new ResourceLocation(MODID,"silverapple"));
    		ForgeRegistries.ITEMS.register(silverapple);
    		ModelLoader.setCustomModelResourceLocation(silverapple, 0, new ModelResourceLocation(MODID + ":silverapple","inventory"));
    		ModelLoader.setCustomModelResourceLocation(silverapple, 1, new ModelResourceLocation(MODID + ":silverapple","inventory"));

    		silver_ingot = new Item()
    				.setUnlocalizedName("silver_ingot")
        			.setMaxStackSize(64)
        			.setCreativeTab(CreativeTabs.MISC)
        			.setRegistryName(new ResourceLocation(MODID,"silver_ingot"));

        	ForgeRegistries.ITEMS.register(silver_ingot);
        	ModelLoader.setCustomModelResourceLocation(silver_ingot, 0, new ModelResourceLocation(MODID + ":silver_ingot",variantIn));

        	ruby_ore = new Block(Material.ROCK)
        			.setUnlocalizedName("ruby_ore")
        			.setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
        			.setHardness(1.5F)
        			.setResistance(1.0F)
        			.setRegistryName(new ResourceLocation(MODID, "ruby_ore"));

        	ForgeRegistries.ITEMS.register(new ItemBlock(ruby_ore).setRegistryName(ruby_ore.getRegistryName()));
        	ForgeRegistries.BLOCKS.register(ruby_ore);
        	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(ruby_ore), 0, new ModelResourceLocation(MODID + ":ruby_ore", variantIn));

        	silver_ore = new Block(Material.ROCK)
        			.setUnlocalizedName("silver_ore")
        			.setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
        			.setHardness(1.5F)
        			.setResistance(1.0F)
        			.setRegistryName(new ResourceLocation(MODID, "silver_ore"));

        	ForgeRegistries.ITEMS.register(new ItemBlock(silver_ore).setRegistryName(silver_ore.getRegistryName()));
        	ForgeRegistries.BLOCKS.register(silver_ore);
        	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(silver_ore), 0, new ModelResourceLocation(MODID + ":silver_ore", variantIn));

        	silver_block = new Block(Material.ROCK)
        			.setUnlocalizedName("silver_block")
        			.setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
        			.setHardness(1.5F)
        			.setResistance(1.0F)
        			.setRegistryName(new ResourceLocation(MODID, "silver_block"));

        	ForgeRegistries.ITEMS.register(new ItemBlock(silver_block).setRegistryName(silver_block.getRegistryName()));
        	ForgeRegistries.BLOCKS.register(silver_block);
        	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(silver_block), 0, new ModelResourceLocation(MODID + ":silver_block", variantIn));

        	platinum_ingot = new Item()
    				.setUnlocalizedName("platinum_ingot")
        			.setMaxStackSize(64)
        			.setCreativeTab(CreativeTabs.MISC)
        			.setRegistryName(new ResourceLocation(MODID,"platinum_ingot"));

        	ForgeRegistries.ITEMS.register(platinum_ingot);
        	ModelLoader.setCustomModelResourceLocation(platinum_ingot, 0, new ModelResourceLocation(MODID + ":platinum_ingot",variantIn));

        	platinumapple = new ApplePlatinum(20,10,false)
    				.setAlwaysEdible()
    				.setCreativeTab(CreativeTabs.FOOD)
    				.setMaxStackSize(64)
    				.setUnlocalizedName("platinumapple")
    				.setRegistryName(new ResourceLocation(MODID,"platinumapple"));
    		ForgeRegistries.ITEMS.register(platinumapple);
    		ModelLoader.setCustomModelResourceLocation(platinumapple, 0, new ModelResourceLocation(MODID + ":platinumapple","inventory"));
    		ModelLoader.setCustomModelResourceLocation(platinumapple, 1, new ModelResourceLocation(MODID + ":platinumapple","inventory"));

    		platinum_ore = new Block(Material.ROCK)
    				.setUnlocalizedName("platinum_ore")
        			.setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
        			.setHardness(1.5F)
        			.setResistance(1.0F)
        			.setRegistryName(new ResourceLocation(MODID, "platinum_ore"));

        	ForgeRegistries.ITEMS.register(new ItemBlock(platinum_ore).setRegistryName(platinum_ore.getRegistryName()));
        	ForgeRegistries.BLOCKS.register(platinum_ore);
        	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(platinum_ore), 0, new ModelResourceLocation(MODID + ":platinum_ore", variantIn));


    		platinum_block = new Block(Material.ROCK)
        			.setUnlocalizedName("platinum_block")
        			.setCreativeTab(CreativeTabs.BUILDING_BLOCKS)
        			.setHardness(1.5F)
        			.setResistance(1.0F)
        			.setRegistryName(new ResourceLocation(MODID, "platinum_block"));

        	ForgeRegistries.ITEMS.register(new ItemBlock(platinum_block).setRegistryName(platinum_block.getRegistryName()));
        	ForgeRegistries.BLOCKS.register(platinum_block);
        	ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(platinum_block), 0, new ModelResourceLocation(MODID + ":platinum_block", variantIn));
        	
        	final ToolMaterial RUBY = EnumHelper.addToolMaterial("ruby",0,1500,8.0F,20F,10);
        	rubysword = new ItemSword(RUBY)
        			.setUnlocalizedName("rubysword")
        			.setCreativeTab(CreativeTabs.COMBAT)
        			.setRegistryName(new ResourceLocation(MODID,"rubysword"));
        	ForgeRegistries.ITEMS.register(rubysword);
        	ModelLoader.setCustomModelResourceLocation(rubysword, 0, new ModelResourceLocation(rubysword.getRegistryName(), variantIn));

        	rubyrod = new Rubyrod();
        	ForgeRegistries.ITEMS.register(rubyrod);
        	ModelLoader.setCustomModelResourceLocation(rubyrod, 0, new ModelResourceLocation(MODID + ":rubyrod",variantIn));
        	
        	//ルートテーブルの追加登録
        	LootTableList.register(new ResourceLocation("moonrosemod:chests/test")); 
        	LootTableList.register(new ResourceLocation("moonrosemod:inject/test2"));    

        	//精錬レシピの追加の登録
        	GameRegistry.addSmelting(ruby_ore, new ItemStack(ruby), 10.0F);
        	GameRegistry.addSmelting(silver_ore, new ItemStack(silver_ingot), 10.0F);
        	GameRegistry.addSmelting(platinum_ore, new ItemStack(platinum_ingot), 10.0F);
        	//定形レシピの登録
        	GameRegistry.addShapedRecipe(new ResourceLocation("silver_block"), new ResourceLocation(MODID), new ItemStack(Item.getItemFromBlock(silver_block),2),
        			new Object[]
        					{
        							"XXX",
        	                        "XXX",
        	                        "XXX",
        	                    
        	                        Character.valueOf('X'),silver_ingot
        	                    
        					});
        	OreDictionary.registerOre("apples",Items.APPLE);
            OreDictionary.registerOre("apples",greenapple);
        	GameRegistry.addShapedRecipe(new ResourceLocation("platinum_block"), new ResourceLocation(MODID), new ItemStack(platinum_block),
        			new Object[]
        					{
        							"XXX",
        	                        "XXX",
        	                        "XXX",

        	                        'X', platinum_ingot
        	        	                    
        					});
        	//燃料追加の登録
        	GameRegistry.registerFuelHandler(new IFuelHandler()
        	{
				@Override
				public int getBurnTime(ItemStack fuel)
				{
					if(fuel.getItem() == ruby)
					{
						return 200;
					}
						return 0;
				}
			});
        	GameRegistry.registerFuelHandler(new IFuelHandler()
        	{
				@Override
				public int getBurnTime(ItemStack fuel)
				{
					if(fuel.getItem() == Item.getItemFromBlock(silver_ore))
					{
						return 200;
					}
						return 0;
				}
			});
        	
        	//村人の取引リスト追加の登録
        	ForgeRegistries.VILLAGER_PROFESSIONS.getValue(new ResourceLocation("minecraft:nitwit")).getCareer(0)
        		.addTrade(1, new VellagerTreadeList())
        		.addTrade(1, new TreadeList3(rubyrod, new PriceInfo(5, 10)))
        		.addTrade(2, new TreadeList())
        		.addTrade(3, new TreadeList2( ))
        		.addTrade(4, new TreadeList3(Items.DIAMOND_SWORD, new PriceInfo(3, 6)));
        	
        	//鉱石を生成するジェネレータークラスの登録
        	GameRegistry.registerWorldGenerator(new WorldGenerate1(), 0);
        	
    }

}

//鉱石を世界に生成させるクラス
class WorldGenerate1  implements IWorldGenerator
{

		@Override
		public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator,IChunkProvider chunkProvider)
		{
			
			switch(world.provider.getDimension())
			{
			case 0:
				int chance = 40;
				int minHeight =10;
				int maxHeight =70;
				int heightDiff = maxHeight - minHeight +1;
			
				for(int i = 0; i < chance; i ++)
				{
					int x =chunkX * 16 + random.nextInt(16);
					int y = minHeight + random.nextInt(heightDiff);
					int z = chunkZ * 16 + random.nextInt(16);
					
					new WorldGenMinable(Robby.ruby_ore.getDefaultState(),9).generate(world, random, new BlockPos(x, y, z));
					new WorldGenMinable(Robby.silver_ore.getDefaultState(),9).generate(world, random, new BlockPos(x, y, z));
				}
				break;
			case -1:
				int chance2 = 40;
				int minHeight2 =10;
				int maxHeight2 =70;
				int heightDiff2 = maxHeight2 - minHeight2 +1;
				for(int i = 0; i < chance2; i ++)
				{
					int x =chunkX * 16 + random.nextInt(16);
					int y = minHeight2 + random.nextInt(heightDiff2);
					int z = chunkZ * 16 + random.nextInt(16);
					
					new WorldGenMinable(Robby.ruby_ore.getDefaultState(), 9, BlockMatcher.forBlock(Blocks.NETHERRACK)).generate(world, random, new BlockPos(x, y, z));
					
				}
				
				break;
			case 1:
				int chance3 = 40;
				int minHeight3 =10;
				int maxHeight3 =70;
				int heightDiff3 = maxHeight3 - minHeight3 +1;
				for(int i = 0; i < chance3; i ++)
				{
					int x =chunkX * 16 + random.nextInt(16);
					int y = minHeight3 + random.nextInt(heightDiff3);
					int z = chunkZ * 16 + random.nextInt(16);
					
					new WorldGenMinable(Robby.ruby_ore.getDefaultState(), 9, BlockMatcher.forBlock(Blocks.END_STONE)).generate(world, random, new BlockPos(x, y, z));	
				
				}
				int x =chunkX * 32 + random.nextInt(16);
				int y = 70 + random.nextInt(10);
				int z = chunkZ * 32 + random.nextInt(16);
				for(int i = 0; i < 5; i ++)
				{
				new WorldGenMinable(Blocks.GLOWSTONE.getDefaultState(), 9, BlockMatcher.forBlock(Blocks.AIR)).generate(world, random, new BlockPos(x, y, z));
				}
			}
		}
}

//村人の取引リストを追加するクラス	
class VellagerTreadeList implements ITradeList
{
	@Override
	public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random)
	{
		recipeList.add(new MerchantRecipe(new ItemStack(Items.GOLD_INGOT), new ItemStack(Robby.ruby,2)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.ruby,2), new ItemStack(Items.DIAMOND)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.ruby), new ItemStack(Items.EMERALD)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.ruby), new ItemStack(Items.EMERALD),new ItemStack(Items.DIAMOND)));
		recipeList.add(new MerchantRecipe(new ItemStack(Items.GOLD_INGOT), new ItemStack(Robby.ruby,2),new ItemStack(Items.GOLDEN_APPLE,1,1)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.platinumapple,1,1), new ItemStack(Robby.platinum_block)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.platinumapple,2,0), new ItemStack(Item.getItemFromBlock(Robby.platinum_block))));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.platinumapple,1,1), new ItemStack(Blocks.GOLD_BLOCK)));
	}
}


//村人の取引リストを追加するクラス		
class TreadeList implements ITradeList
{
	@Override
	public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random)
	{
		recipeList.add(new MerchantRecipe(new ItemStack(Items.APPLE), new ItemStack(Items.GOLD_INGOT,8),new ItemStack(Items.GOLDEN_APPLE)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.ruby,5), new ItemStack(Robby.silverapple)));
		recipeList.add(new MerchantRecipe(new ItemStack(Robby.ruby,10), new ItemStack(Robby.silverapple,1,1)));
		
	}
}

//エンチャント付きの本をリストに追加(エンチャントはランダム)本とルビー(個数は下の式の結果で決まる)とエンチャント付本と交換
class TreadeList2 implements ITradeList
{
		@Override
	   public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random)
       {
           Enchantment enchantment = (Enchantment)Enchantment.REGISTRY.getRandomObject(random);
           int i = MathHelper.getInt(random, enchantment.getMinLevel(), enchantment.getMaxLevel());
           ItemStack itemstack = ItemEnchantedBook.getEnchantedItemStack(new EnchantmentData(enchantment, i));
           int j = 2 + random.nextInt(5 + i * 10) + 3 * i;

           if (enchantment.isTreasureEnchantment())
           {
               j *= 2;
           }

           if (j > 64)
           {
               j = 64;
           }

           recipeList.add(new MerchantRecipe(new ItemStack(Items.BOOK), new ItemStack(Robby.ruby, j), itemstack));
       }

}

//エンチャント付きの武器や防具などを取引リストに追加する。必要なルビーの数が設定の数値の中でランダム 指定のアイテムにランダムでエンチャント
class TreadeList3 implements ITradeList
{
	public ItemStack enchantedItemStack;
	public PriceInfo priceInfo;
	
	public TreadeList3(Item p_i45814_1_, PriceInfo p_i45814_2_)
	{
		 this.enchantedItemStack = new ItemStack(p_i45814_1_);
         this.priceInfo = p_i45814_2_;
	}
	@Override
	public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random)
	{
		 int i = 1;

         if (this.priceInfo != null)
         {
             i = this.priceInfo.getPrice(random);
         }

         ItemStack itemstack = new ItemStack(Robby.ruby, i, 0);
         ItemStack itemstack1 = EnchantmentHelper.addRandomEnchantment
        		 (random, new ItemStack(this.enchantedItemStack.getItem(), 1, this.enchantedItemStack.getMetadata()), 5 + random.nextInt(100), false);
         recipeList.add(new MerchantRecipe(itemstack, itemstack1));
		
	}
	
}

//エンチャント付き金のリンゴっぽいものを作る、白金のリンゴクラス
class ApplePlatinum extends ItemAppleGold
{

	public ApplePlatinum(int amount, float saturation, boolean isWolfFood)
	{
		super(amount, saturation, isWolfFood);
		this.setHasSubtypes(true);
	}
	  public EnumRarity getRarity(ItemStack stack)
	    {
	        return stack.getMetadata() == 0 ? EnumRarity.COMMON : EnumRarity.COMMON;
	    }
	  
	  @SideOnly(Side.CLIENT)
	    public boolean hasEffect(ItemStack stack)
	    {
	        return super.hasEffect(stack) || stack.getMetadata() > 0;
	    }
	  protected void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player)
	    {
	        if (!worldIn.isRemote)
	        {
	            if (stack.getMetadata() > 0)
	            {
	                player.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, 400, 1));
	                player.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 6000, 0));
	                player.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, 6000, 0));
	                player.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, 2400, 3));
	            }
	            else
	            {
	                player.addPotionEffect(new PotionEffect(MobEffects.REGENERATION, 100, 1));
	                player.addPotionEffect(new PotionEffect(MobEffects.ABSORPTION, 2400, 0));
	            }
	        }
	    }
	  public void getSubItems(CreativeTabs tab, NonNullList items)
	    {
	        if (this.isInCreativeTab(tab))
	        {
	            items.add(new ItemStack(this));
	            items.add(new ItemStack(this, 1, 1));
	        }
	    }
}
	
//銀のリンゴクラス	
class SilverApple extends ItemFood
{
		public SilverApple(int amount, float saturation, boolean isWolfFood)
		{
			super(20, 10, false);

		}
		@SideOnly(Side.CLIENT)
		 public boolean hasEffect(ItemStack stack)
		  {
		      return super.hasEffect(stack) || stack.getMetadata() > 0;
		  }
		  
		@SideOnly(Side.CLIENT)
		public void onFoodEaten(ItemStack stack, World worldIn, EntityPlayer player)
		{

           if(!worldIn.isRemote)
           {
        	   if (stack.getMetadata() > 0)
        	   {
        		   player.addPotionEffect(new PotionEffect(Potion.getPotionById(10), 1200, 10));	   
        		   player.sendMessage(new TextComponentString("リジェネ効果(60秒)" ));
        	   }
        	   else
        	   {
        		   player.addPotionEffect(new PotionEffect(Potion.getPotionById(11), 1200, 10));	   
        		   player.sendMessage(new TextComponentString("防御アップ(30秒)" ));  
        	   }  
	   		}
		}
		  public void getSubItems(CreativeTabs tab, NonNullList items)
		  {
		        if (this.isInCreativeTab(tab))
		        {
		            items.add(new ItemStack(this));
		            items.add(new ItemStack(this, 1, 1));
		        }
		  }

}

//クリエイティブタブを追加するクラス
abstract class Tab extends CreativeTabs
{

	public Tab(String label)
	{
		super("moonrose_tab");
	}

	 public static final CreativeTabs MOONROSE = new CreativeTabs(getNextID(), "moonrose_tab")
	 {
		 @SideOnly(Side.CLIENT)
		 public ItemStack getTabIconItem()
		{
			 return  new ItemStack(Item.getItemFromBlock(Robby.ruby_ore));
		}
	 };
}


class Rubyrod extends ItemSword
{
	public static final IAttribute ATTACK_SPEED2 = (new RangedAttribute((IAttribute)null, "generic.attackSpeed", 2.0D, 0.0D, 600.0D)).setShouldWatch(true);
	private final float attackDamage;
	 protected float attackSpeed;
	static ToolMaterial material = EnumHelper.addToolMaterial("ruby",5,1500,10F,30F,30);
    public Rubyrod()
    {
        super(material);
        this.setRegistryName("rubyrod");
        this.setCreativeTab(Tab.MOONROSE);
        this.setUnlocalizedName("rubyrod");
        this.attackSpeed = 10.0F;
        this.attackDamage = 3.0F + material.getDamageVsEntity();
    }
   
    public Multimap getItemAttributeModifiers(EntityEquipmentSlot equipmentSlot)
    {
        Multimap multimap = super.getItemAttributeModifiers(equipmentSlot);

        if (equipmentSlot == EntityEquipmentSlot.MAINHAND)
        {
            multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", (double)this.attackDamage, 0));
            multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool modifier" ,(double)this.attackSpeed , 0));
            //multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), new AttributeModifier(ATTACK_SPEED_MODIFIER, "Tool modifier", (double)this.attackSpeed, 0));
        }

        return multimap;
    }

    @Override
    public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand,
            EnumFacing facing, float hitX, float hitY, float hitZ) {
        worldIn.setBlockState(pos.offset(facing), Blocks.CHEST.getDefaultState());
        if (worldIn.getTileEntity(pos.offset(facing)) instanceof TileEntityChest) {
            ((TileEntityChest) worldIn.getTileEntity(pos.offset(facing))).setLootTable(
                    new ResourceLocation("moonrosemod:chests/test"), player.getRNG().nextLong());
        }
        return super.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
    }
}


class Apples extends ItemFood
{
		public Apples(int amount, float saturation, boolean isWolfFood)
		{
			super(20, 10, false);

		}
		
		
		  public void getSubItems(CreativeTabs tab, NonNullList items)
		  {
		        if (this.isInCreativeTab(tab))
		        {
		            items.add(new ItemStack(getItemById(260)));
		            items.add(new ItemStack(this, 1, 1));
		        }
		  }
}

class MoonBlock extends Block
{

	public MoonBlock(Material blockMaterialIn, MapColor blockMapColorIn) {
		super(blockMaterialIn, blockMapColorIn);
		
	}
	

}