diff --git a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java index f80b87bc7..d089bad59 100644 --- a/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java +++ b/Plugins/Mineplex.Core.Common/src/mineplex/core/common/util/UtilMath.java @@ -180,4 +180,14 @@ public class UtilMath return values.get(closestIndex); } + + public static boolean isOdd(int size) + { + return !isEven(size); + } + + public static boolean isEven(int size) + { + return size % 2 == 0; + } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/AccessRule.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/AccessRule.java new file mode 100644 index 000000000..1ffa94e58 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/AccessRule.java @@ -0,0 +1,25 @@ +package mineplex.game.clans.clans.siege.cannon; + +import java.util.function.Predicate; + +import org.bukkit.entity.Player; + +import mineplex.game.clans.clans.siege.weapon.AccessType; + +public class AccessRule +{ + private Predicate _access; + private AccessType _type; + + public AccessRule(AccessType type, Predicate access) + { + _type = type; + _access = access; + } + + public boolean allow(AccessType type, Player player) + { + return type.equals(_type) && _access.test(player); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/Cannon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/Cannon.java index 6fc3e5416..0898a9196 100644 --- a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/Cannon.java +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/cannon/Cannon.java @@ -1,610 +1,125 @@ package mineplex.game.clans.clans.siege.cannon; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; +import java.util.Vector; import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.Sound; -import org.bukkit.craftbukkit.v1_8_R3.entity.CraftArmorStand; import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; import org.bukkit.entity.Slime; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.HandlerList; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDamageEvent; -import org.bukkit.event.entity.EntityExplodeEvent; -import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.player.PlayerArmorStandManipulateEvent; -import org.bukkit.event.player.PlayerInteractAtEntityEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffectType; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; import mineplex.core.common.util.C; import mineplex.core.common.util.F; -import mineplex.core.common.util.UtilAlg; -import mineplex.core.common.util.UtilBlock; import mineplex.core.common.util.UtilEnt; -import mineplex.core.common.util.UtilInv; -import mineplex.core.common.util.UtilItem; -import mineplex.core.common.util.UtilMath; import mineplex.core.common.util.UtilParticle; import mineplex.core.common.util.UtilParticle.ParticleType; import mineplex.core.common.util.UtilParticle.ViewDist; import mineplex.core.common.util.UtilPlayer; import mineplex.core.common.util.UtilServer; -import mineplex.core.common.util.UtilText; -import mineplex.core.common.util.UtilTextMiddle; -import mineplex.core.common.util.UtilTime; -import mineplex.core.hologram.Hologram; -import mineplex.core.itemstack.ItemBuilder; -import mineplex.core.updater.UpdateType; -import mineplex.core.updater.event.UpdateEvent; import mineplex.game.clans.clans.ClanInfo; -import mineplex.game.clans.clans.ClanTips.TipType; -import mineplex.game.clans.clans.ClansManager; -import mineplex.game.clans.clans.siege.BarrierCollisionBox; +import mineplex.game.clans.clans.siege.weapon.AccessType; +import mineplex.game.clans.clans.siege.weapon.ProjectileType; +import mineplex.game.clans.clans.siege.weapon.SiegeWeapon; +import mineplex.game.clans.clans.siege.weapon.WeaponStateInfo; -public class Cannon implements Listener +public class Cannon extends SiegeWeapon { - public static final ItemStack CANNON_ITEM = new ItemBuilder(Material.IRON_BLOCK, 1).setRawTitle(C.cBlue + "Cannon").setLore(C.cWhite + "BOOM BABY!").build(); - - public static final int COOLDOWN = 20 * 1000 /* 20 seconds*/; - - public static final int MAX_SULPHUR = 3; - public static final int MAX_TNT = 1; - - public static final double MAX_HEALTH = 600; - - public static final int TNT_SLOT = 4; - public static final List SULPHUR_SLOTS = Arrays.asList(1, 3, 5, 7); - public static final List EMPTY_SLOTS = Arrays.asList(0, 2, 6, 8); - - private static final double[] VERT_POWER = { 0.5, 0.75631, 0.9382 }; - private static final double[] HORIZ_POWER = { 0.8, 1.1241, 1.34231 }; - - private Location _location; - private CannonState _state; - - private Player _rider; - - // Entity Information - private List _entities; - - private TNTPrimed _projectile; - - private Inventory _inventory; - - private long _lastFired = -1; - - private double _health = MAX_HEALTH; - - private Hologram _healthHologram; - - private ClanInfo _clan; - - private BarrierCollisionBox _collisionBox; - public Cannon(Location location, ClanInfo clan) { - _location = location; - _state = CannonState.UNLOADED; + super(location, 600.d, "Cannon", clan, clan.Clans); - _clan = clan; + setBoundingBox(1); - _entities = new ArrayList<>(); + setStateInfo("Unloaded", new WeaponStateInfo(Material.SPONGE, (byte) 1)); + setStateInfo("Loaded", new WeaponStateInfo(Material.SPONGE, (byte) 0)); - _collisionBox = BarrierCollisionBox.single(_location.clone()); - _collisionBox.Construct(); - _collisionBox.registerRight((block, player) -> handleRightClick(player)); - _collisionBox.registerLeft((block, player) -> handleLeftClick(player, -1)); + Slime slime = location.getWorld().spawn(location, Slime.class); + Slime slime2 = location.getWorld().spawn(location, Slime.class); - _inventory = UtilServer.getServer().createInventory(null, InventoryType.DISPENSER, C.cRedB + "Cannon"); - - _healthHologram = new Hologram(ClansManager.getInstance().getHologramManager(), location.clone().add(.5, 3, .5), "Cannon Health", getDisplayHealth()); - _healthHologram.start(); + slime.setPassenger(slime2); - updateEntities(); - } - - public void cleanup() - { - _entities.forEach(Entity::remove); + UtilEnt.silence(slime, true); + UtilEnt.silence(slime2, true); + UtilEnt.Vegetate(slime); + UtilEnt.Vegetate(slime2); - _entities.clear(); + slime.setSize(-1); + slime2.setSize(-1); + slime.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 99999999, 1, true, false)); + slime2.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 99999999, 1, true, false)); - _collisionBox.Destruct(); - _healthHologram.stop(); - _healthHologram = null; + ArmorStand armorStand = location.getWorld().spawn(location, ArmorStand.class); - HandlerList.unregisterAll(this); - } - - private void updateEntities() - { - if (_entities.isEmpty()) - { - Slime slime = getArmorStandLocation().getWorld().spawn(getArmorStandLocation(), Slime.class); - - UtilEnt.silence(slime, true); - UtilEnt.Vegetate(slime); - - slime.setSize(-1); - slime.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 99999999, 1, true, false)); - - _entities.add(slime); - - slime = getArmorStandLocation().getWorld().spawn(getArmorStandLocation(), Slime.class); - - UtilEnt.silence(slime, true); - UtilEnt.Vegetate(slime); - - slime.setSize(-1); - slime.addPotionEffect(new PotionEffect(PotionEffectType.INVISIBILITY, 99999999, 1, true, false)); - - UtilMath.getLast(_entities).setPassenger(slime); - - _entities.add(slime); - - ArmorStand armorStand = _location.getWorld().spawn(getArmorStandLocation(), ArmorStand.class); - - UtilEnt.setFakeHead(armorStand, true); - armorStand.teleport(getArmorStandLocation()); - armorStand.setVisible(false); - armorStand.setHelmet(_state.toItemStack()); - armorStand.setGravity(false); - - armorStand.setPassenger(UtilMath.getFirst(_entities)); - - _entities.add(0, armorStand); - } - else - { - getArmorStand().setHelmet(_state.toItemStack()); - } - } - - private CraftArmorStand getArmorStand() - { - return (CraftArmorStand) UtilMath.getFirst(_entities); - } - - private Location getArmorStandLocation() - { - return _location.clone().add(.5, .15, .5); - } - - private void setState(CannonState state) - { - _state = state; - updateEntities(); - } - - public void fire() - { - TNTPrimed tnt = _location.getWorld().spawn(_location.clone().add(.5, .3, .5), TNTPrimed.class); + UtilEnt.setFakeHead(armorStand, true); + armorStand.teleport(location); + armorStand.setVisible(false); + armorStand.setGravity(false); - _projectile = tnt; + armorStand.setPassenger(slime); - double vVel = VERT_POWER[getPower() - 1]; - double hMulti = HORIZ_POWER[getPower() - 1]; + addEntity(slime, "Slime1"); + addEntity(slime2, "PLAYERMOUNT"); + addEntity(armorStand, "WEAPON"); - Vector velocity = UtilAlg.getTrajectory( - getArmorStand().getLocation(), - UtilAlg.moveForward( - getArmorStand().getLocation(), - 2., - (float) Math.toDegrees(getArmorStand().getHeadPose().getY()), false)) - .multiply(hMulti) - .setY(vVel); + setState("Unloaded"); - tnt.setVelocity(velocity); + setFirepowerType(Material.SULPHUR); + setAmmunitionType(Material.TNT); - _inventory.setItem(TNT_SLOT, UtilInv.decrement(_inventory.getItem(TNT_SLOT))); - SULPHUR_SLOTS.forEach(_inventory::clear); + setFirepowerSlots(1, 3, 5, 7); + setMaximumFirepowerPerSlot(3); - UtilParticle.PlayParticleToAll(ParticleType.LARGE_EXPLODE, getArmorStandLocation(), new Vector(0, 0, 0), .1f, 2, ViewDist.MAX); - UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(getArmorStandLocation(), Sound.EXPLODE, 1.f, 1.f)); + setAmmunitionSlot(4); + setMaximumAmmunitionPerSlot(1); - _lastFired = System.currentTimeMillis(); - } - - @EventHandler - public void onCloseInv(InventoryCloseEvent event) - { - if (!event.getInventory().equals(_inventory)) - { - return; - } + setFireCooldown(20000); - ClansManager.getInstance().runSyncLater(() -> { - if (event.getPlayer().getInventory().equals(_inventory)) + setProjectileType(ProjectileType.PRIMED_TNT); + setProjectileDoCrater(3, 2.d); + + enableInventory(UtilServer.getServer().createInventory(null, InventoryType.DISPENSER, C.cDAquaB + _name), new AccessRule(AccessType.RCLICK_BB, super::isRiding)); + + setRideable(new AccessRule(AccessType.RCLICK_BB, player -> { + if (!_owner.isMember(player)) { - return; + UtilPlayer.message(player, F.main("Clans", "This cannon is not owned by your Clan.")); + return false; } - if (canBeFired()) + if (getRider() != null && !getRider().equals(player)) { - UtilTextMiddle.display("Cannon Ready", "Power Level: " + C.cGreen + UtilText.repeat("▌", getPower()) + C.cRed + UtilText.repeat("▌", 3 - getPower()), 20, 100, 20, _rider); - } - }, 3L); - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onTntExplode(EntityExplodeEvent event) - { - // stop the tnt from exploding naturally - if (event.getEntity().equals(_projectile)) - { - event.setCancelled(true); - } - } - - public void updateProjectile() - { - if (_projectile != null) - { - UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, _projectile.getLocation().add(0, .5, 0), new Vector(0, 0, 0), .1f, 3, ViewDist.MAX); - - _projectile.setFuseTicks(40); - - if ((Math.abs(_projectile.getVelocity().getX()) < 0.01 || Math.abs(_projectile.getVelocity().getZ()) < 0.01) && UtilBlock.getInRadius(_projectile.getLocation(), 2).keySet().stream().filter(block -> !UtilItem.isBoundless(block.getType())).iterator().hasNext() && _projectile.getTicksLived() >= 10) - { - //Do Explosion; - - new CannonCrater(this, UtilBlock.nearestFloor(_projectile.getLocation())); - - UtilServer.getServer().getOnlinePlayers().forEach(player -> player.playSound(_projectile.getLocation(), Sound.EXPLODE, 1.f, 1.f)); - - _projectile.remove(); - _projectile = null; - } - } - } - - private void attemptFire() - { - if (canBeFired()) - { - if (System.currentTimeMillis() - _lastFired < COOLDOWN) - { - UtilPlayer.message(_rider, F.main("Clans", "Cannon is cooling down. (" + F.time(UtilTime.MakeStr(COOLDOWN - (System.currentTimeMillis() - _lastFired)) + C.mBody + ")"))); - return; + UtilPlayer.message(player, F.main("Clans", "Someone is already riding this cannon.")); + return false; } - fire(); - } - else + return !player.equals(getRider()); + })); + } + + @Override + public void UpdateState(String state) + { + ((ArmorStand) getEntity("WEAPON")).setHelmet(new ItemStack(getStateInfo(state).getType(), getStateInfo(state).getData())); + } + + @Override + protected void tick() + { + if (getProjectile() != null) { - UtilPlayer.message(_rider, F.main("Clans", "Cannon is not correctly loaded.")); - _rider.playSound(_rider.getLocation(), Sound.CLICK, 1.f, 1.f); + UtilParticle.PlayParticleToAll(ParticleType.LARGE_SMOKE, getProjectile().getLocation().add(0, .5, 0), new Vector(0, 0, 0), .1f, 3, ViewDist.MAX); } } - private void handleOpenInv(Player player) + @Override + protected double[] getProjectileVelocityMult() { - if (!player.equals(_rider)) - { - return; - } + int firepower = getPowerLevel(); - if (_inventory == null) - { - cleanup(); - return; - } - - _rider.openInventory(_inventory); + return new double[] { firepower, firepower }; } - private int getPower() - { - int power = 0; - - for (int slot : SULPHUR_SLOTS) - { - if (_inventory.getItem(slot) != null) - { - power += _inventory.getItem(slot).getAmount(); - } - } - - return power / 4; - } - - private int getTnt() - { - return _inventory.getItem(TNT_SLOT) != null ? _inventory.getItem(TNT_SLOT).getAmount() : 0; - } - - private boolean canBeFired() - { - return getTnt() > 0 && getPower() > 0 && _projectile == null; - } - - @EventHandler - public void updateState(UpdateEvent event) - { -// if (event.getType() == UpdateType.FASTEST) -// { -// if (_state == CannonState.LOADED) -// { -// double yaw = getArmorStand().getHeadPose().getY() - 7.75d; -// -// Location loc = new Location(_location.getWorld(), getArmorStand().getLocation().getX() + (0.5 * Math.cos(yaw)), _location.getY() + 1.12, getArmorStand().getLocation().getZ() + (0.5 * Math.sin(yaw))); -// -// loc = UtilAlg.moveForward(loc, 0.1, (float) Math.toDegrees(yaw + 7.75), false); -// -// UtilParticle.PlayParticleToAll(ParticleType.FLAME, loc, new Vector(0, 0, 0), 0.f, 1, ViewDist.MAX); -// } -// } - - if (event.getType() != UpdateType.TICK) - { - return; - } - - CannonState newState = _inventory.getItem(TNT_SLOT) != null ? CannonState.LOADED : CannonState.UNLOADED; - - if (_state != newState) - { - setState(newState); - } - - checkInv(); - - updateProjectile(); - } - - public void checkInv() - { - for (int slot = 0; slot < 9; slot++) - { - ItemStack item = _inventory.getItem(slot); - - if (item == null) - { - continue; - } - - if (slot == TNT_SLOT) - { - if (item.getType() != Material.TNT) - { - _rider.getInventory().addItem(item); - _inventory.setItem(slot, null); - } - else - { - if (item.getAmount() > MAX_TNT) - { - _rider.getInventory().addItem(new ItemStack(Material.TNT, item.getAmount() - MAX_TNT)); - _inventory.setItem(slot, new ItemStack(Material.TNT, MAX_TNT)); - } - } - } - else if (SULPHUR_SLOTS.contains(slot)) - { - if (item.getType() != Material.SULPHUR) - { - _rider.getInventory().addItem(item); - _inventory.setItem(slot, null); - } - else - { - if (item.getAmount() > MAX_SULPHUR) - { - _rider.getInventory().addItem(new ItemStack(Material.SULPHUR, item.getAmount() - MAX_SULPHUR)); - _inventory.setItem(slot, new ItemStack(Material.SULPHUR, MAX_SULPHUR)); - } - } - } - else if (EMPTY_SLOTS.contains(slot)) // also classes as just an 'else{}' - { - _rider.getInventory().addItem(item); - _inventory.setItem(slot, null); - } - } - } - - @EventHandler(priority = EventPriority.HIGHEST) - public void onDmg(EntityDamageByEntityEvent event) - { - if (!_entities.contains(event.getEntity())) - { - return; - } - - if (!(event.getDamager() instanceof Player)) - { - handleLeftClick((Player) event.getDamager(), event.getFinalDamage()); - } - } - - @EventHandler - public void onInteract(PlayerInteractAtEntityEvent event) - { - if (_entities.contains(event.getRightClicked())) - { - handleRightClick(event.getPlayer()); - event.setCancelled(true); - } - } - - @EventHandler - public void onInteract(PlayerInteractEntityEvent event) - { - if (_entities.contains(event.getRightClicked())) - { - handleRightClick(event.getPlayer()); - event.setCancelled(true); - } - } - - @EventHandler - public void onInteract(PlayerArmorStandManipulateEvent event) - { - if (_entities.contains(event.getRightClicked())) - { - handleRightClick(event.getPlayer()); - event.setCancelled(true); - } - } - - public void handleLeftClick(Player player, double damage) - { - if (!_clan.isMember(player)) - { - removeHealth(damage == -1 ? calcDmg(player) : damage); - } - - if (!player.equals(_rider)) - { - return; - } - - attemptFire(); - } - - private double calcDmg(Player player) - { - ItemStack item = player.getItemInHand(); - - if (item == null) - { - return 1; - } - - double dmg = UtilItem.getAttackDamage(item.getType()); - - switch(item.getType()) - { - case RECORD_4: - dmg += 7; - case GREEN_RECORD: - dmg += 6; - case GOLD_RECORD: - dmg += 9; - case RECORD_3: - dmg += 1; - case RECORD_5: - dmg += 7; - default: - } - - return dmg; - } - - public void handleRightClick(Player player) - { - if (!_clan.isMember(player)) - { - UtilPlayer.message(player, F.main("Clans", "This Cannon does not belong to your Clan.")); - return; - } - - Entity passenger = UtilMath.getLast(_entities).getPassenger(); - if (passenger == null) - { - UtilMath.getLast(_entities).setPassenger(player); - - _rider = player; - - ClansManager.getInstance().ClanTips.displayTip(TipType.MOUNT_CANNON, _rider); - } - else - { - handleOpenInv(player); - } - } - - @EventHandler - public void update(UpdateEvent event) - { - if (event.getType() != UpdateType.TICK) - { - return; - } - - if (_rider != null && !_rider.equals(UtilMath.getLast(_entities).getPassenger())) - { - _rider = null; - } - - if (_rider != null) - { - if (System.currentTimeMillis() - _lastFired < 5000) - { - return; - } - - ArmorStand armorStand = (ArmorStand) UtilMath.getFirst(_entities); - double standYaw = Math.toDegrees(armorStand.getHeadPose().getY()) % 360; - double riderYaw = _rider.getLocation().getYaw() % 360; - - // riderYaw = 350 and standYaw = 20 - // dif should be -30 and not 330 - double dif = riderYaw - standYaw; - if (dif > 180) dif -= 360; - if (dif < -180) dif += 360; - - double yaw = standYaw + Math.min(dif / 20.f, 4f); - - armorStand.setHeadPose(new EulerAngle(0, Math.toRadians(yaw), 0)); - } - } - - @EventHandler - public void onDamage(EntityDamageEvent event) - { - if (_entities.contains(event.getEntity())) - { - event.setCancelled(true); - } - } - - // Health Managemnet - public double getHealth() - { - return _health; - } - - public String getDisplayHealth() - { - return UtilText.getProgress(null, _health / MAX_HEALTH, null, false, 12); - } - - public void setHealth(double health) - { - _health = UtilMath.clamp(health, 0, MAX_HEALTH); - - _healthHologram.setText("Cannon Health", getDisplayHealth()); - - if (_health == 0) - { - cleanup(); - } - } - - public void removeHealth(double health) - { - setHealth(_health - health); - } - - public void addHealth(double health) - { - setHealth(_health + health); - } } diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/AccessType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/AccessType.java new file mode 100644 index 000000000..aafb8c9d4 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/AccessType.java @@ -0,0 +1,7 @@ +package mineplex.game.clans.clans.siege.weapon; + +public enum AccessType +{ + RCLICK_BB, + LCLICK_BB, +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/ProjectileType.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/ProjectileType.java new file mode 100644 index 000000000..0f364ee89 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/ProjectileType.java @@ -0,0 +1,7 @@ +package mineplex.game.clans.clans.siege.weapon; + +public enum ProjectileType +{ + PRIMED_TNT, + FALLING_BLOCK; +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/SiegeWeapon.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/SiegeWeapon.java new file mode 100644 index 000000000..e2fc34e90 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/SiegeWeapon.java @@ -0,0 +1,283 @@ +package mineplex.game.clans.clans.siege.weapon; + +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.Validate; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.inventory.Inventory; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; + +import mineplex.core.common.util.UtilMath; +import mineplex.core.common.util.UtilServer; +import mineplex.core.common.util.UtilText; +import mineplex.core.hologram.Hologram; +import mineplex.core.updater.UpdateType; +import mineplex.core.updater.event.UpdateEvent; +import mineplex.game.clans.clans.ClanInfo; +import mineplex.game.clans.clans.ClansManager; +import mineplex.game.clans.clans.siege.BarrierCollisionBox; +import mineplex.game.clans.clans.siege.cannon.AccessRule; + +public abstract class SiegeWeapon implements Listener +{ + private ClansManager _clans; + + protected ClanInfo _owner; + protected final String _name; + protected final double _maxHealth; + protected double _health; + + protected Inventory _inventory; + protected AccessRule _inventoryAccess; + + private Hologram _infoHologram; + private BarrierCollisionBox _collisionBox; + + private Location _location; + + private final Map _registeredStates; + private String _currentState; + + private final List _comprisedOf; + + // Friendly-name mapping to index in _comprisedOf for easier management of entities. + private final Map _entityMapping; + + private boolean _isRideable; + private AccessRule _mountAccess; + + private Player _rider; + + public SiegeWeapon(Location location, double maxHealth, String name, ClanInfo owner, ClansManager clansManager) + { + _location = location; + _name = name; + _health = _maxHealth = maxHealth; + _owner = owner; + + _comprisedOf = Lists.newArrayList(); + _registeredStates = Maps.newHashMap(); + _entityMapping = Maps.newHashMap(); + + _infoHologram = new Hologram(ClansManager.getInstance().getHologramManager(), _location.clone().add(.5, 3, .5), _name + " Health", getDisplayHealth()); + _infoHologram.start(); + + UtilServer.getPluginManager().registerEvents(this, clansManager.getPlugin()); + + _clans = clansManager; + } + + protected void enableInventory(Inventory inventory, AccessRule accessRule) + { + _inventory = inventory; + _inventoryAccess = accessRule; + } + + protected void setBoundingBox(int size) + { + Validate.isTrue(UtilMath.isOdd(size), "Size must be an odd number."); + Validate.isTrue(size > 0, "Size must be a positive number."); + + _collisionBox = size == 1 ? BarrierCollisionBox.single(_location.clone()) : BarrierCollisionBox.all(_location.clone().subtract((size - 1) / 2, 0, (size - 1) / 2), _location.clone().add(((size - 1) / 2) + .5, size - 1, ((size - 1) / 2) + .5)); + _collisionBox.Construct(); + _collisionBox.registerRight((block, player) -> handleRightClick(player)); + _collisionBox.registerLeft((block, player) -> handleLeftClick(player)); + } + + // Riding + + protected Player getRider() + { + return _rider; + } + + protected void setRideable(AccessRule accessRule) + { + _isRideable = true; + _mountAccess = accessRule; + } + + // Internal + + private void kill() + { + Cleanup(); + + _comprisedOf.forEach(Entity::remove); + + _entityMapping.clear(); + _comprisedOf.clear(); + _infoHologram.stop(); + + HandlerList.unregisterAll(this); + } + + private void handleMount(Player player) + { + getEntity("PLAYERMOUNT").setPassenger(player); + OnMount(player); + } + + private void handleInventoryOpen(Player player) + { + player.openInventory(_inventory); + } + + private void handleRightClick(Player player) + { + RightClick(player); + + if (_isRideable && _mountAccess.allow(AccessType.RCLICK_BB, player)) + { + handleMount(player); + } + + if (_inventory != null && _inventoryAccess.allow(AccessType.RCLICK_BB, player)) + { + handleInventoryOpen(player); + } + } + + private void handleLeftClick(Player player) + { + LeftClick(player); + + if (_isRideable && _mountAccess.allow(AccessType.LCLICK_BB, player)) + { + handleMount(player); + } + + if (_inventory != null && _inventoryAccess.allow(AccessType.LCLICK_BB, player)) + { + handleInventoryOpen(player); + } + } + + // Methods for implementation by sub-classes + + protected void Tick() + { + } + + protected void OnMount(Player player) + { + } + + protected void LeftClick(Player player) + { + } + + protected void RightClick(Player player) + { + } + + protected void Cleanup() + { + } + + protected void UpdateState(String state) + { + } + + // Entity Management + + protected final boolean addEntity(Entity entity, String uniqueName) + { + boolean success = _comprisedOf.add(entity); + + if (success) + { + _entityMapping.put(uniqueName, _comprisedOf.size() - 1); + } + + return success; + } + + protected final Entity getEntity(String uniqueName) + { + return _comprisedOf.get(_entityMapping.get(uniqueName)); + } + + // Health Management + + public final double getHealth() + { + return _health; + } + + public final String getDisplayHealth() + { + return UtilText.getProgress(null, _health / _maxHealth, null, false, 12); + } + + public final void setHealth(double health) + { + _health = UtilMath.clamp(health, 0, _maxHealth); + + _infoHologram.setText(_name + " Health", getDisplayHealth()); + + if (_health == 0) + { + kill(); + } + } + + public final void removeHealth(double health) + { + setHealth(_health - health); + } + + public final void addHealth(double health) + { + setHealth(_health + health); + } + + //State Management + + public final void setState(String state) + { + Validate.isTrue(_registeredStates.containsKey(state), "Provided state has not yet been registered."); + + _currentState = state; + + UpdateState(state); + } + + public final void setStateInfo(String state, WeaponStateInfo info) + { + _registeredStates.put(state, info); + } + + public final WeaponStateInfo getStateInfo(String state) + { + if (!_registeredStates.containsKey(state)) + { + _registeredStates.put(state, new WeaponStateInfo(Material.STONE, (byte) 101)); + } + + return _registeredStates.get(state); + } + + // Events + + @EventHandler + public void update(UpdateEvent event) + { + if (event.getType() != UpdateType.TICK) + { + return; + } + + Tick(); + } + +} diff --git a/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/WeaponStateInfo.java b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/WeaponStateInfo.java new file mode 100644 index 000000000..917035f38 --- /dev/null +++ b/Plugins/Mineplex.Game.Clans/src/mineplex/game/clans/clans/siege/weapon/WeaponStateInfo.java @@ -0,0 +1,25 @@ +package mineplex.game.clans.clans.siege.weapon; + +import org.bukkit.Material; + +public class WeaponStateInfo +{ + private Material _material; + private byte _data; + + public WeaponStateInfo(Material material, byte data) + { + _material = material; + _data = data; + } + + public Material getType() + { + return _material; + } + + public byte getData() + { + return _data; + } +}