Add explosive bows & improve source code (#7)
* Add explosive bow item * Fix buggy inventory management code * Use crossbow instead of bow to support multishot * Add weapon item builder * Make the explosive crossbow shoot faster & more
This commit is contained in:
parent
440dc4091c
commit
17b34d3bdf
|
@ -4,17 +4,16 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import pw.kaboom.weapons.commands.CommandWeapons;
|
||||
import pw.kaboom.weapons.modules.player.PlayerReceiveWeapon;
|
||||
import pw.kaboom.weapons.modules.player.PlayerUseWeapon;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponArcher;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponArmageddon;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponBlobinator;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponExplosiveCrossbow;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponGrenade;
|
||||
import pw.kaboom.weapons.modules.weapons.WeaponMachineGun;
|
||||
|
||||
|
@ -71,6 +70,7 @@ public final class Main extends JavaPlugin {
|
|||
this.getServer().getPluginManager().registerEvents(new WeaponBlobinator(), this);
|
||||
this.getServer().getPluginManager().registerEvents(new WeaponGrenade(), this);
|
||||
this.getServer().getPluginManager().registerEvents(new WeaponMachineGun(), this);
|
||||
this.getServer().getPluginManager().registerEvents(new WeaponExplosiveCrossbow(), this);
|
||||
}
|
||||
|
||||
public static HashSet<BlockFace> getBlockFaces() {
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package pw.kaboom.weapons;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
public class WeaponItemBuilder {
|
||||
private final ItemStack itemStack;
|
||||
private final ItemMeta itemMeta;
|
||||
|
||||
private WeaponItemBuilder(Material material) {
|
||||
this.itemStack = new ItemStack(material);
|
||||
this.itemMeta = this.itemStack.getItemMeta();
|
||||
}
|
||||
|
||||
public WeaponItemBuilder enchantment(Enchantment enchantment) {
|
||||
return enchantment(enchantment, enchantment.getStartLevel());
|
||||
}
|
||||
|
||||
public WeaponItemBuilder enchantment(Enchantment enchantment, int level) {
|
||||
this.itemMeta.addEnchant(enchantment, level, true);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public WeaponItemBuilder name(String name) {
|
||||
final Component component = Component.text(name)
|
||||
.decoration(TextDecoration.ITALIC, false);
|
||||
this.itemMeta.displayName(component);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public static WeaponItemBuilder builder(Material material) {
|
||||
return new WeaponItemBuilder(material);
|
||||
}
|
||||
|
||||
public ItemStack build() {
|
||||
this.itemStack.setItemMeta(this.itemMeta);
|
||||
|
||||
return this.itemStack;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,27 +1,20 @@
|
|||
package pw.kaboom.weapons.commands;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import pw.kaboom.weapons.WeaponItemBuilder;
|
||||
|
||||
public final class CommandWeapons implements CommandExecutor {
|
||||
private void addWeapon(final Inventory inventory, final Material material,
|
||||
final Component name) {
|
||||
final ItemStack item = new ItemStack(material, 1);
|
||||
final ItemMeta itemMeta = item.getItemMeta();
|
||||
|
||||
itemMeta.displayName(name);
|
||||
item.setItemMeta(itemMeta);
|
||||
private void addWeapon(final Inventory inventory, final ItemStack item) {
|
||||
inventory.addItem(item);
|
||||
}
|
||||
|
||||
|
@ -34,26 +27,42 @@ public final class CommandWeapons implements CommandExecutor {
|
|||
final Player player = (Player) sender;
|
||||
final Inventory inventory = Bukkit.createInventory(null, 18, Component.text("Weapons"));
|
||||
|
||||
addWeapon(inventory, Material.ANVIL, Component.text("Anvil Dropper")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.SPECTRAL_ARROW, Component.text("Archer")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.FIRE_CHARGE, Component.text("Armageddon")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.MAGMA_CREAM, Component.text("Blobinator")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.EGG, Component.text("Grenade")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.BLAZE_POWDER, Component.text("Laser")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.STICK, Component.text("Lightning Stick")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.GOLDEN_HORSE_ARMOR, Component.text("Machine Gun")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.BLAZE_ROD, Component.text("Nuker")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, Material.IRON_HORSE_ARMOR, Component.text("Sniper")
|
||||
.decoration(TextDecoration.ITALIC, false));
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.ANVIL)
|
||||
.name("Anvil Dropper")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.SPECTRAL_ARROW)
|
||||
.name("Archer")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.FIRE_CHARGE)
|
||||
.name("Armageddon")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.MAGMA_CREAM)
|
||||
.name("Blobinator")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.EGG)
|
||||
.name("Grenade")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.BLAZE_POWDER)
|
||||
.name("Laser")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.STICK)
|
||||
.name("Lightning Stick")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.GOLDEN_HORSE_ARMOR)
|
||||
.name("Machine Gun")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.BLAZE_ROD)
|
||||
.name("Nuker")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.IRON_HORSE_ARMOR)
|
||||
.name("Sniper")
|
||||
.build());
|
||||
addWeapon(inventory, WeaponItemBuilder.builder(Material.CROSSBOW)
|
||||
.name("Explosive Crossbow")
|
||||
.enchantment(Enchantment.MULTISHOT)
|
||||
.enchantment(Enchantment.QUICK_CHARGE, 5)
|
||||
.build());
|
||||
|
||||
player.openInventory(inventory);
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -1,22 +1,47 @@
|
|||
package pw.kaboom.weapons.modules.player;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryView;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class PlayerReceiveWeapon implements Listener {
|
||||
@EventHandler
|
||||
void onInventoryClick(final InventoryClickEvent event) {
|
||||
if (event.isCancelled() || !Component.text("Weapons").equals(event.getView().title())) {
|
||||
final Component weaponViewName = Component.text("Weapons");
|
||||
final InventoryView view = event.getView();
|
||||
final Component viewTitle = view.title();
|
||||
|
||||
if (event.isCancelled() || !viewTitle.equals(weaponViewName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Inventory clickedInventory = event.getClickedInventory();
|
||||
|
||||
if (clickedInventory == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clickedInventory.equals(view.getTopInventory())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ItemStack item = event.getCurrentItem();
|
||||
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Component weaponName = item.getItemMeta().displayName();
|
||||
|
||||
if (weaponName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = (Player) event.getWhoClicked();
|
||||
|
||||
player.getInventory().addItem(item);
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
package pw.kaboom.weapons.modules.weapons;
|
||||
|
||||
import com.destroystokyo.paper.event.entity.EntityRemoveFromWorldEvent;
|
||||
import com.destroystokyo.paper.event.server.ServerTickEndEvent;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||
import org.bukkit.event.entity.ProjectileLaunchEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.projectiles.ProjectileSource;
|
||||
|
||||
public class WeaponExplosiveCrossbow implements Listener {
|
||||
|
||||
private static final int PARTICLE_OFFSET = 2;
|
||||
private final List<Projectile> explosiveProjectiles = new ArrayList<>();
|
||||
private final SecureRandom secureRandom = new SecureRandom();
|
||||
|
||||
@EventHandler
|
||||
public void onShootArrow(ProjectileLaunchEvent event) {
|
||||
final Projectile projectile = event.getEntity();
|
||||
final ProjectileSource source = projectile.getShooter();
|
||||
|
||||
if (!(source instanceof final HumanEntity humanEntity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Player player = (Player) humanEntity;
|
||||
final PlayerInventory playerInventory = player.getInventory();
|
||||
final ItemStack offHandItem = playerInventory.getItemInOffHand();
|
||||
final ItemStack mainHandItem = playerInventory.getItemInMainHand();
|
||||
final Material offHandItemMaterial = offHandItem.getType();
|
||||
final Material mainHandItemMaterial = mainHandItem.getType();
|
||||
|
||||
if (!mainHandItemMaterial.equals(Material.CROSSBOW) && !offHandItemMaterial.equals(
|
||||
Material.CROSSBOW)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Component itemName = Component.text("Explosive Crossbow")
|
||||
.decoration(TextDecoration.ITALIC, false);
|
||||
final ItemStack bow = mainHandItemMaterial == Material.CROSSBOW ?
|
||||
mainHandItem : offHandItem;
|
||||
final ItemMeta bowMeta = bow.getItemMeta();
|
||||
final Component displayName = bowMeta.displayName();
|
||||
|
||||
if (displayName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(displayName.equals(itemName))) {
|
||||
return;
|
||||
}
|
||||
|
||||
projectile.customName(Component.text("WeaponExplosiveArrow"));
|
||||
explosiveProjectiles.add(projectile);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onProjectileHit(ProjectileHitEvent event) {
|
||||
final Projectile projectile = event.getEntity();
|
||||
final Component customName = projectile.customName();
|
||||
|
||||
if (customName == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!customName.equals(Component.text("WeaponExplosiveArrow"))) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Entity hitEntity = event.getHitEntity();
|
||||
final Block hitBlock = event.getHitBlock();
|
||||
|
||||
final Location explosionLocation =
|
||||
(hitBlock != null || hitEntity != null) ?
|
||||
(hitEntity != null
|
||||
? hitEntity.getLocation() : hitBlock.getLocation())
|
||||
: projectile.getLocation();
|
||||
|
||||
final World world = projectile.getWorld();
|
||||
|
||||
world.createExplosion(explosionLocation, 4.9f, true);
|
||||
projectile.remove();
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onEntityDestroy(EntityRemoveFromWorldEvent event) {
|
||||
final Entity entity = event.getEntity();
|
||||
|
||||
if (!(entity instanceof final Projectile projectile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
explosiveProjectiles.remove(projectile);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onTickEnd(ServerTickEndEvent event) {
|
||||
for (Projectile projectile : explosiveProjectiles) {
|
||||
final World world = projectile.getWorld();
|
||||
final Location location = projectile.getLocation()
|
||||
.add(secureRandom.nextDouble(-PARTICLE_OFFSET, PARTICLE_OFFSET),
|
||||
secureRandom.nextDouble(-PARTICLE_OFFSET, PARTICLE_OFFSET),
|
||||
secureRandom.nextDouble(-PARTICLE_OFFSET, PARTICLE_OFFSET));
|
||||
|
||||
world.spawnParticle(Particle.FLAME, location, 4);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue