use of net.glowstone.inventory.GlowInventorySlot in project Glowstone by GlowstoneMC.
the class ItemBow method endUse.
@Override
public void endUse(GlowPlayer player, ItemStack bow) {
// Check arrows again, since plugins may have changed the inventory while the bow was drawn
Optional<GlowInventorySlot> maybeArrow = findArrow(player);
GlowInventorySlot slot = null;
ItemStack arrow = null;
final Material arrowType;
Projectile launchedProjectile = null;
boolean consumeArrow = false;
if (maybeArrow.isPresent()) {
slot = maybeArrow.get();
arrow = slot.getItem();
arrowType = arrow.getType();
consumeArrow = (player.getGameMode() != GameMode.CREATIVE);
} else if (player.getGameMode() == GameMode.CREATIVE) {
// Can fire without arrows in Creative
arrowType = Material.ARROW;
consumeArrow = false;
} else {
arrowType = Material.AIR;
}
switch(arrowType) {
case ARROW:
if (bow.containsEnchantment(Enchantment.ARROW_INFINITE)) {
consumeArrow = false;
}
launchedProjectile = player.launchProjectile(Arrow.class);
break;
case TIPPED_ARROW:
launchedProjectile = player.launchProjectile(TippedArrow.class);
GlowTippedArrow launchedTippedArrow = (GlowTippedArrow) launchedProjectile;
launchedTippedArrow.copyFrom((PotionMeta) arrow.getItemMeta());
break;
case SPECTRAL_ARROW:
launchedProjectile = player.launchProjectile(SpectralArrow.class);
break;
case AIR:
// Not in creative mode and have no arrow
break;
default:
GlowServer.logger.log(Level.SEVERE, () -> String.format("Attempt to fire %s from a bow", arrowType));
}
if (launchedProjectile != null) {
float chargeFraction = (TICKS_TO_FULLY_CHARGE - Floats.constrainToRange(player.getUsageTime(), 0.0f, TICKS_TO_FULLY_CHARGE)) / TICKS_TO_FULLY_CHARGE;
EntityShootBowEvent event = new EntityShootBowEvent(player, bow, arrow, launchedProjectile, chargeFraction);
event.setConsumeArrow(consumeArrow);
event = EventFactory.getInstance().callEvent(event);
consumeArrow = event.getConsumeArrow();
// TODO: Call for Skeleton firing too when implemented
if (event.isCancelled()) {
launchedProjectile.remove();
} else {
chargeFraction = event.getForce();
launchedProjectile = (Projectile) event.getProjectile();
if (consumeArrow) {
int amount = arrow.getAmount();
if (amount <= 1) {
arrow = InventoryUtil.createEmptyStack();
} else {
arrow.setAmount(amount - 1);
}
slot.setItem(arrow);
}
double damage = Math.max(1.0, MAX_BASE_DAMAGE + (chargeFraction == 1.0 && ThreadLocalRandom.current().nextFloat() >= 0.8 ? 1 : 0) * chargeFraction * (1 + 0.25 * bow.getEnchantmentLevel(Enchantment.ARROW_DAMAGE)));
launchedProjectile.setVelocity(player.getEyeLocation().getDirection().multiply(Math.max(5, chargeFraction * MAX_SPEED)));
if (bow.containsEnchantment(Enchantment.ARROW_FIRE)) {
// Arrow will burn as long as it's in flight, unless extinguished by water
launchedProjectile.setFireTicks(Integer.MAX_VALUE);
}
// Plugin may change projectile to non arrow.
if (launchedProjectile instanceof Arrow) {
Arrow launchedArrow = (Arrow) launchedProjectile;
launchedArrow.setDamage(damage);
launchedArrow.setKnockbackStrength(bow.getEnchantmentLevel(Enchantment.ARROW_KNOCKBACK));
// 20% crit chance
if (ThreadLocalRandom.current().nextDouble() < 0.2) {
launchedArrow.setCritical(true);
}
}
if (player.getInventory().getItemInMainHand().getType() == Material.BOW) {
player.getInventory().setItemInMainHand(InventoryUtil.damageItem(player, bow));
} else {
player.getInventory().setItemInOffHand(InventoryUtil.damageItem(player, bow));
}
}
}
player.setUsageItem(null);
player.setUsageTime(0);
}
Aggregations