Attempt to properly update...
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,60 @@
|
|||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Chain Lightning",
|
||||||
|
aliases = {"chainlightning"}
|
||||||
|
)
|
||||||
|
public class ChainLightning implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How many blocks the chain lightning can spread over.
|
||||||
|
* Must be greater than 0.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many server ticks between each lightning strike.
|
||||||
|
* Must be greater than 0.
|
||||||
|
*/
|
||||||
|
private final int TICKS = 10;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
final LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), true);
|
||||||
|
if (target == null || !(target instanceof Player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
strikeLightning(arena, (Player) target, new ArrayList<Player>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void strikeLightning(final Arena arena, final Player p, final List<Player> done) {
|
||||||
|
arena.scheduleTask(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!arena.isRunning() || !arena.inArena(p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Smite the target
|
||||||
|
arena.getWorld().strikeLightning(p.getLocation());
|
||||||
|
done.add(p);
|
||||||
|
|
||||||
|
// Grab all nearby players
|
||||||
|
List<Player> nearby = AbilityUtils.getNearbyPlayers(arena, p, RADIUS);
|
||||||
|
|
||||||
|
// Remove all that are "done", and return if empty
|
||||||
|
nearby.removeAll(done);
|
||||||
|
if (nearby.isEmpty()) return;
|
||||||
|
|
||||||
|
// Otherwise, smite the next target!
|
||||||
|
strikeLightning(arena, nearby.get(0), done);
|
||||||
|
}
|
||||||
|
}, TICKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Disorient Distant",
|
||||||
|
aliases = {"disorientdistant"}
|
||||||
|
)
|
||||||
|
public class DisorientDistant implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How far away players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
for (Player p : AbilityUtils.getDistantPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
loc.setYaw(loc.getYaw() + 45 + AbilityUtils.random.nextInt(270));
|
||||||
|
p.teleport(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Disorient Nearby",
|
||||||
|
aliases = {"disorientnearby"}
|
||||||
|
)
|
||||||
|
public class DisorientNearby implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), false);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
loc.setYaw(loc.getYaw() + 45 + AbilityUtils.random.nextInt(270));
|
||||||
|
p.teleport(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Disorient Target",
|
||||||
|
aliases = {"disorienttarget"}
|
||||||
|
)
|
||||||
|
public class DisorientTarget implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the boss has no target, should a random player be selected?
|
||||||
|
*/
|
||||||
|
private final boolean RANDOM = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), RANDOM);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
Location loc = target.getLocation();
|
||||||
|
loc.setYaw(loc.getYaw() + 45 + AbilityUtils.random.nextInt(270));
|
||||||
|
target.teleport(loc);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Fetch Distant",
|
||||||
|
aliases = {"fetchdistant"}
|
||||||
|
)
|
||||||
|
public class FetchDistant implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How far away players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getDistantPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
p.teleport(bLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Fetch Nearby",
|
||||||
|
aliases = {"fetchnearby"}
|
||||||
|
)
|
||||||
|
public class FetchNearby implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
p.teleport(bLoc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Fetch Target",
|
||||||
|
aliases = {"fetchtarget"}
|
||||||
|
)
|
||||||
|
public class FetchTarget implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the boss has no target, should a random player be selected?
|
||||||
|
*/
|
||||||
|
private final boolean RANDOM = true;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), RANDOM);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
target.teleport(boss.getEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Fire Aura",
|
||||||
|
aliases = {"fireaura","auraoffire"}
|
||||||
|
)
|
||||||
|
public class FireAura implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many ticks the players should be on fire for.
|
||||||
|
*/
|
||||||
|
private final int TICKS = 20;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS))
|
||||||
|
p.setFireTicks(TICKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Flood",
|
||||||
|
aliases = {"flood"}
|
||||||
|
)
|
||||||
|
public class Flood implements Ability
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Player p = AbilityUtils.getRandomPlayer(arena);
|
||||||
|
Block block = p.getLocation().getBlock();
|
||||||
|
|
||||||
|
if (block.getTypeId() == 0) {
|
||||||
|
block.setTypeId(8);
|
||||||
|
arena.addBlock(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Lightning Aura",
|
||||||
|
aliases = {"lightningaura","auraoflightning"}
|
||||||
|
)
|
||||||
|
public class LightningAura implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
World world = arena.getWorld();
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
world.strikeLightning(p.getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Living Bomb",
|
||||||
|
aliases = {"livingbomb"}
|
||||||
|
)
|
||||||
|
public class LivingBomb implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How many ticks before the bomb goes off.
|
||||||
|
*/
|
||||||
|
private final int FUSE = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the bomb.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many ticks players affected by the bomb should burn.
|
||||||
|
*/
|
||||||
|
private final int AFTERBURN = 40;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final Arena arena, MABoss boss) {
|
||||||
|
// Grab the target, or a random player.
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), true);
|
||||||
|
|
||||||
|
// We only want players.
|
||||||
|
if (target == null || !(target instanceof Player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
final Player p = (Player) target;
|
||||||
|
p.setFireTicks(FUSE + 5);
|
||||||
|
|
||||||
|
// Create an explosion after 4 seconds
|
||||||
|
arena.scheduleTask(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
// If the player died, or if they put out the fire.
|
||||||
|
if (!arena.isRunning() || !arena.inArena(p) || p.getFireTicks() <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explode!
|
||||||
|
arena.getWorld().createExplosion(p.getLocation(), 1F);
|
||||||
|
|
||||||
|
// And set every nearby player on fire!
|
||||||
|
for (Player nearby : AbilityUtils.getNearbyPlayers(arena, p, RADIUS)) {
|
||||||
|
nearby.setFireTicks(AFTERBURN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, FUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Obsidian Bomb",
|
||||||
|
aliases = {"obsidianbomb"}
|
||||||
|
)
|
||||||
|
public class ObsidianBomb implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How many ticks before the bomb goes off.
|
||||||
|
*/
|
||||||
|
private final int FUSE = 80;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final Arena arena, MABoss boss) {
|
||||||
|
// Grab the target, or a random player.
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), true);
|
||||||
|
|
||||||
|
final World world = arena.getWorld();
|
||||||
|
final Location loc = target.getLocation();
|
||||||
|
|
||||||
|
Block b = world.getBlockAt(target.getLocation());
|
||||||
|
b.setType(Material.OBSIDIAN);
|
||||||
|
arena.addBlock(b);
|
||||||
|
|
||||||
|
arena.scheduleTask(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!arena.isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
world.getBlockAt(loc).breakNaturally();
|
||||||
|
world.createExplosion(loc, 3F);
|
||||||
|
}
|
||||||
|
}, FUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Pull Distant",
|
||||||
|
aliases = {"pulldistant"}
|
||||||
|
)
|
||||||
|
public class PullDistant implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How far away players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getDistantPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
Vector v = new Vector(bLoc.getX() - loc.getX(), 0, bLoc.getZ() - loc.getZ());
|
||||||
|
|
||||||
|
double a = Math.abs(bLoc.getX() - loc.getX());
|
||||||
|
double b = Math.abs(bLoc.getZ() - loc.getZ());
|
||||||
|
double c = Math.sqrt((a*a + b*b));
|
||||||
|
|
||||||
|
p.setVelocity(v.normalize().multiply(c*0.3).setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Pull Nearby",
|
||||||
|
aliases = {"pullnearby"}
|
||||||
|
)
|
||||||
|
public class PullNearby implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
Vector v = new Vector(bLoc.getX() - loc.getX(), 0, bLoc.getZ() - loc.getZ());
|
||||||
|
|
||||||
|
double a = Math.abs(bLoc.getX() - loc.getX());
|
||||||
|
double b = Math.abs(bLoc.getZ() - loc.getZ());
|
||||||
|
double c = Math.sqrt((a*a + b*b));
|
||||||
|
|
||||||
|
p.setVelocity(v.normalize().multiply(c*0.3).setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Pull Target",
|
||||||
|
aliases = {"pulltarget"}
|
||||||
|
)
|
||||||
|
public class PullTarget implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the boss has no target, should a random player be selected?
|
||||||
|
*/
|
||||||
|
private final boolean RANDOM = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), RANDOM);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
Location loc = target.getLocation();
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
Vector v = new Vector(bLoc.getX() - loc.getX(), 0, bLoc.getZ() - loc.getZ());
|
||||||
|
|
||||||
|
double a = Math.abs(bLoc.getX() - loc.getX());
|
||||||
|
double b = Math.abs(bLoc.getZ() - loc.getZ());
|
||||||
|
double c = Math.sqrt((a*a + b*b));
|
||||||
|
|
||||||
|
target.setVelocity(v.normalize().multiply(c*0.3).setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DISCLAIMER: The Ability source code is provided as-is, and the creator(s) of
|
||||||
|
* MobArena WILL NOT be held responsible for any damage that may
|
||||||
|
* result from altering the files.
|
||||||
|
*
|
||||||
|
* WARNING: Unless you know exactly what you are doing, i.e. you have a lot
|
||||||
|
* of experience with Java and Bukkit, you should never change any
|
||||||
|
* other values than those of the variables in CAPITAL LETTERS.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Root Target
|
||||||
|
* Freezes the boss' target in place for ~3 seconds (default), by warping the
|
||||||
|
* player to the same spot [ITERATIONS] times, with [TICKS] server ticks
|
||||||
|
* between each iteration.
|
||||||
|
*
|
||||||
|
* @author garbagemule
|
||||||
|
*/
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Root Target",
|
||||||
|
aliases = {"roottarget", "freezetarget"}
|
||||||
|
)
|
||||||
|
public class RootTarget implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How many times the player will be warped back to his original position.
|
||||||
|
* Must be greater than 0.
|
||||||
|
*/
|
||||||
|
private final int ITERATIONS = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How many server ticks between each iteration of
|
||||||
|
* Must be greater than 0.
|
||||||
|
*/
|
||||||
|
private final int TICKS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
final LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), true);
|
||||||
|
if (target == null || !(target instanceof Player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Player p = (Player) target;
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
|
||||||
|
rootTarget(arena, p, loc, ITERATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rootTarget(final Arena arena, final Player p, final Location loc, final int counter) {
|
||||||
|
// If the counter is 0, we're done.
|
||||||
|
if (counter <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arena.scheduleTask(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (!arena.isRunning() || !arena.inArena(p)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.teleport(loc);
|
||||||
|
rootTarget(arena, p, loc, counter - 1);
|
||||||
|
}
|
||||||
|
}, TICKS);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import org.bukkit.entity.Arrow;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Shoot Arrow",
|
||||||
|
aliases = {"arrow","arrows"}
|
||||||
|
)
|
||||||
|
public class ShootArrow implements Ability
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
//boss.getEntity().launchProjectile(Arrow.class);
|
||||||
|
boss.getEntity().shootArrow();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import org.bukkit.entity.Fireball;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Shoot Fireball",
|
||||||
|
aliases = {"fireball","fireballs"}
|
||||||
|
)
|
||||||
|
public class ShootFireball implements Ability
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
//boss.getEntity().launchProjectile(Fireball.class);
|
||||||
|
boss.getEntity().throwEgg();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Shuffle Positions",
|
||||||
|
aliases = {"shuffle","shufflepositions"}
|
||||||
|
)
|
||||||
|
public class ShufflePositions implements Ability
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
// Grab the players and add the boss
|
||||||
|
List<LivingEntity> entities = new ArrayList<LivingEntity>(arena.getPlayersInArena());
|
||||||
|
entities.add(boss.getEntity());
|
||||||
|
|
||||||
|
// Grab the locations
|
||||||
|
List<Location> locations = new LinkedList<Location>();
|
||||||
|
for (LivingEntity e : entities) {
|
||||||
|
locations.add(e.getLocation());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shuffle the entities list.
|
||||||
|
Collections.shuffle(entities);
|
||||||
|
|
||||||
|
/* The entities are shuffled, but the locations are not, so if
|
||||||
|
* we remove the first element of each list, chances are they
|
||||||
|
* will not match, i.e. shuffle achieved! */
|
||||||
|
while (!entities.isEmpty() && !locations.isEmpty()) {
|
||||||
|
entities.remove(0).teleport(locations.remove(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Throw Distant",
|
||||||
|
aliases = {"throwdistant"}
|
||||||
|
)
|
||||||
|
public class ThrowDistant implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How far away players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 8;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getDistantPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
|
||||||
|
p.setVelocity(v.normalize().setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Throw Nearby",
|
||||||
|
aliases = {"thrownearby"}
|
||||||
|
)
|
||||||
|
public class ThrowNearby implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* How close players must be to be affected by the ability.
|
||||||
|
*/
|
||||||
|
private final int RADIUS = 5;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
|
||||||
|
for (Player p : AbilityUtils.getNearbyPlayers(arena, boss.getEntity(), RADIUS)) {
|
||||||
|
Location loc = p.getLocation();
|
||||||
|
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
|
||||||
|
p.setVelocity(v.normalize().setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Throw Target",
|
||||||
|
aliases = {"throwtarget"}
|
||||||
|
)
|
||||||
|
public class ThrowTarget implements Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* If the boss has no target, should a random player be selected?
|
||||||
|
*/
|
||||||
|
private final boolean RANDOM = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
LivingEntity target = AbilityUtils.getTarget(arena, boss.getEntity(), RANDOM);
|
||||||
|
if (target == null) return;
|
||||||
|
|
||||||
|
Location bLoc = boss.getEntity().getLocation();
|
||||||
|
Location loc = target.getLocation();
|
||||||
|
Vector v = new Vector(loc.getX() - bLoc.getX(), 0, loc.getZ() - bLoc.getZ());
|
||||||
|
|
||||||
|
target.setVelocity(v.normalize().setY(0.8));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
import com.garbagemule.MobArena.waves.ability.*;
|
||||||
|
|
||||||
|
@AbilityInfo(
|
||||||
|
name = "Warp",
|
||||||
|
aliases = {"warp","warptoplayer"}
|
||||||
|
)
|
||||||
|
public class WarpToPlayer implements Ability
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void execute(Arena arena, MABoss boss) {
|
||||||
|
Player p = AbilityUtils.getRandomPlayer(arena);
|
||||||
|
boss.getEntity().teleport(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,799 @@
|
|||||||
|
package com.garbagemule.MobArena;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.block.Block;
|
||||||
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
|
import org.bukkit.block.ContainerBlock;
|
||||||
|
import org.bukkit.block.Sign;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.entity.Projectile;
|
||||||
|
import org.bukkit.entity.Slime;
|
||||||
|
import org.bukkit.entity.Wolf;
|
||||||
|
import org.bukkit.event.Event.Result;
|
||||||
|
import org.bukkit.event.block.Action;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.block.BlockBurnEvent;
|
||||||
|
import org.bukkit.event.block.BlockEvent;
|
||||||
|
import org.bukkit.event.block.BlockFormEvent;
|
||||||
|
import org.bukkit.event.block.BlockIgniteEvent;
|
||||||
|
import org.bukkit.event.block.BlockPlaceEvent;
|
||||||
|
import org.bukkit.event.block.SignChangeEvent;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||||
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
||||||
|
import org.bukkit.event.entity.EntityChangeBlockEvent;
|
||||||
|
import org.bukkit.event.entity.EntityCombustEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
|
import org.bukkit.event.entity.EntityRegainHealthEvent;
|
||||||
|
import org.bukkit.event.entity.EntityTargetEvent;
|
||||||
|
import org.bukkit.event.entity.FoodLevelChangeEvent;
|
||||||
|
import org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason;
|
||||||
|
import org.bukkit.event.entity.EntityTargetEvent.TargetReason;
|
||||||
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||||
|
import org.bukkit.event.player.PlayerAnimationEvent;
|
||||||
|
import org.bukkit.event.player.PlayerBucketEmptyEvent;
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
import org.bukkit.event.player.PlayerKickEvent;
|
||||||
|
import org.bukkit.event.player.PlayerPreLoginEvent;
|
||||||
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
import org.bukkit.event.player.PlayerRespawnEvent;
|
||||||
|
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.material.Attachable;
|
||||||
|
import org.bukkit.material.Bed;
|
||||||
|
import org.bukkit.material.Door;
|
||||||
|
import org.bukkit.material.Redstone;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.MAUtils;
|
||||||
|
import com.garbagemule.MobArena.MobArena;
|
||||||
|
import com.garbagemule.MobArena.Msg;
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.leaderboards.Leaderboard;
|
||||||
|
import com.garbagemule.MobArena.listeners.MAGlobalListener.TeleportResponse;
|
||||||
|
import com.garbagemule.MobArena.region.ArenaRegion;
|
||||||
|
import com.garbagemule.MobArena.region.RegionPoint;
|
||||||
|
import com.garbagemule.MobArena.repairable.*;
|
||||||
|
import com.garbagemule.MobArena.util.TextUtils;
|
||||||
|
import com.garbagemule.MobArena.util.config.ConfigSection;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
|
||||||
|
public class ArenaListener
|
||||||
|
{
|
||||||
|
private MobArena plugin;
|
||||||
|
private Arena arena;
|
||||||
|
private ArenaRegion region;
|
||||||
|
private MonsterManager monsters;
|
||||||
|
|
||||||
|
private boolean softRestore,
|
||||||
|
softRestoreDrops,
|
||||||
|
protect;
|
||||||
|
private boolean monsterExp,
|
||||||
|
monsterInfight,
|
||||||
|
pvpEnabled,
|
||||||
|
foodRegen,
|
||||||
|
lockFoodLevel;
|
||||||
|
private boolean allowTeleport,
|
||||||
|
canShare,
|
||||||
|
allowMonsters;
|
||||||
|
|
||||||
|
private Set<Player> banned;
|
||||||
|
|
||||||
|
public ArenaListener(Arena arena, MobArena plugin) {
|
||||||
|
this.plugin = plugin;
|
||||||
|
this.arena = arena;
|
||||||
|
this.region = arena.getRegion();
|
||||||
|
this.monsters = arena.getMonsterManager();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO: Figure out if this is really a good idea + It saves needing all
|
||||||
|
* those methods in Arena.java + It is relatively simple + It would be
|
||||||
|
* fairly easy to implement an observer pattern - More private fields -
|
||||||
|
* Uglier code
|
||||||
|
*/
|
||||||
|
ConfigSection s = arena.getSettings();
|
||||||
|
this.softRestore = s.getBoolean("soft-restore", false);
|
||||||
|
this.softRestoreDrops = s.getBoolean("soft-restore-drops", false);
|
||||||
|
this.protect = s.getBoolean("protect", true);
|
||||||
|
this.monsterExp = s.getBoolean("monster-exp", false);
|
||||||
|
this.monsterInfight = s.getBoolean("monster-infight", false);
|
||||||
|
this.pvpEnabled = s.getBoolean("pvp-enabled", false);
|
||||||
|
this.foodRegen = s.getBoolean("food-regen", false);
|
||||||
|
this.lockFoodLevel = s.getBoolean("lock-food-level", true);
|
||||||
|
this.allowTeleport = s.getBoolean("allow-teleporting", false);
|
||||||
|
this.canShare = s.getBoolean("share-items-in-arena", true);
|
||||||
|
|
||||||
|
this.allowMonsters = arena.getWorld().getAllowMonsters();
|
||||||
|
|
||||||
|
this.banned = new HashSet<Player>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
if (onBlockDestroy(event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBlockBurn(BlockBurnEvent event) {
|
||||||
|
if (onBlockDestroy(event))
|
||||||
|
return;
|
||||||
|
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onBlockDestroy(BlockEvent event) {
|
||||||
|
if (!arena.getRegion().contains(event.getBlock().getLocation()) || arena.inEditMode() || (!arena.isProtected() && arena.isRunning()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Block b = event.getBlock();
|
||||||
|
if (arena.removeBlock(b) || b.getType() == Material.TNT)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (softRestore && arena.isRunning()) {
|
||||||
|
BlockState state = b.getState();
|
||||||
|
|
||||||
|
Repairable r = null;
|
||||||
|
if (state instanceof ContainerBlock)
|
||||||
|
r = new RepairableContainer(state);
|
||||||
|
else if (state instanceof Sign)
|
||||||
|
r = new RepairableSign(state);
|
||||||
|
else if (state.getData() instanceof Attachable)
|
||||||
|
r = new RepairableAttachable(state);
|
||||||
|
else
|
||||||
|
r = new RepairableBlock(state);
|
||||||
|
|
||||||
|
arena.addRepairable(r);
|
||||||
|
|
||||||
|
if (!softRestoreDrops)
|
||||||
|
b.setTypeId(0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBlockPlace(BlockPlaceEvent event) {
|
||||||
|
Block b = event.getBlock();
|
||||||
|
|
||||||
|
// If the event didn't happen in the region, or if in edit mode, ignore
|
||||||
|
if (!arena.getRegion().contains(b.getLocation()) || arena.inEditMode()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the arena isn't running, or if the player isn't in the arena, cancel.
|
||||||
|
if (!arena.isRunning() || !arena.inArena(event.getPlayer())) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, block was placed during a session.
|
||||||
|
arena.addBlock(b);
|
||||||
|
|
||||||
|
switch (b.getType()){
|
||||||
|
// For doors, add the block just above (so we get both halves)
|
||||||
|
case WOODEN_DOOR:
|
||||||
|
case IRON_DOOR_BLOCK:
|
||||||
|
arena.addBlock(b.getRelative(0, 1, 0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBlockForm(BlockFormEvent event) {
|
||||||
|
if (!arena.getRegion().contains(event.getBlock().getLocation()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If a snowman forms some snow on its path, add the block
|
||||||
|
if (event.getNewState().getType() == Material.SNOW)
|
||||||
|
arena.addBlock(event.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onBlockIgnite(BlockIgniteEvent event) {
|
||||||
|
if (!arena.getRegion().contains(event.getBlock().getLocation()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (event.getCause()){
|
||||||
|
case LIGHTNING:
|
||||||
|
case SPREAD:
|
||||||
|
event.setCancelled(true);
|
||||||
|
break;
|
||||||
|
case FLINT_AND_STEEL:
|
||||||
|
if (arena.isRunning())
|
||||||
|
arena.addBlock(event.getBlock().getRelative(BlockFace.UP));
|
||||||
|
else
|
||||||
|
event.setCancelled(true);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSignChange(SignChangeEvent event) {
|
||||||
|
arena.setLeaderboard(new Leaderboard(plugin, arena, event.getBlock().getLocation()));
|
||||||
|
arena.getRegion().set(RegionPoint.LEADERBOARD, event.getBlock().getLocation());
|
||||||
|
|
||||||
|
Messenger.tellPlayer(event.getPlayer(), "Leaderboard made. Now set up the stat signs!");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onCreatureSpawn(CreatureSpawnEvent event) {
|
||||||
|
if (!arena.getRegion().contains(event.getLocation())) {
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
event.setCancelled(!allowMonsters);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getSpawnReason() != SpawnReason.CUSTOM) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LivingEntity entity = (LivingEntity) event.getEntity();
|
||||||
|
if (arena.isRunning() && entity instanceof Slime)
|
||||||
|
monsters.addMonster(entity);
|
||||||
|
|
||||||
|
// If running == true, setCancelled(false), and vice versa.
|
||||||
|
event.setCancelled(!arena.isRunning());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityExplode(EntityExplodeEvent event) {
|
||||||
|
if (!monsters.getMonsters().contains(event.getEntity()) && !arena.getRegion().contains(event.getLocation(), 10))
|
||||||
|
return;
|
||||||
|
|
||||||
|
monsters.removeMonster(event.getEntity());
|
||||||
|
|
||||||
|
// Cancel if the arena isn't running
|
||||||
|
if (!arena.isRunning()) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Uncancel, just in case.
|
||||||
|
event.setCancelled(false);
|
||||||
|
|
||||||
|
// If the arena isn't destructible, just clear the blocklist.
|
||||||
|
if (!softRestore && protect) {
|
||||||
|
List<Block> blocks = new LinkedList<Block>(arena.getBlocks());
|
||||||
|
event.blockList().retainAll(blocks);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!softRestoreDrops)
|
||||||
|
event.setYield(0);
|
||||||
|
|
||||||
|
// Handle all the blocks in the block list.
|
||||||
|
for (Block b : event.blockList()) {
|
||||||
|
BlockState state = b.getState();
|
||||||
|
|
||||||
|
if (state.getData() instanceof Door && ((Door) state.getData()).isTopHalf()) {
|
||||||
|
state = b.getRelative(BlockFace.DOWN).getState();
|
||||||
|
}
|
||||||
|
else if (state.getData() instanceof Bed && ((Bed) state.getData()).isHeadOfBed()) {
|
||||||
|
state = b.getRelative(((Bed) state.getData()).getFacing().getOppositeFace()).getState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a Repairable from the block.
|
||||||
|
Repairable r = null;
|
||||||
|
if (state instanceof ContainerBlock)
|
||||||
|
r = new RepairableContainer(state);
|
||||||
|
else if (state instanceof Sign)
|
||||||
|
r = new RepairableSign(state);
|
||||||
|
else if (state.getData() instanceof Bed)
|
||||||
|
r = new RepairableBed(state);
|
||||||
|
else if (state.getData() instanceof Door)
|
||||||
|
r = new RepairableDoor(state);
|
||||||
|
else if (state.getData() instanceof Attachable || state.getData() instanceof Redstone)
|
||||||
|
r = new RepairableAttachable(state);
|
||||||
|
else
|
||||||
|
r = new RepairableBlock(state);
|
||||||
|
|
||||||
|
// Cakes and liquids should just get removed. If player-placed block, drop as item.
|
||||||
|
Material mat = state.getType();
|
||||||
|
if (mat == Material.CAKE_BLOCK || mat == Material.WATER || mat == Material.LAVA)
|
||||||
|
arena.removeBlock(b);
|
||||||
|
else if (arena.removeBlock(b))
|
||||||
|
arena.getWorld().dropItemNaturally(b.getLocation(), new ItemStack(state.getTypeId(), 1));
|
||||||
|
else if (softRestore)
|
||||||
|
arena.addRepairable(r);
|
||||||
|
else
|
||||||
|
arena.queueRepairable(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
*
|
||||||
|
* DEATH LISTENERS
|
||||||
|
*
|
||||||
|
******************************************************/
|
||||||
|
|
||||||
|
public void onEntityDeath(EntityDeathEvent event) {
|
||||||
|
if (event instanceof PlayerDeathEvent) {
|
||||||
|
onPlayerDeath((PlayerDeathEvent) event, (Player) event.getEntity());
|
||||||
|
}
|
||||||
|
else if (monsters.removeMonster(event.getEntity())) {
|
||||||
|
onMonsterDeath(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPlayerDeath(PlayerDeathEvent event, Player player) {
|
||||||
|
if (arena.inArena(player) || arena.inLobby(player)) {
|
||||||
|
event.getDrops().clear();
|
||||||
|
event.setDroppedExp(0);
|
||||||
|
event.setKeepLevel(true);
|
||||||
|
arena.playerDeath(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onPlayerRespawn(PlayerRespawnEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
if (!arena.isDead(p)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location loc = arena.getRespawnLocation(p);
|
||||||
|
event.setRespawnLocation(loc);
|
||||||
|
|
||||||
|
arena.playerRespawn(p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onMonsterDeath(EntityDeathEvent event) {
|
||||||
|
EntityDamageEvent e1 = event.getEntity().getLastDamageCause();
|
||||||
|
EntityDamageByEntityEvent e2 = (e1 instanceof EntityDamageByEntityEvent) ? (EntityDamageByEntityEvent) e1 : null;
|
||||||
|
Entity damager = (e2 != null) ? e2.getDamager() : null;
|
||||||
|
|
||||||
|
// Make sure to grab the owner of a projectile/pet
|
||||||
|
if (damager instanceof Projectile) {
|
||||||
|
damager = ((Projectile) damager).getShooter();
|
||||||
|
}
|
||||||
|
else if (damager instanceof Wolf && arena.hasPet(damager)) {
|
||||||
|
damager = (Player) ((Wolf) damager).getOwner();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the damager was a player, add to kills.
|
||||||
|
if (damager instanceof Player) {
|
||||||
|
ArenaPlayer ap = arena.getArenaPlayer((Player) damager);
|
||||||
|
if (ap != null) {
|
||||||
|
ArenaPlayerStatistics stats = ap.getStats();
|
||||||
|
if (stats != null) {
|
||||||
|
ap.getStats().inc("kills");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!monsterExp)
|
||||||
|
event.setDroppedExp(0);
|
||||||
|
|
||||||
|
event.getDrops().clear();
|
||||||
|
|
||||||
|
List<ItemStack> loot = monsters.getLoot(event.getEntity());
|
||||||
|
if (loot != null && !loot.isEmpty()) {
|
||||||
|
event.getDrops().add(getRandomItem(loot));
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ItemStack getRandomItem(List<ItemStack> stacks) {
|
||||||
|
return stacks.get((new Random()).nextInt(stacks.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
*
|
||||||
|
* DAMAGE LISTENERS
|
||||||
|
*
|
||||||
|
******************************************************/
|
||||||
|
|
||||||
|
public void onEntityDamage(EntityDamageEvent event) {
|
||||||
|
Entity damagee = event.getEntity();
|
||||||
|
if (!arena.isRunning() || !arena.getRegion().contains(damagee.getLocation())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EntityDamageByEntityEvent edbe = (event instanceof EntityDamageByEntityEvent) ? (EntityDamageByEntityEvent) event : null;
|
||||||
|
Entity damager = null;
|
||||||
|
|
||||||
|
if (edbe != null) {
|
||||||
|
damager = edbe.getDamager();
|
||||||
|
|
||||||
|
if (damager instanceof Projectile) {
|
||||||
|
damager = ((Projectile) damager).getShooter();
|
||||||
|
}
|
||||||
|
else if (damager instanceof Wolf && arena.hasPet(damager)) {
|
||||||
|
damager = (Player) ((Wolf) damager).getOwner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pet wolf
|
||||||
|
if (damagee instanceof Wolf && arena.hasPet(damagee)) {
|
||||||
|
onPetDamage(event, (Wolf) damagee, damager);
|
||||||
|
}
|
||||||
|
// Player
|
||||||
|
else if (damagee instanceof Player) {
|
||||||
|
onPlayerDamage(event, (Player) damagee, damager);
|
||||||
|
}
|
||||||
|
// Boss
|
||||||
|
else if (monsters.getBossMonsters().contains(damagee)) {
|
||||||
|
onBossDamage(event, (LivingEntity) damagee, damager);
|
||||||
|
}
|
||||||
|
// Regular monster
|
||||||
|
else if (monsters.getMonsters().contains(damagee)) {
|
||||||
|
onMonsterDamage(event, damagee, damager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPlayerDamage(EntityDamageEvent event, Player player, Entity damager) {
|
||||||
|
// Cancel all damage in the lobby and spec area
|
||||||
|
if (arena.inLobby(player) || arena.inSpec(player)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// If PvP is disabled and damager is a player, cancel damage
|
||||||
|
else if (arena.inArena(player)) {
|
||||||
|
if (!pvpEnabled && damager instanceof Player) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.setCancelled(false);
|
||||||
|
arena.getArenaPlayer(player).getStats().add("dmgTaken", event.getDamage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPetDamage(EntityDamageEvent event, Wolf pet, Entity damager) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onMonsterDamage(EntityDamageEvent event, Entity monster, Entity damager) {
|
||||||
|
if (damager instanceof Player) {
|
||||||
|
Player p = (Player) damager;
|
||||||
|
if (!arena.inArena(p)) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArenaPlayerStatistics aps = arena.getArenaPlayer(p).getStats();
|
||||||
|
aps.add("dmgDone", event.getDamage());
|
||||||
|
aps.inc("hits");
|
||||||
|
}
|
||||||
|
else if (damager instanceof Wolf && arena.hasPet(damager)) {
|
||||||
|
event.setDamage(1);
|
||||||
|
Player p = (Player) ((Wolf) damager).getOwner();
|
||||||
|
ArenaPlayerStatistics aps = arena.getArenaPlayer(p).getStats();
|
||||||
|
aps.add("dmgDone", event.getDamage());
|
||||||
|
// arena.getArenaPlayer(p).getStats().dmgDone += event.getDamage();
|
||||||
|
}
|
||||||
|
else if (damager instanceof LivingEntity) {
|
||||||
|
if (!monsterInfight)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onBossDamage(EntityDamageEvent event, LivingEntity monster, Entity damager) {
|
||||||
|
// Health the boss back up.
|
||||||
|
monster.setHealth(monster.getMaxHealth());
|
||||||
|
|
||||||
|
// Damage the underlying MABoss.
|
||||||
|
MABoss boss = monsters.getBoss(monster);
|
||||||
|
boss.damage(event.getDamage());
|
||||||
|
|
||||||
|
// If it died, remove it from the arena.
|
||||||
|
if (boss.isDead()) {
|
||||||
|
monsters.removeBoss(monster);
|
||||||
|
monster.damage(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// And "cancel out" the damage.
|
||||||
|
event.setDamage(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityCombust(EntityCombustEvent event) {
|
||||||
|
if (monsters.getMonsters().contains(event.getEntity()))
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityTarget(EntityTargetEvent event) {
|
||||||
|
if (!arena.isRunning() || event.isCancelled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (arena.hasPet(event.getEntity())) {
|
||||||
|
if (event.getReason() != TargetReason.TARGET_ATTACKED_OWNER && event.getReason() != TargetReason.OWNER_ATTACKED_TARGET)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(event.getTarget() instanceof Player))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the target is a player, cancel.
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (monsters.getMonsters().contains(event.getEntity())) {
|
||||||
|
if (event.getReason() == TargetReason.FORGOT_TARGET)
|
||||||
|
event.setTarget(MAUtils.getClosestPlayer(plugin, event.getEntity(), arena));
|
||||||
|
|
||||||
|
else if (event.getReason() == TargetReason.TARGET_DIED)
|
||||||
|
event.setTarget(MAUtils.getClosestPlayer(plugin, event.getEntity(), arena));
|
||||||
|
|
||||||
|
else if (event.getReason() == TargetReason.TARGET_ATTACKED_ENTITY)
|
||||||
|
if (arena.hasPet(event.getTarget()))
|
||||||
|
event.setCancelled(true);
|
||||||
|
|
||||||
|
else if (event.getReason() == TargetReason.CLOSEST_PLAYER)
|
||||||
|
if (!arena.inArena((Player) event.getTarget()))
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityChangeBlock(EntityChangeBlockEvent event) {
|
||||||
|
if (arena.getRegion().contains(event.getBlock().getLocation()))
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEntityRegainHealth(EntityRegainHealthEvent event) {
|
||||||
|
if (!arena.isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(event.getEntity() instanceof Player) || !arena.inArena((Player) event.getEntity()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!foodRegen && event.getRegainReason() == RegainReason.SATIATED) {
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFoodLevelChange(FoodLevelChangeEvent event) {
|
||||||
|
if (!arena.isRunning())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!(event.getEntity() instanceof Player) || !arena.inArena((Player) event.getEntity()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the food level is locked, cancel all changes.
|
||||||
|
if (lockFoodLevel)
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerAnimation(PlayerAnimationEvent event) {
|
||||||
|
if (!arena.isRunning() || !arena.inArena(event.getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
arena.getArenaPlayer(event.getPlayer()).getStats().inc("swings");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerDropItem(PlayerDropItemEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
|
||||||
|
// If the player is active in the arena, only cancel if sharing is not
|
||||||
|
// allowed
|
||||||
|
if (arena.inArena(p)) {
|
||||||
|
if (!canShare) {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else, if the player is in the lobby or a spectator, just cancel
|
||||||
|
else if (arena.inLobby(p) || arena.inSpec(p)) {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the player is not in the arena in any way (as arena player, lobby
|
||||||
|
* player or a spectator), but they -are- in the region, it must mean
|
||||||
|
* they are trying to drop items when not allowed
|
||||||
|
*/
|
||||||
|
else if (region.contains(p.getLocation())) {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_DROP_ITEM);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the player is in the banned set, it means they got kicked or
|
||||||
|
* disconnected during a session, meaning they are more than likely
|
||||||
|
* trying to steal items, if a PlayerDropItemEvent is fired.
|
||||||
|
*/
|
||||||
|
else if (banned.contains(p)) {
|
||||||
|
Messenger.warning("Player " + p.getName() + " tried to steal class items!");
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerBucketEmpty(PlayerBucketEmptyEvent event) {
|
||||||
|
if (!arena.getReadyPlayersInLobby().contains(event.getPlayer()) && !arena.inArena(event.getPlayer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!arena.isRunning()) {
|
||||||
|
event.getBlockClicked().getRelative(event.getBlockFace()).setTypeId(0);
|
||||||
|
event.setCancelled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Block liquid = event.getBlockClicked().getRelative(event.getBlockFace());
|
||||||
|
arena.addBlock(liquid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerInteract(PlayerInteractEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
if (arena.inArena(p) || !arena.inLobby(p))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Player is in the lobby, so disallow using items.
|
||||||
|
Action a = event.getAction();
|
||||||
|
if (a == Action.RIGHT_CLICK_AIR || a == Action.RIGHT_CLICK_BLOCK) {
|
||||||
|
event.setUseItemInHand(Result.DENY);
|
||||||
|
event.setCancelled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's no block involved, just return.
|
||||||
|
if (!event.hasBlock())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Iron block
|
||||||
|
if (event.getClickedBlock().getTypeId() == 42) {
|
||||||
|
handleReadyBlock(p);
|
||||||
|
}
|
||||||
|
// Sign
|
||||||
|
else if (event.getClickedBlock().getState() instanceof Sign) {
|
||||||
|
Sign sign = (Sign) event.getClickedBlock().getState();
|
||||||
|
handleSign(sign, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleReadyBlock(Player p) {
|
||||||
|
if (arena.getArenaPlayer(p).getArenaClass() != null) {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_PLAYER_READY);
|
||||||
|
arena.playerReady(p);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_PICK_CLASS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSign(Sign sign, Player p) {
|
||||||
|
// Check if the first line is a class name.
|
||||||
|
String className = ChatColor.stripColor(sign.getLine(0)).toLowerCase();
|
||||||
|
|
||||||
|
if (!arena.getClasses().containsKey(className) && !className.equals("random"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check for permission.
|
||||||
|
if (!plugin.has(p, "mobarena.classes." + className) && !className.equals("random")) {
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PERMISSION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay the inventory stuff to ensure that right-clicking works.
|
||||||
|
delayAssignClass(p, className);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void delayAssignClass(final Player p, final String className) {
|
||||||
|
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin,new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
arena.assignClass(p, className);
|
||||||
|
|
||||||
|
if (!className.equalsIgnoreCase("random"))
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_CLASS_PICKED, TextUtils.camelCase(className), arena.getClassLogo(className));
|
||||||
|
else
|
||||||
|
Messenger.tellPlayer(p, Msg.LOBBY_CLASS_RANDOM);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
arena.playerLeave(p);
|
||||||
|
banned.add(p);
|
||||||
|
scheduleUnban(p, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerKick(PlayerKickEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
if (!arena.isEnabled() || (!arena.inArena(p) && !arena.inLobby(p))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arena.playerLeave(p);
|
||||||
|
banned.add(p);
|
||||||
|
scheduleUnban(p, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleUnban(final Player p, int ticks) {
|
||||||
|
plugin.getServer().getScheduler().scheduleSyncDelayedTask(plugin, new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
banned.remove(p);
|
||||||
|
}
|
||||||
|
}, ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeleportResponse onPlayerTeleport(PlayerTeleportEvent event) {
|
||||||
|
if (!arena.isEnabled() || !region.isSetup() || arena.inEditMode() || allowTeleport) {
|
||||||
|
return TeleportResponse.IDGAF;
|
||||||
|
}
|
||||||
|
|
||||||
|
Location to = event.getTo();
|
||||||
|
Location from = event.getFrom();
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
|
||||||
|
if (region.contains(from)) {
|
||||||
|
// Players not in the arena are free to warp out.
|
||||||
|
if (!arena.inArena(p) && !arena.inLobby(p) && !arena.inSpec(p)) {
|
||||||
|
return TeleportResponse.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Covers the case in which both locations are in the arena.
|
||||||
|
if (region.contains(to) || region.isWarp(to) || to.equals(arena.getPlayerEntry(p))) {
|
||||||
|
return TeleportResponse.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
Messenger.tellPlayer(p, Msg.WARP_FROM_ARENA);
|
||||||
|
return TeleportResponse.REJECT;
|
||||||
|
}
|
||||||
|
else if (region.contains(to)) {
|
||||||
|
if (region.isWarp(from) || region.isWarp(to) || to.equals(arena.getPlayerEntry(p))) {
|
||||||
|
return TeleportResponse.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
Messenger.tellPlayer(p, Msg.WARP_TO_ARENA);
|
||||||
|
return TeleportResponse.REJECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TeleportResponse.IDGAF;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event) {
|
||||||
|
Player p = event.getPlayer();
|
||||||
|
|
||||||
|
if (event.isCancelled() || (!arena.inArena(p) && !arena.inLobby(p))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is safe, because commands will always have at least one element.
|
||||||
|
String base = event.getMessage().split(" ")[0];
|
||||||
|
|
||||||
|
// Check if the entire base command is allowed.
|
||||||
|
if (plugin.getArenaMaster().isAllowed(base)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not, check if the specific command is allowed.
|
||||||
|
String noslash = event.getMessage().substring(1);
|
||||||
|
if (plugin.getArenaMaster().isAllowed(noslash)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is dirty, but it ensures that commands are indeed blocked.
|
||||||
|
event.setMessage("/");
|
||||||
|
|
||||||
|
// Cancel the event regardless.
|
||||||
|
event.setCancelled(true);
|
||||||
|
Messenger.tellPlayer(p, Msg.MISC_COMMAND_NOT_ALLOWED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPlayerPreLogin(PlayerPreLoginEvent event) {
|
||||||
|
Player p = plugin.getServer().getPlayer(event.getName());
|
||||||
|
if (p == null || !p.isOnline()) return;
|
||||||
|
|
||||||
|
Arena arena = plugin.getArenaMaster().getArenaWithPlayer(p);
|
||||||
|
if (arena == null) return;
|
||||||
|
|
||||||
|
arena.playerLeave(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.garbagemule.MobArena.waves.ability;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
import com.garbagemule.MobArena.waves.MABoss;
|
||||||
|
|
||||||
|
public interface Ability
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Execute the boss ability.
|
||||||
|
* The ability should be concise and not start any unnecessary threading,
|
||||||
|
* or schedule any unnecessary tasks.
|
||||||
|
* The MABoss object can be used to get the LivingEntity that is the boss,
|
||||||
|
* and to damage, heal or just set the boss health directly.
|
||||||
|
* @param arena the Arena of the boss
|
||||||
|
* @param boss the MABoss object
|
||||||
|
*/
|
||||||
|
public void execute(Arena arena, MABoss boss);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.garbagemule.MobArena.waves.ability;
|
||||||
|
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;;
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface AbilityInfo
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The "pretty print" name of the ability.
|
||||||
|
* This value is printed when a boss executes the ability in the arena.
|
||||||
|
*/
|
||||||
|
public String name();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The config aliases for the ability.
|
||||||
|
* This is used by MobArena to parse ability names from the config-file.
|
||||||
|
*/
|
||||||
|
public String[] aliases();
|
||||||
|
}
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
package com.garbagemule.MobArena.waves.ability;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.StandardJavaFileManager;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.Messenger;
|
||||||
|
import com.garbagemule.MobArena.util.FileUtils;
|
||||||
|
|
||||||
|
public class AbilityManager
|
||||||
|
{
|
||||||
|
private static final String jarpath = "." + File.separator + "plugins" + File.separator + "MobArena.jar";
|
||||||
|
private static final String classpath = jarpath + ";" + System.getProperty("java.class.path");
|
||||||
|
|
||||||
|
private static Map<String,Ability> abilities;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an Ability by one of its aliases.
|
||||||
|
* @param name an Ability alias
|
||||||
|
* @return an Ability, if one exists with the given alias, false otherwise
|
||||||
|
*/
|
||||||
|
public static Ability fromString(String name) {
|
||||||
|
return abilities.get(name.toLowerCase().replaceAll("[-_.]", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load the known abilities as well as all custom abilities from
|
||||||
|
* the specified directory.
|
||||||
|
* @param dir a directory of .class (and/or .java) files
|
||||||
|
*/
|
||||||
|
public static void loadAbilities(File classDir) {
|
||||||
|
abilities = new HashMap<String,Ability>();
|
||||||
|
|
||||||
|
// Extract all of the source files.
|
||||||
|
File javaDir = new File(classDir, "src");
|
||||||
|
extractSourceFiles(javaDir);
|
||||||
|
|
||||||
|
// The custom abilities to compile will be in the 'src'-dir
|
||||||
|
compileAbilities(javaDir, classDir);
|
||||||
|
|
||||||
|
// Load all the custom abilities.
|
||||||
|
loadClasses(classDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void extractSourceFiles(File javaDir) {
|
||||||
|
// Only extract the files if the folder doesn't exist.
|
||||||
|
if (javaDir.exists()) return;
|
||||||
|
|
||||||
|
String path = "abilities/";
|
||||||
|
|
||||||
|
List<String> files = new ArrayList<String>();
|
||||||
|
|
||||||
|
files.add(path + "ChainLightning.java");
|
||||||
|
files.add(path + "LivingBomb.java");
|
||||||
|
files.add(path + "ObsidianBomb.java");
|
||||||
|
files.add(path + "Flood.java");
|
||||||
|
files.add(path + "WarpToPlayer.java");
|
||||||
|
files.add(path + "RootTarget.java");
|
||||||
|
files.add(path + "ShufflePositions.java");
|
||||||
|
|
||||||
|
files.add(path + "ShootArrow.java");
|
||||||
|
files.add(path + "ShootFireball.java");
|
||||||
|
|
||||||
|
files.add(path + "FireAura.java");
|
||||||
|
files.add(path + "LightningAura.java");
|
||||||
|
|
||||||
|
files.add(path + "DisorientDistant.java");
|
||||||
|
files.add(path + "DisorientNearby.java");
|
||||||
|
files.add(path + "DisorientTarget.java");
|
||||||
|
|
||||||
|
files.add(path + "PullDistant.java");
|
||||||
|
files.add(path + "PullNearby.java");
|
||||||
|
files.add(path + "PullTarget.java");
|
||||||
|
|
||||||
|
files.add(path + "ThrowDistant.java");
|
||||||
|
files.add(path + "ThrowNearby.java");
|
||||||
|
files.add(path + "ThrowTarget.java");
|
||||||
|
|
||||||
|
FileUtils.extractResources(javaDir, files.toArray(new String[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void compileAbilities(File javaDir, File classDir) {
|
||||||
|
if (!javaDir.exists()) return;
|
||||||
|
|
||||||
|
// Make ready a new list of files to compile.
|
||||||
|
List<File> toCompile = getSourceFilesToCompile(javaDir, classDir);
|
||||||
|
|
||||||
|
// No files to compile?
|
||||||
|
if (toCompile.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the compiler and the file manager
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
|
||||||
|
|
||||||
|
// Generate some JavaFileObjects
|
||||||
|
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(toCompile);
|
||||||
|
|
||||||
|
// Include the MobArena.jar on the classpath, and set the destination folder.
|
||||||
|
List<String> options = Arrays.asList("-classpath", classpath, "-d", classDir.getPath());
|
||||||
|
|
||||||
|
// Set up the compilation task.
|
||||||
|
JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, null, options, null, compilationUnits);
|
||||||
|
|
||||||
|
// Call the task.
|
||||||
|
task.call();
|
||||||
|
|
||||||
|
// And close the file manager.
|
||||||
|
try {
|
||||||
|
fileManager.close();
|
||||||
|
}
|
||||||
|
catch (Exception e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<File> getSourceFilesToCompile(File javaDir, File classDir) {
|
||||||
|
List<File> result = new ArrayList<File>();
|
||||||
|
|
||||||
|
if (javaDir == null || !javaDir.exists()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Grab the array of compiled files.
|
||||||
|
File[] classFiles = classDir.listFiles();
|
||||||
|
|
||||||
|
// Go through each source file.
|
||||||
|
for (File javaFile : javaDir.listFiles()) {
|
||||||
|
// Skip if it's not a .java file.
|
||||||
|
if (!javaFile.getName().endsWith(".java")) {
|
||||||
|
Messenger.info("Found invalid ability file: " + javaFile.getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the associated .class file.
|
||||||
|
File classFile = findClassFile(javaFile, classFiles);
|
||||||
|
|
||||||
|
// If the .class file is newer, we don't need to compile.
|
||||||
|
if (isClassFileNewer(javaFile, classFile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result.add(javaFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File findClassFile(File javaFile, File[] classFiles) {
|
||||||
|
String javaFileName = javaFile.getName();
|
||||||
|
String classFileName = javaFileName.substring(0, javaFileName.lastIndexOf(".")) + ".class";
|
||||||
|
|
||||||
|
for (File classFile : classFiles) {
|
||||||
|
if (classFile.getName().equals(classFileName)) {
|
||||||
|
return classFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isClassFileNewer(File javaFile, File classFile) {
|
||||||
|
if (classFile == null) return false;
|
||||||
|
|
||||||
|
return (classFile.lastModified() > javaFile.lastModified());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (Compiles and) loads all custom abilities in the given directory.
|
||||||
|
* @param dir a directory
|
||||||
|
*/
|
||||||
|
private static void loadClasses(File classDir) {
|
||||||
|
// Grab the class loader
|
||||||
|
ClassLoader loader = getLoader(classDir);
|
||||||
|
if (loader == null) return;
|
||||||
|
|
||||||
|
StringBuffer buffy = new StringBuffer();
|
||||||
|
|
||||||
|
for (File file : classDir.listFiles()) {
|
||||||
|
String filename = file.getName();
|
||||||
|
|
||||||
|
// Only load .class files.
|
||||||
|
int dot = filename.lastIndexOf(".class");
|
||||||
|
if (dot < 0) continue;
|
||||||
|
|
||||||
|
// Trim off the .class extension
|
||||||
|
String name = filename.substring(0, file.getName().lastIndexOf("."));
|
||||||
|
|
||||||
|
// And make an Ability.
|
||||||
|
Ability ability = makeAbility(loader, name);
|
||||||
|
if (ability == null) continue;
|
||||||
|
|
||||||
|
// Then load the ability into the map.
|
||||||
|
String abilityName = loadAbility(ability);
|
||||||
|
|
||||||
|
if (abilityName != null) {
|
||||||
|
buffy.append(", " + abilityName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an Ability into the abilities map by all of its aliases.
|
||||||
|
* @param ability an Ability
|
||||||
|
* @return the first alias of
|
||||||
|
*/
|
||||||
|
private static String loadAbility(Ability ability) {
|
||||||
|
// Grab the annotation.
|
||||||
|
AbilityInfo info = ability.getClass().getAnnotation(AbilityInfo.class);
|
||||||
|
if (info == null) return null;
|
||||||
|
|
||||||
|
// Put the command in the map with each of its aliases.
|
||||||
|
for (String name : info.aliases()) {
|
||||||
|
abilities.put(name, ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info.aliases()[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ask the given ClassLoader to load the ability with the given name.
|
||||||
|
* @param loader a ClassLoader
|
||||||
|
* @param name a class name
|
||||||
|
* @return an Ability, if the ClassLoader found one with the given name, null otherwise
|
||||||
|
*/
|
||||||
|
private static Ability makeAbility(ClassLoader loader, String name) {
|
||||||
|
try {
|
||||||
|
// Load the class.
|
||||||
|
Class<?> c = loader.loadClass(name);
|
||||||
|
|
||||||
|
// Create an instance of it.
|
||||||
|
Object o = c.newInstance();
|
||||||
|
|
||||||
|
// If it's an ability, return it.
|
||||||
|
if (o instanceof Ability) {
|
||||||
|
return (Ability) o;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {}
|
||||||
|
|
||||||
|
// Otherwise, return null.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a ClassLoader for the given directory.
|
||||||
|
* @param dir a directory
|
||||||
|
* @return a ClassLoader, or null
|
||||||
|
*/
|
||||||
|
private static ClassLoader getLoader(File dir) {
|
||||||
|
try {
|
||||||
|
ClassLoader loader = new URLClassLoader(new URL[] { dir.toURI().toURL() }, Ability.class.getClassLoader());
|
||||||
|
return loader;
|
||||||
|
}
|
||||||
|
catch (Exception e) {}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn an array of aliases into a comma-separated string of aliases.
|
||||||
|
* @param aliases an array of Strings
|
||||||
|
* @return a comma-separated String
|
||||||
|
*/
|
||||||
|
/*private static String aliasString(String[] aliases) {
|
||||||
|
StringBuffer buffy = new StringBuffer();
|
||||||
|
for (String a : aliases) {
|
||||||
|
buffy.append(a + ", ");
|
||||||
|
}
|
||||||
|
return buffy.substring(0, buffy.length() - 2);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
package com.garbagemule.MobArena.waves.ability;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Creature;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import com.garbagemule.MobArena.MAUtils;
|
||||||
|
import com.garbagemule.MobArena.framework.Arena;
|
||||||
|
|
||||||
|
public class AbilityUtils
|
||||||
|
{
|
||||||
|
public static Random random = new Random();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the target player of the LivingEntity if possible.
|
||||||
|
* @param the arena
|
||||||
|
* @param entity The entity whose target to get
|
||||||
|
* @param random Grab a random player if no target was found
|
||||||
|
* @return The target player, or null
|
||||||
|
*/
|
||||||
|
public static LivingEntity getTarget(Arena arena, LivingEntity entity, boolean random) {
|
||||||
|
if (entity instanceof Creature) {
|
||||||
|
LivingEntity target = ((Creature) entity).getTarget();
|
||||||
|
|
||||||
|
if (target instanceof Player) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (random) {
|
||||||
|
return getRandomPlayer(arena);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a random arena player.
|
||||||
|
* @param arena the arena
|
||||||
|
* @return a random arena player, or null if none were found
|
||||||
|
*/
|
||||||
|
public static Player getRandomPlayer(Arena arena) {
|
||||||
|
List<Player> list = new ArrayList<Player>(arena.getPlayersInArena());
|
||||||
|
if (list.isEmpty()) return null;
|
||||||
|
|
||||||
|
return list.get(random.nextInt(list.size()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of nearby players
|
||||||
|
* @param arena the arena
|
||||||
|
* @param boss the boss
|
||||||
|
* @param x the 'radius' in which to grab players
|
||||||
|
* @return a list of nearby players
|
||||||
|
*/
|
||||||
|
public static List<Player> getNearbyPlayers(Arena arena, Entity boss, int x) {
|
||||||
|
List<Player> result = new ArrayList<Player>();
|
||||||
|
for (Entity e : boss.getNearbyEntities(x, x, x)) {
|
||||||
|
if (arena.getPlayersInArena().contains(e)) {
|
||||||
|
result.add((Player) e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of distant players
|
||||||
|
* @param arena the arena
|
||||||
|
* @param boss the boss
|
||||||
|
* @param x the 'radius' in which to exclude players
|
||||||
|
* @return a list of distant players
|
||||||
|
*/
|
||||||
|
public static List<Player> getDistantPlayers(Arena arena, Entity boss, int x) {
|
||||||
|
List<Player> result = new ArrayList<Player>();
|
||||||
|
for (Player p : arena.getPlayersInArena()) {
|
||||||
|
if (MAUtils.distanceSquared(arena.getPlugin(), p, boss.getLocation()) > (double) (x*x)) {
|
||||||
|
result.add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user