2014-11-21 73 views
0

我有一個可啓動的事件。我試圖從事件中獲取一個清單並將其清除,但將該清單放入Metadata存儲中的事件中創建的實體中。到目前爲止,我已經嘗試過:如何通過Runnable修改事件

注意:這是實現的類,並且是一個事件偵聽器。

@EventHandler 
public synchronized void playerDeathEvent(final EntityDeathEvent event) { 

    Bukkit.getServer().getScheduler().scheduleSyncDelayedTask(this, new Runnable() { 
     public void run() { 
      Entity p = event.getEntity(); 
      // Spawn the Firework, get the FireworkMeta. 
      Firework fw = (Firework) p.getWorld().spawnEntity(p.getLocation(), EntityType.FIREWORK); 
      FireworkMeta fwm = fw.getFireworkMeta(); 

      // Our random generator 
      Random r = new Random(); 

      // Get the type 
      int rt = r.nextInt(4) + 1; 
      Type type = Type.BALL;  
      if (rt == 1) type = Type.BALL; 
      if (rt == 2) type = Type.BALL_LARGE; 
      if (rt == 3) type = Type.BURST; 
      if (rt == 4) type = Type.CREEPER; 
      if (rt == 5) type = Type.STAR; 

      //Get our random colors 
      int r1i = r.nextInt(15) + 1; 
      int r2i = r.nextInt(15) + 1; 
      Color c1 = getColor(r1i); 
      Color c2 = getColor(r2i); 

      // Create our effect with this 
      FireworkEffect effect = FireworkEffect.builder().flicker(r.nextBoolean()).withColor(c1).withFade(c2).with(type).trail(r.nextBoolean()).build(); 

      // Then apply the effect to the meta 
      fwm.addEffect(effect); 

      // Generate some random power and set it 
      int rp = r.nextInt(2) + 1; 
      fwm.setPower(rp); 

      // Then apply this to our rocket 
      fw.setFireworkMeta(fwm); 
      // Clear drops and set the drops to be released on explosion 

      //TODO: fix problem where list is cleared before put into Metadata 
      List<ItemStack> list = new ArrayList<ItemStack>(); 
      for (ItemStack stack : event.getDrops()) 
       list.add(stack); 
      fw.setMetadata("dropItems", new FixedMetadataValue(GLDPlugin, list)); 
      event.getDrops().clear(); 
      forceDelete(event); 
     } 
    }); 

} 

public void forceDelete(EntityDeathEvent event) { 
    for (int i = 0; i < event.getDrops().size(); i++) 
     event.getDrops().remove(i); 
} 

及(就在最後一節):

  @EventHandler 
      public synchronized void onEntityDeath(EntityDeathEvent evt) 
      final EntityDeathEvent event = evt; 

      //No code in this section was changed from the code above. 

      //TODO: fix problem where list is cleared before put into Metadata 
      List<ItemStack> list = new ArrayList<ItemStack>(); 
      for (ItemStack stack : event.getDrops()) 
       list.add(stack); 
      fw.setMetadata("dropItems", new FixedMetadataValue(GLDPlugin, list)); 

     } 
    }); 
    evt = event; 
    evt.getDrops().clear(); 
    forceDelete(evt); 
} 

在頂部的一個,也不會明確event.getDrops()並會把list到實體的元數據,複製event.getDrops()。在底部示例中,它將清除event.getDrops(),但不會將list放入實體的元數據中,刪除event.getDrops()。這兩種輸出都是不可接受的,因爲這會導致產生任何物品或產生雙重物品。有任何想法嗎?

我試圖讓它這樣玩家不會掉落死亡的物品,但他們仍然從清單中移除:

編輯:對於那些你們誰更bukkit精明更好的解釋。我也需要它,因此將List<ItemStack>放入衍生的煙花的元數據中。

+0

'event.getDrops()'可能會傳遞給你'List'的一個副本' – MadProgrammer 2014-11-21 00:09:11

+0

@MadProgrammer當EntityDeathEvent'是最終的時候它正在做什麼,但是當它不是我可以清除它時。我明白,最終會使它保持不變,但我需要解決它。 – mirvine 2014-11-21 00:18:13

回答

2

你打電話:

Firework.setMetadata(String, MetadataValue); 

基本上是Metadatable.setMetadata()方法。下面是該方法的文檔:

/** 
* Sets a metadata value in the implementing object's metadata store. 
* 
* @param metadataKey A unique key to identify this metadata. 
* @param newMetadataValue The metadata value to apply. 
* @throws IllegalArgumentException If value is null, or the owning plugin 
*  is null 
*/ 
public void setMetadata(String metadataKey, MetadataValue newMetadataValue); 

因此,不能保證,設置項目的"dropItems"元數據後,將任何事情都發生了。您必須實現一個偵聽器來檢查煙花的銷燬時間,如果煙花包含此元數據,則丟棄這些項目。 MetadataValue不是NBT值。

要修改NBT值,你會從CraftBukkit通過反射直接檢索,就像這樣:

Firework fw = (Firework) p.getWorld().spawnEntity(p.getLocation(), EntityType.FIREWORK); 
java.lang.reflect.Field _entity_ = CraftEntity.class.getField("entity"); 
_entity_.setAccessible(true); 
net.minecraft.server.Entity entity = _entity_.get(fw); 
// et cetera 

簡而言之:不要。編寫自定義事件處理程序以在煙花爆炸時檢查元數據值,並相應地採取相應措施。

+0

我想你誤解了我的問題。我不認爲簡單地把標題爲「dropItems」的元數據放在物品上就可以了。我確實有一個監聽器(使用protocollib,因爲firework爆炸沒有實現),它與我的測試命令一起使用時效果很好,它基本上做了同樣的事情,但不必清除列表。我的問題是我可以清除列表並且不生成任何東西,或者不清除列表並且無法生成此插件。儘管謝謝你的迴應! – mirvine 2014-11-21 13:38:23

+0

@ itrollin98我不認爲我明白你想表達的是什麼。 – Unihedron 2014-11-21 14:21:16

+0

我正在努力使其實體不會在死亡時丟棄物品,但煙花的元數據值包含丟棄列表。 – mirvine 2014-11-21 15:28:47