【Modding】Baubles対応アイテムを作ろう その2

2016-07-14_00-06-50.png

Moddingの道は長く険しい。
だがそれだけに、達成したときの喜びも大きい。

・Baublesスロットに置かれているアイテムを調べよう

public static boolean getBaubles(Item par1Item,EntityPlayer player)
{
if(Loader.isModLoaded("Baubles"))
{
IInventory baubles = BaublesApi.getBaubles(player);
boolean bauble = false;
if(baubles != null)
{
for(int i = 0; i < baubles.getSizeInventory(); i++)
{
ItemStack itemstack = baubles.getStackInSlot(i);
if(itemstack != null)
{
if(par1Item == baubles.getStackInSlot(i).getItem())
{
return true;
}
}
}
}
}
return false;
}

こんな感じでメソッドをちゃちゃちゃっと作ってやればあっさり調べられます。
戻り値を変えたりすればItemStackを返すことも出来ますね。

Baublesスロットはプレイヤーインベントリのように見えますが、
実はプレイヤーインベントリではありません。

プレイヤーインベントリでないということは、
当然、player.inventory.hasItem()などで調べることができません。
そういうわけでこういうメソッドを作って調べてあげる必要があります。

・動作を設定しよう
onWornTick()メソッドをオーバーライドして、そのアイテム固有の動作をさせるのもいいでしょう。
ですがonWornTick()メソッドはonUpdate()メソッドとできることがあまり変わりません。

たとえば落下ダメージを無効にしたいときは2つのパターンがありますが、
onWornTick()、onUpdate()内でfallDistanceを0にしつづける方法と、
イベントを登録してインベントリを監視し、所持している時にonPlayerFall内でイベントをキャンセルする方法です。

前者の場合、fallDistanceが0になっているのでどんなに高所から落下してもパーティクルが発生しません。
後者の場合はしっかりパーティクルが飛び散っていきます。
(たしかこういう違いがあったはず)

アイテムの数が少なければ前者の方法でも良いですが、
アイテムが増えてくると前者の方法は少々力技なので更新するときが大変です。
やはりここは後者の方法を使ってソースコードを綺麗にまとめておきたいですね。

public class ARNoFallDamageEventHooks
{
private boolean noFallDamage = false;
@SubscribeEvent//(1.6までは@ForgeSubscribe)
public void LivingUpdate(LivingUpdateEvent event)
{
if(event.entityLiving != null && event.entityLiving instanceof EntityPlayer && event.entityLiving .worldObj.isRemote)
{
EntityPlayerSP player = (EntityPlayerSP) event.entityLiving;
Falling(player);
}
}
private void Falling(EntityPlayerSP player)
{
//クリエイティブでないなら
if(!player.capabilities.isCreativeMode)
{
//飛行が許可されていないなら
if(!player.capabilities.allowFlying)
{
if(equipArmor(ARGetItemRegister("bedrockboots"), player, ARMOR_BOOTS))
{
this.noFallDamage = true;
}
else if(equipArmor(ARGetItemRegister("angelusboots"), player, ARMOR_BOOTS))
{
this.noFallDamage = true;
}
else if(hasItem(ARGetItemRegister("gravitationfeather"), player)||(hasItem(ARGetItemRegister("supergravitationfeather"), player)))
{
this.noFallDamage = true;
}
else if(hasItem(ARGetItemRegister("exchangeiginiton"), player)||(hasItem(ARGetItemRegister("ultimateexchangeiginiton"), player)))
{
this.noFallDamage = true;
}
else if(getBaubles(ARGetItemRegister("gravitationfeather"), player)||getBaubles(ARGetItemRegister("supergravitationfeather"), player))
{
this.noFallDamage = true;
}
else if(getBaubles(ARGetItemRegister("exchangeiginiton"), player)||(getBaubles(ARGetItemRegister("ultimateexchangeiginiton"), player)))
{
this.noFallDamage = true;
}
else
{
this.noFallDamage = false;
}
}
}
}
//落下時ダメージ無効化処理。LivingFallEventが実装されたバージョンのみ
@SubscribeEvent
public void onPlayerFall(LivingFallEvent event)
{
if (event.entityLiving instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer)event.entityLiving;
if (this.noFallDamage)
{
event.setCanceled(true);
}
}
}
}

