1.7.10の開発講座を修正中です。このページには誤りや古い情報が含まれる可能性があります。
新しい剣・シャベル・斧・ツルハシ・クワや、適正ブロックを自由に設定できるツールを追加する。
目次
ソースコード
package tutorial.aluminiummod;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemHoe;
import net.minecraft.item.ItemSpade;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraftforge.common.util.EnumHelper;
import cpw.mods.fml.common.Mod;
import cpw.mods.fml.common.Mod.EventHandler;
import cpw.mods.fml.common.event.FMLPreInitializationEvent;
import cpw.mods.fml.common.registry.GameRegistry;
@Mod(modid = AluminiumMod.MODID, name = AluminiumMod.MODNAME, version = AluminiumMod.VERSION)
public class AluminiumMod {
public static final String MODID = "AluminiumMod";
public static final String MODNAME = "Aluminium Mod";
public static final String VERSION = "1.0.0";
public static Item aluminium;
public static Item swordAluminium;
public static Item shovelAluminium;
public static Item pickaxeAluminium;
public static Item axeAluminium;
public static Item hoeAluminium;
public static Item toolAluminium;
public static ToolMaterial ALUMINIUM;
@EventHandler
public void perInit(FMLPreInitializationEvent event) {
aluminium = new Item()
.setCreativeTab(CreativeTabs.tabMaterials)
.setUnlocalizedName("aluminium")
.setTextureName("aluminiummod:aluminium");
GameRegistry.registerItem(aluminium, "aluminium");
ALUMINIUM = EnumHelper.addToolMaterial("ALUMINIUM", 3, 1000, 7.5F, 2.5F, 10)
.setRepairItem(new ItemStack(AluminiumMod.aluminium));
swordAluminium = new ItemSword(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabCombat)
.setUnlocalizedName("swordAluminium")
.setTextureName("aluminiummod:aluminium_sword");
GameRegistry.registerItem(swordAluminium, "swordAluminium");
shovelAluminium = new ItemSpade(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabTools)
.setUnlocalizedName("shovelAluminium")
.setTextureName("aluminiummod:aluminium_shovel");
GameRegistry.registerItem(shovelAluminium, "shovelAluminium");
pickaxeAluminium = new AluminiumPickaxe(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabTools)
.setUnlocalizedName("pickaxeAluminium")
.setTextureName("aluminiummod:aluminium_pickaxe");
GameRegistry.registerItem(pickaxeAluminium, "pickaxeAluminium");
axeAluminium = new AluminiumAxe(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabTools)
.setUnlocalizedName("axeAluminium")
.setTextureName("aluminiummod:aluminium_axe");
GameRegistry.registerItem(axeAluminium, "axeAluminium");
hoeAluminium = new ItemHoe(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabTools)
.setUnlocalizedName("hoeAluminium")
.setTextureName("aluminiummod:aluminium_hoe");
GameRegistry.registerItem(hoeAluminium, "hoeAluminium");
toolAluminium = new AluminiumTool(ALUMINIUM)
.setCreativeTab(CreativeTabs.tabTools)
.setUnlocalizedName("toolAluminium")
.setTextureName("aluminiummod:aluminium_tool");
GameRegistry.registerItem(toolAluminium, "toolAluminium");
}
}
package tutorial.aluminiummod;
import net.minecraft.item.ItemPickaxe;
public class AluminiumPickaxe extends ItemPickaxe {
public AluminiumPickaxe(ToolMaterial toolMaterial) {
super(toolMaterial);
}
}
package tutorial.aluminiummod;
import net.minecraft.item.ItemAxe;
public class AluminiumAxe extends ItemAxe {
public AluminiumAxe(ToolMaterial toolMaterial) {
super(toolMaterial);
}
}
package tutorial.aluminiummod;
import java.util.Set;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
import com.google.common.collect.Sets;
public class AluminiumTool extends ItemTool {
private static final Set canHarvestBlock = Sets.newHashSet(new Block[] { Blocks.diamond_block });
public AluminiumTool(ToolMaterial toolMaterial) {
super(0.0F, toolMaterial, canHarvestBlock);
}
@Override
public boolean func_150897_b(Block block) {
return true;
}
@Override
public float func_150893_a(ItemStack itemStack, Block block) {
if (block.getMaterial() == Material.rock) {
return this.efficiencyOnProperMaterial;
}
return super.func_150893_a(itemStack, block);
}
// ここにItemHoeのプログラムを張り付ければ、クワの効果も得られる。
}
解説
ToolMaterial
ツールの性質を保持するためのenum。
ToolMaterial setRepairItem(ItemStack stack)
金床で修繕するための素材を設定するメソッド。
EnumHelper
ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability)
新しくツールマテリアルを追加するためのメソッド。
引数は順に、ツールマテリアルの名前・回収レベル・最大耐久値・採掘速度・攻撃に使用したときのダメージ倍率・エンチャントの付きやすさ。
ダイヤモンドは、3, 1561, 8.0F, 3.0F, 10
Item
public boolean func_150897_b(Block block)
引数のブロックを回収できるかを返す。
public float func_150893_a(ItemStack itemStack, Block block)
採掘速度を返す。
ItemToolでは、コンストラクタの第3引数のSetに登録されているブロックのときに適性時採掘速度を返している。
使用例
オファレンの万能ツールを追加している部分
package nahama.ofalenmod;
/*略*/
/** @author Akasata Nahama */
@Mod(modid = OfalenModCore.MODID, name = OfalenModCore.MODNAME, version = OfalenModCore.VERSION)
public class OfalenModCore {
public static final String MODID = "OfalenMod";
public static final String MODNAME = "Ofalen Mod";
public static final String VERSION = "[1.7.10]1.0.0";
/*略*/
/** 最初に行われる処理。アイテム・ブロックの追加などを行う */
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
/*略*/
// アイテムを設定するメソッドを実行
OfalenModItemCore.registerItem();
/*略*/
}
/*略*/
}
package nahama.ofalenmod.core;
/*略*/
public class OfalenModItemCore {
/*略*/
public static Item toolPerfectOfalen;
/*略*/
/**アイテムを設定する*/
public static void registerItem () {
/*略*/
toolPerfectOfalen = new OfalenPerfectTool(OfalenModMaterialCore.PERFECTT)
.setUnlocalizedName("toolPerfectOfalen")
.setTextureName("ofalenmod:ofalen_perfect_tool");
GameRegistry.registerItem(toolPerfectOfalen, "toolPerfectOfalen");
/*略*/
}
}
package nahama.ofalenmod.item.tool;
import nahama.ofalenmod.OfalenModCore;
import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
import net.minecraft.world.World;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.UseHoeEvent;
import cpw.mods.fml.common.eventhandler.Event.Result;
public class OfalenPerfectTool extends ItemTool {
public OfalenPerfectTool(ToolMaterial material) {
super(0.0F, material, null);
this.setCreativeTab(OfalenModCore.tabOfalen);
}
@Override
public boolean func_150897_b(Block block) {
return true;
}
/**採掘速度の設定*/
@Override
public float func_150893_a(ItemStack itemStack, Block block) {
//他のツールでは適正ブロックの判定をするが、ここではすべてに適正採掘速度を適用する
return this.efficiencyOnProperMaterial;
}
//クワの処理
/**アイテムが使われた(右クリック)時の処理*/
@Override
public boolean onItemUse(ItemStack itemStack, EntityPlayer entityPlayer, World world, int x, int y, int z, int side, float hitX, float hitY, float hitZ) {
//プレイヤーが編集不可ならば
if (!entityPlayer.canPlayerEdit(x, y, z, side, itemStack)) {
//falseを返す
return false;
} else {
//eventの登録
UseHoeEvent event = new UseHoeEvent(entityPlayer, itemStack, world, x, y, z);
if (MinecraftForge.EVENT_BUS.post(event)) {
return false;
}
if (event.getResult() == Result.ALLOW) {
//ダメージを与える
itemStack.damageItem(1, entityPlayer);
return true;
}
//右クリックされたブロックを取得する
Block block = world.getBlock(x, y, z);
//右クリックされたブロックの上が空気ブロックで、右クリックされたブロックが草ブロックか土ブロックならば
if (side != 0 && world.getBlock(x, y + 1, z).isAir(world, x, y + 1, z) && (block == Blocks.grass || block == Blocks.dirt)) {
Block block1 = Blocks.farmland;
//音を鳴らす
world.playSoundEffect((double)((float)x + 0.5F), (double)((float)y + 0.5F), (double)((float)z + 0.5F), block1.stepSound.getStepResourcePath(), (block1.stepSound.getVolume() + 1.0F) / 2.0F, block1.stepSound.getPitch() * 0.8F);
//クライアント側では何もせず
if (world.isRemote) {
return true;
//サーバー側では
} else {
//ブロックを置き換えて
world.setBlock(x, y, z, block1);
//ダメージを与える
itemStack.damageItem(1, entityPlayer);
return true;
}
} else {
return false;
}
}
}
//剣の処理
/**Entityを叩いたときの処理。ItemToolでは2のダメージをアイテムに与えるが、剣と同じように1与えるようにする。*/
@Override
public boolean hitEntity(ItemStack itemStack, EntityLivingBase target, EntityLivingBase player) {
itemStack.damageItem(1, player);
return true;
}
@Override
public EnumAction getItemUseAction(ItemStack itemStack) {
return EnumAction.block;
}
@Override
public int getMaxItemUseDuration(ItemStack itemStack) {
return 72000;
}
@Override
public ItemStack onItemRightClick(ItemStack itemStack, World world, EntityPlayer player) {
player.setItemInUse(itemStack, this.getMaxItemUseDuration(itemStack));
return itemStack;
}
}
Tips
ここで、実装したツールに常時エンチャントを追加する方法を紹介する。
コードは、匠Craftの匠式ツールや対地雷ツールを参考にしていただきたい。
Itemをオーバーライドしたクラスに、以下のメソッドを追加する。
//アイテムに対して毎ティック呼ばれるメソッド。
//引数は、itemStack(アイテムと個数、メタデータ等をまとめたもの),world(ワールド),entity(持っているEntity),slot(現在あるスロット番号),isHeld(手持ちかどうか)
public void onUpdate(ItemStack itemStack, World world, Entity entity, int slot, boolean isHeld) {
//エンチャントされていないかどうかを確認する。
if (itemStack.isItemEnchanted() == false) {
//エンチャントを付与する。引数はエンチャント,レベルの順に追加する。
itemStack.addEnchantment(TEnchantment.enchantmentMS, 1);
}
}
これにより、常時効果を発揮するエンチャントや手に持ってるときに効果を発揮するものなどを実装できる。
なぜか
ItemPickaxeと
ItemAxeが
minecraft.netに保護されます
「保護される」とは具体的にどのような状態なのでしょうか。
1.7.10でItemPickaxeとItemAxeはpublicクラスだと思います。
material を追加せずに剣を作ることは可能ですか?
(例)
GameRegistry.addRecipe(
new ItemStack(Item.Fire_Trident),
"PBP",
"BTB",
" B ",
'P', Items.blaze_powder
'B', Items.blaze_lod
'T', Items.trident
)
みたいな。
トライデントは1.7.10にはなく、1.13で追加されたアイテムなので、それを使用するレシピは基本的にJSONで指定することになります。
また、トライデントは剣ではなく、素材による違いがないので、ToolMaterial(1.16.5ではItemTier)を使いません。
トライデントの実装については関連するクラス(1.16.5ではTridentItemやTridentEntity)をご覧ください。
トライデントではなく剣を追加したい場合は、既存のToolMaterial(鉄やダイヤモンドなど)を利用することもできます。
ミサイルの様に敵対mobを追尾し、爆発するアイテムはどのようにプログラムを組めば良いのでしょうか?(イメージとしてはミサイル発射基を手で持った時にインベントリにあるミサイルを一消費し、ミサイルを飛ばすと追尾できる←弓矢と似たイメージ)矢にあたるミサイルのプログラムを教えて頂ければ良いです。発射基の方は弓のプログラムを借りれば一応できるとは思うので。
また、魚雷の様な物も作りたいのですが、特定のキーを押すと、プレイヤーの1ブロック下から魚雷が出るといった物も教えて下さい。
また、この様な事をある特定のキーを押すと、一斉に実行できるプログラムも出来れば…
長文、複数の要望失礼しました。
やっぱり、先程質問しました追加インベントリにある時に、特定のキーを押すとミサイル、魚雷が発射される、という様な発動条件でよろしくお願いします。
ミサイルや魚雷は、矢を参考にして
ProjectileEntity
などを継承して作るとよいでしょう。更新時にWorld.getNearestLoadedEntity
などで周囲のEntityを探して目標にし、移動速度を制御すれば追尾を実装できます。EntityとRendererの登録はMOBの追加も参考になると思います。キー割り当ての追加に関する解説記事はありませんので、オファレンMODで設定キーの追加を行っている部分を参考にしてください。
KeyInputEvent
などでキーが押されたことを判定できますが、このイベントはクライアントでしか発生しません。サーバーにパケットを送り、サーバー側でプレイヤーインベントリの操作やEntityの生成などの処理をします。パケットについての解説は、公式ドキュメント(英語)などを確認してください。キー割り当てを追加せずにアイテムの右クリックだけで処理を行うようにすると、バニラがパケットによる同期をしているので、MOD側で同期を気にせずに使えます。魚雷やミサイルについて、雪玉(
SnowballItem
とSnowballEntity
)のような実装を行えば、パケットを扱う必要はないでしょう。ここに載せたコードは1.16.5のOfficial Mappingに基づいています。バージョンによってはクラスやメソッドの名前が異なります。
丁寧にありがとうございます!
オフハンドに特定のツールAを置くとインベントリに、追加する武器B.C.D.Fのみが置けるようなインベントリを更に追加する事は出来ますか?
追加する数も制御できる用にしたいのですが…(ツールAの小型版なら追加インベントリは1個、中型なら2個、大型なら3個というように)
また、その追加インベントリに置いた時だけその武器の効果が発揮出来る様にするのも出来ますか?
長文失礼しました。
よろしければコードの例も載せて頂ければ幸いです。
アイテムを右クリックしたときに独自のインベントリを開く、という動作なら比較的容易に実装できます。「GUIの実装」とそのコメント欄をご覧ください。ツールAのNBTにインベントリ情報を保存することになるので、それを用いて他の効果を発動させるか判定できます。
また、キー割り当てを追加し、そのキーが押された時に独自のインベントリを開く、という動作も可能です。キー割り当ての追加に関する解説記事はありませんが、オファレンMODで設定キーの追加を行っている部分を参考にしてください。他にも、「Baubles」はバニラのプレイヤーインベントリにボタンを追加し、そのボタンが押されたら独自のインベントリに遷移するという実装をしています。これらの方法では、ForgeにCapability APIがあるバージョンなら、PlayerEntityにCapabilityを追加してインベントリ情報を保存することもできるでしょう。
キーイベントを盗んで、バニラのプレイヤーインベントリの代わりに独自インベントリを開く、という実装もできます。ただし、バニラのプレイヤーインベントリが開けなくなるとBaublesのような他のMODの動作に影響する場合があります。「クラス書き換えの利用」を使えば、バニラのプレイヤーインベントリを改変することもできますが、同様の理由でおすすめしません。
求める動作が明確になっているようなので、似た動作をする他のMODのコードを見るのは有効な手段だと思います。
ありがとうございます。
上のMOD開発講座のメニューにこのページが書いていないです。
見間違いだったらすいません
こちらの追加漏れですね……
追加致しました、ご報告有難うございます。