この記事は"Minecraft Forge6.6.0.497以降"を前提MODとしています。 |
Enchantmentの追加
Enchantmentの追加は, 大別するとItemのaddInformationを使ってエンチャント風にアイテム情報を追加し, Itemの適当なメソッドで効果を実装するか, Enchantmentを継承で実装するかの二択になる. 前者はエンチャントそのものではないので, たとえばエンチャントブックなどは出現しないし, エンチャントテーブルでも付与できない. その代わりそのアイテム固有のエンチャントという形になる. 後者はエンチャントブックも追加され, エンチャントテーブルでも(適切な重みを設定すれば)付与できる. しかし, エンチャントの効果はハードコーディングされてる個所が多く, 継承したクラスを作るだけでは具体的なエンチャント効果を実装することはできない. そこでForgeのEventシステムを利用し, 適切な個所にフックをかけてエンチャントの効果を実装している. なお, Forge497+が必須ではない. MLでもエンチャントの追加自体は可能.
ソースコード
- EnchantmentSampleCore.java
package sample.ench; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.network.NetworkMod; import cpw.mods.fml.common.event.FMLInitializationEvent; import cpw.mods.fml.common.registry.LanguageRegistry; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.Entity; import net.minecraft.entity.passive.EntityPig; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.DamageSource; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.ForgeSubscribe; import net.minecraftforge.event.entity.player.AttackEntityEvent; @Mod( modid = "EnchantmentSample", name = "EnchantmentSample", version = "1.0.0" ) @NetworkMod( clientSideRequired = true, serverSideRequired = false ) public class EnchantmentSampleCore { public static Enchantment enchantmentSample; @Mod.Init public void init(FMLInitializationEvent event) { enchantmentSample = (new EnchantmentSample(28, 10, EnumEnchantmentType.weapon)).setName("sample"); LanguageRegistry.instance().addStringLocalization(enchantmentSample.getName(), "en_US", "Sample"); MinecraftForge.EVENT_BUS.register(this); } @ForgeSubscribe public void doEnchantmentSample(AttackEntityEvent event) { EntityPlayer player = event.entityPlayer; Entity target = event.target; ItemStack equippedItem = player.getCurrentEquippedItem(); if (equippedItem != null && EnchantmentHelper.getEnchantments(equippedItem).keySet().contains(enchantmentSample.effectId)) { if (target instanceof EntityPig) { target.attackEntityFrom(DamageSource.causePlayerDamage(player), 20); } } } }
- EnchantmentSample.java
package sample.ench; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnumEnchantmentType; public class EnchantmentSample extends Enchantment { public EnchantmentSample(int effectId, int weight, EnumEnchantmentType type) { super(effectId, weight, type); } @Override public int getMaxLevel() { return 3; } @Override public int getMinEnchantability(int par1) { return 10 + par1 * 10; } @Override public int getMaxEnchantability(int par1) { return this.getMinEnchantability(par1) + 50; } }
解説
基本的にはBlockやItem, CreativeTabと同じである. すなわち既存の基底クラスを継承し, その継承したクラスから基底クラスのコンストラクタを呼ぶのである.
EnchantmentSampleCoreクラス
MinecraftForge.EVENT_BUS.register(this);
ForgeのEventクラスを登録する.
@ForgeSubscribe public void doEnchantmentSample(AttackEntityEvent event) { }
ForgeのEventシステムを実装する. @ForgeSubscribeアノテーションが付与されたメソッドの引数に, フックをかけたいEventを指定することで適切な個所でフックされる. 今回はプレイヤーが他のEntityを攻撃したときに呼ばれる.
EnchantmentSampleクラス
public EnchantmentSample(int effectId, int weight, EnumEnchantmentType type)
コンストラクタ, 引数はエンチャントのID, エンチャントの出現比, エンチャントの種類である. 具体的な値はバニラのコードを参照. なおエンチャントIDは256制限があり, 同じIDでは競合する. そのためModに組む込む場合はエンチャントIDをコンフィグで変更できるようにすべき.
public int getMaxLevel() public int getMinEnchantability(int par1) public int getMaxEnchantability(int par1)
エンチャントの最大レベルを返すメソッド エンチャントの最小Enchantability エンチャントの最大Enchantability
実際の挙動
剣にエンチャントを何度かしているとたまにSampleというエンチャントが出現する. またエンチャントブックも登録されていて, Anvilを使って張り付けることが可能である. 実装されている効果は豚を攻撃したときに, 豚に大ダメージを与えるというもの. Enchantmentの他のメソッドをオーバーライドすることでエンチャントの付きやすさや排他性なども変更できる. またEnumEnchantmentTypeにEnumHelperで独自の定数を追加した場合はユニークエンチャントになる. エンチャント効果の実装はフックを掛けたい個所のEventを使うか, Tick処理を使う必要があることに注意.