スポンサーサイト

【Modding】Baubles対応アイテムを作ろう その1

2016-07-14_00-06-50.png

さてさて、ThaumCraftの前提Modとして有名になりつつある「Baubles」。

アクセサリを装備するスロットを追加する小物Modですね。

僕の作っているMod、「AdditionalRecipe」は持っていると効果を発揮するアイテムが多く、
いろんな効果を得ようとするとすぐインベントリがぱんぱんになってしまいます。

そんなある日、「ExtraUtilities」の「Flying Ring」がBaubles追加スロットの、
Ringsスロットに装備できるという今更ながらな話を聞いて、これだと思いました。

・IBaubleをimplementsする

@Optional.Interface(iface = "baubles.api.IBauble", modid = "Baubles")
public class GravitationFeather extends Item implements IBauble

当然Baublesスロットに装備するためには必要になってきます。
Optional.InterfaceアノーテションでBaublesが導入されているときだけ、
IBaublesをimplementsできる……と思うのですが、正直使い方がわかっていません。

・必要メソッドをオーバーライドする

@Override
@Optional.Method(modid = "Baubles")
public BaubleType getBaubleType(ItemStack itemstack) {
return BaubleType.AMULET;
}
@Override
@Optional.Method(modid = "Baubles")
public void onWornTick(ItemStack itemstack, EntityLivingBase player) {
}
@Override
@Optional.Method(modid = "Baubles")
public void onEquipped(ItemStack itemstack, EntityLivingBase player) {
}
@Override
@Optional.Method(modid = "Baubles")
public void onUnequipped(ItemStack itemstack, EntityLivingBase player) {
}
@Override
@Optional.Method(modid = "Baubles")
public boolean canEquip(ItemStack itemstack, EntityLivingBase player) {
return true;
}
@Override
@Optional.Method(modid = "Baubles")
public boolean canUnequip(ItemStack itemstack, EntityLivingBase player) {
return true;
}

当然BaublesAPIを利用する上では必要になってきます。

getBaubleTypeでどのスロットに装備可能か決まります。
AMULETは上段のスロット、RINGは中段の2スロット、BELTは下段のスロットです。

onWornTickは装備時に毎Tick呼び出されます。
onUpdateのBaubleスロット版だと思います。

onEquipped、OnUnequippedはそれぞれ装備されたとき、
はずされたときに一度だけ呼び出されます。

canEquip、canUnequipはまぁ見たとおりだと思います。
canUnequipはわかりますがcanEquipの使いどころがわからない。

Optional.Methodアノテーションで非導入時は、
メソッドとして認識しないようにできる……のかな?

まぁこれだけやっておけば一応は装備可能になります。
次回以降はBaublesスロットに装備したときの特殊効果を、
どう付けるかを考えていきたいと思います。

AdditionalRecipe用記事

AdditionalRecipeというModを作成したので公開。

MCver 1.6.4、Forge 9.11.1.965です。

ダウンロードはForumから…… -> 個別記事

更新履歴は続きを読むから。
続きを読む

移植作業おわりました(´・ω・`)

01_k2_08.png

Movin to the Beat,Movin to the Beat......
That's a Ridge Racer......

というわけで1.7.10版に移植できたのでめでたくリリースです!
AdditionalRecipe1.7.10 - Github
jarファイルをダウンロードしてください。

1.6.4版も安定版ができたのでリリースです。
AdditionalRecipe1.6.4 - Github
zipファイルをダウンロードしてください。



この曲はクッソ卑怯なんだよなぁ……

AdditionalRecipe進捗

2015-10-15_01.png

進捗だめです。

一応岩盤鎧は追加できました。想定してる機能の実装もできました。