2014年2月23日 星期日

Minecraft plugin fastbuild 2

這篇接續上一篇 最近花了一點時間,把fastbuild plugin本來預定的功能寫完了。

至於為什麼會相隔這麼久(16天),因為作者平常都在打東方有很多事情要忙,加上Java實在不是作者熟悉的語言,以致進度緩慢。
這次主要寫的是break的部分,原始碼比place 的listener多了一倍,因為break還涉及手中工具的耐久度設定、是否要掉下東西等,功能更複雜。
廢話不多說,來看看怎麼設計。

Event Handler

首先我們要聲請監聽票的event是BlockBreakEvent,這個event會在block被破壞的時候呼叫。 這個event會包含資訊有:玩家,被破壞的方塊。
為了要做到fastbuild的功能,我另外監看了PlayerInteractEvent,可以從這個事件中取得,玩家是碰到方塊的哪一個面。
因為plugin只能做到event based,因此這個plugin還是有一點限制,我們不能讓使用者邊敲方塊,後面一整排的方塊都開始出現裂痕,只能處理BlockBreakEvent(方塊已經爆了),再把後面的方塊設成空氣。這樣會產生一個問題:如果使用者用鏟子爆了泥土,可是後面是石頭,這樣不就可以用鏟子當超強挖礦工具?
所以這裡我們限制會一起挖的,只能是同樣類型的block。
for (int i = 0; i < n-1; i++) {
  nextBlock = block.getRelative(face);
  //currently only deal with same type block
  if (nextBlock.getType() == originType) {
    Collection drops = getDrops(tool, nextBlock);
    nextBlock.setType(Material.AIR);
    if (!isCreative) {
      // drops
      createDrops(nextBlock, drops);
      // durability
      if(!reduceDurability(tool,player)) {
        break;
      }
    }
  } else {
    break;
  }

Durability:

這部分參考[2][3],透過ItemStack的setDurability()跟getDurability()去設值,要注意的是durability值愈高表示工具愈爛,並且可以用ItemStack.getType().getMaxDurability(),來確定工具壞了,以免工具只能挖一格,卻把20格都挖掉了。

Enchantment:

我們處理的enchantment有unbreaking跟silk touch,分別影響durability跟drop items。 minecraft裡物品的item max durability值是恆定的,unbreaking只是在增加durability時加上一個機率,有一定的機不扣durability,在這裡我們複製這個設定。 可以透過ItemStack.getEnchantmentLevel(Enchantment ench); 來取得enchantment的值,非0表示有enchantment。

drops:

這裡我們呼叫 block.getDrops(ItemStack) 來產生drop items內容,用這個的好處是,它會自動判斷工具的等級高低,像用木鎬挖鐵礦,這個事件就會回傳空的內容。不過它不會處理工具有Silk touch的狀況,因些有Silk touch的時候要自己把原本的方塊傳回去。
最後再利用World.dropItemNaturally(Location, ItemStack)產生drop items即可。

Demo:

這個是用gtk-recordMyDesktop錄的,聲音好像比畫面還要慢一點,我也不知道問題在哪lol。

原始碼:

本程式公開所有原始碼,遇到bugs歡迎修改後丟pull request https://github.com/lc85301/FastBuild

參考資料:

1. Bukkit API Overview,要寫plugin不看這個不行www
http://jd.bukkit.org/
2. Minecraft Wiki enchantment:
http://minecraft.gamepedia.com/Enchanting
3. Minecraft Wiki tools
http://minecraft.gamepedia.com/Tools

沒有留言:

張貼留言