实践1:爆炸弓/引爆剑/手榴弹
显然,Minecraft中的TNT并不能满足我们随意轰炸的欲望
- 附魔种类判断
- 攻击/被攻击事件
- 实现爆炸
我们来实现之前的引爆附魔效果,效果图如下
有关攻击的事件
- AttackEntityEvent 玩家攻击实体时触发,显然先于下面的 LivingAttackEvent 触发
- LivingAttackEvent 存活的实体被攻击时触发
- LivingSetAttackTargetEvent 生物设置其攻击目标时触发,这里的生物应该指的就是可主动攻击的生物,不包括玩家。比如僵尸看到村民开始追击。
有关弓箭的事件
- ArrowNockEvent 开始拉弓时触发
- ArrowLooseEvent 松开弓时触发,无论是否射出箭
- ProjectileImpactEvent.Arrow 弓箭落地时触发,实际是关于射出的弓箭实体的事件
可以看到,如果是引爆的近程武器,我们可以使用 AttackEntityEvent 或 LivingAttackEvent 来实现;如果是弓这个远程武器,我们可以用 LivingAttackEvent 或 ProjectileImpactEvent.Arrow 来实现。注意箭/火焰弹等远程武器不会触发 AttackEntityEvent。
爆炸
Minecraft 中的爆炸使用 World 对象的
createExplosion(Entity entityIn, x, y, z, strength, boolean isSmoking)
实现。
- entityIn 爆炸源,可以为 null,不参与爆炸伤害判定
- x,y,z double,坐标
- strength float,爆炸威力/范围,普通苦力怕为3.0,TNT为4.0或者更大一点,末影水晶为6.0,所以说。。
- isSmoking 是否破坏地形和造成伤害
此外,World 对象还有一个
newExplosion(Entity entityIn, x, y, z, strength, boolean isFlaming, boolean isSmoking)
方法,比上面的多了一个 isFlaming 参数,即爆炸是否产生火。而上面的那个方法即为 isFlaming=false 的情况。
如何判断附魔
EnchantmentHelper.getEnchantmentLevel(Enchantment enchID, ItemStack stack)
- enchID 需要检测的附魔对象
- stack 需要检测的物品,可以从player对象上拿到
- return 返回附魔等级,若无返回0
通过 AttackEntityEvent 事件实现引爆在近战武器上的效果
@SubscribeEvent
public static void onPlayerAttack(AttackEntityEvent event) {
Entity e = event.getTarget();
EntityPlayer player = event.getEntityPlayer();
if (!player.world.isRemote) {
if (EnchantmentHelper.getEnchantmentLevel(ElementLoader.ignite, player.getHeldItemMainhand()) == 1) {
player.world.createExplosion(player, e.posX, e.posY, e.posZ, 3.0f, true);
}
}
}
- player.world.isRemote 用于判断是哪个 Side,通常我们只需要一个 Side 去处理即可,比如服务器端。暂时还没有弄明白,但很多事件都是这么写的
- player.getHeldItemMainhand() 用于获取玩家主手的物品,也可以探索player的其他方法
- 这里我们设置玩家自身是爆炸源,
要不然你想让玩家炸死么
通过 ProjectileImpactEvent.Arrow 事件实现爆炸弓
@SubscribeEvent
public static void onArrowAttack(ProjectileImpactEvent.Arrow event) {
EntityArrow e = event.getArrow();
if (!e.world.isRemote) {
if (e.shootingEntity instanceof EntityPlayer) {
EntityPlayer player = (EntityPlayer) e.shootingEntity;
if (EnchantmentHelper.getEnchantmentLevel(ElementLoader.ignite, player.getHeldItemMainhand()) != 0) {
e.world.createExplosion(null, e.posX, e.posY, e.posZ, 10.0f, true);
}
}
}
}
- 基本大同小异,注意不同的对象有不同的方法和属性
通过 LivingAttackEvent 事件
一些伤害类型可以直接使用 event.getSource()
获取伤害类型并与 DamageSource 中的常量进行比较,有些没有常量的伤害类型可以使用 event.getSource().getDamageType()
来获取伤害类型名称进行比较,名称可从 DamageSource 类中查看。其中远程武器比如弓箭等被定义为间接伤害,可以用 getTrueSource()
来获取射箭者实体。
投掷物手榴弹
未完待续......