我有一个可以触发事件的runnable。我试图从事件中获取列表并清除它,但将列表放在事件期间创建的实体中的元数据存储中。到目前为止,我已经尝试过:
注意:这个类在implements中,并且是一个事件监听器。
@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 :(得分: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
简而言之:不要。编写自定义事件处理程序以在fireworks爆炸时检查元数据值,并相应地对其进行操作。