userUUID;
+ private final Timer timer;
+
+ public TimerClearEvent(Timer timer) {
+ this.userUUID = Optional.absent();
+ this.timer = timer;
+ }
+
+ public TimerClearEvent(UUID userUUID, Timer timer) {
+ this.userUUID = Optional.of(userUUID);
+ this.timer = timer;
+ }
+
+ /**
+ * Gets the optional UUID of the user this was removed for.
+ *
+ * This may return absent if the timer is not of a player type
+ *
+ *
+ * @return the removed user UUID or {@link Optional#absent()}
+ */
+ public Optional getUserUUID() {
+ return userUUID;
+ }
+
+ /**
+ * Gets the {@link Timer} that was expired.
+ *
+ * @return the expiring timer
+ */
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/TimerExpireEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/TimerExpireEvent.java
new file mode 100644
index 0000000..b4d7dd2
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/events/TimerExpireEvent.java
@@ -0,0 +1,59 @@
+package me.redis.bunkers.events;
+
+import com.google.common.base.Optional;
+import me.redis.bunkers.timer.Timer;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.UUID;
+
+/**
+ * Event called when a {@link Timer} expires.
+ */
+public class TimerExpireEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private final Optional userUUID;
+ private final Timer timer;
+
+ public TimerExpireEvent(Timer timer) {
+ this.userUUID = Optional.absent();
+ this.timer = timer;
+ }
+
+ public TimerExpireEvent(UUID userUUID, Timer timer) {
+ this.userUUID = Optional.fromNullable(userUUID);
+ this.timer = timer;
+ }
+
+ /**
+ * Gets the optional UUID of the user this has expired for.
+ *
+ * This may return absent if the timer is not of a player type
+ *
+ *
+ * @return the expiring user UUID or {@link Optional#absent()}
+ */
+ public Optional getUserUUID() {
+ return userUUID;
+ }
+
+ /**
+ * Gets the {@link Timer} that was expired.
+ *
+ * @return the expiring timer
+ */
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/TimerExtendEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/TimerExtendEvent.java
new file mode 100644
index 0000000..ef66e09
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/events/TimerExtendEvent.java
@@ -0,0 +1,98 @@
+package me.redis.bunkers.events;
+
+import com.google.common.base.Optional;
+import me.redis.bunkers.timer.Timer;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import javax.annotation.Nullable;
+import java.util.UUID;
+
+/**
+ * Event called when a {@link Timer} is extended.
+ */
+public class TimerExtendEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private boolean cancelled;
+ private final Optional player;
+ private final Optional userUUID;
+ private final Timer timer;
+ private final long previousDuration;
+ private long newDuration;
+
+ public TimerExtendEvent(Timer timer, long previousDuration, long newDuration) {
+ this.player = Optional.absent();
+ this.userUUID = Optional.absent();
+ this.timer = timer;
+ this.previousDuration = previousDuration;
+ this.newDuration = newDuration;
+ }
+
+ public TimerExtendEvent(@Nullable Player player, UUID uniqueId, Timer timer, long previousDuration, long newDuration) {
+ this.player = Optional.fromNullable(player);
+ this.userUUID = Optional.fromNullable(uniqueId);
+ this.timer = timer;
+ this.previousDuration = previousDuration;
+ this.newDuration = newDuration;
+ }
+
+ public Optional getPlayer() {
+ return player;
+ }
+
+ /**
+ * Gets the optional UUID of the user this was removed for.
+ *
+ * This may return absent if the timer is not of a player type
+ *
+ *
+ * @return the removed user UUID or {@link Optional#absent()}
+ */
+ public Optional getUserUUID() {
+ return userUUID;
+ }
+
+ /**
+ * Gets the {@link Timer} that was expired.
+ *
+ * @return the expiring timer
+ */
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public long getPreviousDuration() {
+ return previousDuration;
+ }
+
+ public long getNewDuration() {
+ return newDuration;
+ }
+
+ public void setNewDuration(long newDuration) {
+ this.newDuration = newDuration;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/TimerPauseEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/TimerPauseEvent.java
new file mode 100644
index 0000000..d86c26e
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/events/TimerPauseEvent.java
@@ -0,0 +1,78 @@
+package me.redis.bunkers.events;
+
+import com.google.common.base.Optional;
+import me.redis.bunkers.timer.Timer;
+import org.bukkit.event.Cancellable;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import java.util.UUID;
+
+/**
+ * Event called when the pause state of a {@link Timer} changes.
+ */
+public class TimerPauseEvent extends Event implements Cancellable {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private boolean cancelled;
+ private final boolean paused;
+ private final Optional userUUID;
+ private final Timer timer;
+
+ public TimerPauseEvent(Timer timer, boolean paused) {
+ this.userUUID = Optional.absent();
+ this.timer = timer;
+ this.paused = paused;
+ }
+
+ public TimerPauseEvent(UUID userUUID, Timer timer, boolean paused) {
+ this.userUUID = Optional.fromNullable(userUUID);
+ this.timer = timer;
+ this.paused = paused;
+ }
+
+ /**
+ * Gets the optional UUID of the user this has expired for.
+ *
+ * This may return absent if the timer is not of a player type
+ *
+ *
+ * @return the expiring user UUID or {@link Optional#absent()}
+ */
+ public Optional getUserUUID() {
+ return userUUID;
+ }
+
+ /**
+ * Gets the {@link Timer} that was expired.
+ *
+ * @return the expiring timer
+ */
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ public boolean isPaused() {
+ return paused;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+
+ @Override
+ public boolean isCancelled() {
+ return cancelled;
+ }
+
+ @Override
+ public void setCancelled(boolean cancelled) {
+ this.cancelled = cancelled;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/TimerStartEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/TimerStartEvent.java
new file mode 100644
index 0000000..603632d
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/events/TimerStartEvent.java
@@ -0,0 +1,75 @@
+package me.redis.bunkers.events;
+
+import com.google.common.base.Optional;
+import me.redis.bunkers.timer.Timer;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Event;
+import org.bukkit.event.HandlerList;
+
+import javax.annotation.Nullable;
+import java.util.UUID;
+
+/**
+ * Event called when a {@link Timer} starts.
+ */
+public class TimerStartEvent extends Event {
+
+ private static final HandlerList handlers = new HandlerList();
+
+ private final Optional player;
+ private final Optional userUUID;
+ private final Timer timer;
+ private final long duration;
+
+ public TimerStartEvent(Timer timer, final long duration) {
+ this.player = Optional.absent();
+ this.userUUID = Optional.absent();
+ this.timer = timer;
+ this.duration = duration;
+ }
+
+ public TimerStartEvent(@Nullable Player player, UUID uniqueId, Timer timer, long duration) {
+ this.player = Optional.fromNullable(player);
+ this.userUUID = Optional.fromNullable(uniqueId);
+ this.timer = timer;
+ this.duration = duration;
+ }
+
+ public Optional getPlayer() {
+ return player;
+ }
+
+ /**
+ * Gets the optional UUID of the user this has expired for.
+ *
+ * This may return absent if the timer is not of a player type
+ *
+ *
+ * @return the expiring user UUID or {@link Optional#absent()}
+ */
+ public Optional getUserUUID() {
+ return userUUID;
+ }
+
+ /**
+ * Gets the {@link Timer} that was expired.
+ *
+ * @return the expiring timer
+ */
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public long getDuration() {
+ return duration;
+ }
+
+ public static HandlerList getHandlerList() {
+ return handlers;
+ }
+
+ @Override
+ public HandlerList getHandlers() {
+ return handlers;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/game/GameManager.java b/Bunkers/src/main/java/me/redis/bunkers/game/GameManager.java
new file mode 100644
index 0000000..db7248f
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/game/GameManager.java
@@ -0,0 +1,112 @@
+package me.redis.bunkers.game;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.events.GameStatusChangeEvent;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import me.redis.bunkers.tasks.GameTimeTask;
+import me.redis.bunkers.tasks.KothTask;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class GameManager {
+ @Getter private Bunkers bunkers = Bunkers.getPlugin();
+ @Getter private GameStatus status;
+ @Getter @Setter private Boolean started = false;
+ @Getter @Setter private long gameTime;
+ @Getter @Setter private boolean event = false;
+ @Getter private int scoreboard = 0;
+ @Getter @Setter private String eventName = "Custom Event";
+ @Getter @Setter private Team winnerTeam;
+
+ public GameManager() {
+ Bukkit.getScheduler().runTaskTimerAsynchronously(Bunkers.getPlugin(), () -> {
+ if (event) {
+ if (scoreboard == 0) {
+ scoreboard = 1;
+ } else if (scoreboard == 1) {
+ scoreboard = 0;
+ }
+ }
+ }, 20L, 20 * 3L);
+
+ }
+
+ public void setStatus(GameStatus status) {
+ Bukkit.getPluginManager().callEvent(new GameStatusChangeEvent(this.status, status));
+ this.status = status;
+ }
+
+ public boolean canBePlayed() {
+ return bunkers.getTeamManager().canBePlayed();
+ }
+
+ @Getter private final int[] cooldown = {30};
+ public void startCooldown() {
+ setStatus(GameStatus.STARTING);
+ setStarted(true);
+
+ new BukkitRunnable() {
+ @Override public void run() {
+ if (cooldown[0] <= 0) {
+ startGame();
+
+ cancel();
+ } else {
+ if (cooldown[0] % 5 == 0) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&eThe match will start in &9" + cooldown[0] + " seconds&e."));
+ }
+ }
+
+ cooldown[0]--;
+ }
+ }.runTaskTimer(Bunkers.getPlugin(), 20L, 20L);
+ }
+
+ public void startGame() {
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player);
+
+ player.teleport(LocationUtils.getLocation(team.getSpawnLocation()));
+ player.getInventory().clear();
+ player.getInventory().setItem(0, new ItemStack(Material.STONE_PICKAXE));
+ player.getInventory().setItem(1, new ItemStack(Material.STONE_AXE));
+ setStatus(GameStatus.PLAYING);
+ profile.setStatus(PlayerStatus.PLAYING);
+ profile.setGamesPlayed(profile.getGamesPlayed() + 1);
+ profile.setBalance(500);
+ profile.save();
+ team.setDtr(team.getMembers().size());
+
+ player.sendMessage(ChatColor.GREEN + "The match has started...");
+ } else {
+ player.kickPlayer(ChatColor.RED + "You must have a team to play.");
+ }
+ }
+
+ Bukkit.getScheduler().scheduleAsyncRepeatingTask(Bunkers.getPlugin(), () -> {
+ Bukkit.getOnlinePlayers().forEach(player -> {
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ if (profile.getStatus() == PlayerStatus.PLAYING) {
+ profile.setBalance(profile.getBalance() + 3);
+ }
+ });
+ }, 0L, 20 * 3L);
+
+ new GameTimeTask().runTaskTimerAsynchronously(Bunkers.getPlugin(), 20L, 20L);
+ Bukkit.getScheduler().runTaskLater(Bunkers.getPlugin(), () -> new KothTask().runTaskTimer(Bunkers.getPlugin(), 20L, 20L), 20 * 60 * 5);
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/game/status/GameStatus.java b/Bunkers/src/main/java/me/redis/bunkers/game/status/GameStatus.java
new file mode 100644
index 0000000..bcaf4c8
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/game/status/GameStatus.java
@@ -0,0 +1,5 @@
+package me.redis.bunkers.game.status;
+
+public enum GameStatus {
+ WAITING, STARTING, PLAYING, ENDING
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/Information.java b/Bunkers/src/main/java/me/redis/bunkers/information/Information.java
new file mode 100644
index 0000000..3dc64bf
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/Information.java
@@ -0,0 +1,68 @@
+package me.redis.bunkers.information;
+
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.model.Filters;
+import lombok.Getter;
+import lombok.Setter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.LocationUtils;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.bukkit.Location;
+
+@Getter
+public class Information {
+ @Setter private String lobbyLocation, kothFirstLocation, kothSecondLocation;
+ @Setter private String serverName;
+ @Setter private int minPlayers = 5;
+ @Setter private String address = "none";
+
+ public Information() {
+ load();
+ }
+
+
+ public void load() {
+ Document document = (Document) Bunkers.getPlugin().getInformationCollection().find(Filters.eq("_id", "Information")).first();
+
+ if (document == null) return;
+
+ lobbyLocation = document.getString("lobbyLocation");
+ serverName = document.getString("serverName");
+ kothFirstLocation = document.getString("kothFirstLocation");
+ kothSecondLocation = document.getString("kothSecondLocation");
+ minPlayers = document.getInteger("minPlayers");
+ address = document.getString("address");
+ }
+
+ public void save() {
+ Document document = new Document("_id", "Information");
+
+ document.put("lobbyLocation", lobbyLocation);
+ document.put("serverName", serverName);
+ document.put("kothFirstLocation", kothFirstLocation);
+ document.put("kothSecondLocation", kothSecondLocation);
+ document.put("minPlayers", minPlayers);
+ document.put("address", address);
+
+ Bson filter = Filters.eq("_id", "Information");
+ FindIterable iterable = Bunkers.getPlugin().getInformationCollection().find(filter);
+
+ if (iterable.first() == null) {
+ Bunkers.getPlugin().getInformationCollection().insertOne(document);
+ } else {
+ Bunkers.getPlugin().getInformationCollection().replaceOne(filter, document);
+ }
+
+ Bunkers.getPlugin().getInformationManager().setInformation(this);
+ }
+
+ public Cuboid getKothCuboid() {
+ return new Cuboid(LocationUtils.getLocation(kothFirstLocation), LocationUtils.getLocation(kothSecondLocation));
+ }
+
+ public Location getKothCenter() {
+ return getKothCuboid().getCenter();
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/InformationManager.java b/Bunkers/src/main/java/me/redis/bunkers/information/InformationManager.java
new file mode 100644
index 0000000..03ceb80
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/InformationManager.java
@@ -0,0 +1,12 @@
+package me.redis.bunkers.information;
+
+import lombok.Getter;
+import lombok.Setter;
+
+public class InformationManager {
+ @Getter @Setter public Information information;
+
+ public InformationManager() {
+ setInformation(new Information());
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/InformationCommand.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/InformationCommand.java
new file mode 100644
index 0000000..ef6953e
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/InformationCommand.java
@@ -0,0 +1,19 @@
+package me.redis.bunkers.information.commands;
+
+import me.redis.bunkers.information.commands.argments.*;
+import me.redis.bunkers.utils.command.ExecutableCommand;
+
+public class InformationCommand extends ExecutableCommand {
+ public InformationCommand() {
+ super("information", null, "info", "bunkers");
+
+ addArgument(new ShowArgument());
+ addArgument(new SetSpawnArgument());
+ addArgument(new SetKothAreaArgument());
+ addArgument(new SetMinimumPlayersArgument());
+ addArgument(new SetServerNameArgument());
+ addArgument(new SetAddressArgument());
+ addArgument(new SetEventArgument());
+ addArgument(new SetEventNameArgument());
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetAddressArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetAddressArgument.java
new file mode 100644
index 0000000..6dc8da9
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetAddressArgument.java
@@ -0,0 +1,42 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.JavaUtils;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetAddressArgument extends CommandArgument {
+ public SetAddressArgument() {
+ super("setaddress", null, "setip");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+ information.setAddress(args[1]);
+ information.save();
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have the server's address. &7&o(You can check it by /information show)"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventArgument.java
new file mode 100644
index 0000000..cc5616c
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventArgument.java
@@ -0,0 +1,47 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.GameManager;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.JavaUtils;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetEventArgument extends CommandArgument {
+ public SetEventArgument() {
+ super("setgameevent", null, "setevent");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ if (!JavaUtils.isBoolean(args[1])) {
+ player.sendMessage(ChatColor.RED + "You must introduce true/false.");
+ return true;
+ }
+
+ GameManager manager = Bunkers.getPlugin().getGameManager();
+ manager.setEvent(Boolean.parseBoolean(args[1]));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eThis is now an event match. &7&o(You can check them by /information show)"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventNameArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventNameArgument.java
new file mode 100644
index 0000000..a204090
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetEventNameArgument.java
@@ -0,0 +1,42 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.GameManager;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.JavaUtils;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetEventNameArgument extends CommandArgument {
+ public SetEventNameArgument() {
+ super("seteventname");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length < 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ GameManager manager = Bunkers.getPlugin().getGameManager();
+ manager.setEventName(StringUtils.join(args, " ", 1, args.length));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have set the event name. &7&o(You can check them by /information show)"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetKothAreaArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetKothAreaArgument.java
new file mode 100644
index 0000000..a7b6aa4
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetKothAreaArgument.java
@@ -0,0 +1,57 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.protocol.ClaimPillar;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetKothAreaArgument extends CommandArgument {
+ public SetKothAreaArgument() {
+ super("setkotharea", null, "area");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName();
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 1) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Wand wand = Bunkers.getPlugin().getWandManager().getWand(player);
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+
+ if (wand == null || wand.getFirstLocation() == null || wand.getSecondLocation() == null) {
+ player.sendMessage(ChatColor.RED + "You must have wand locations.");
+ return true;
+ }
+
+ information.setKothFirstLocation(LocationUtils.getString(wand.getFirstLocation()));
+ information.setKothSecondLocation(LocationUtils.getString(wand.getSecondLocation()));
+ information.save();
+
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+ profile.getFirstPillar().removePillar();
+ profile.setFirstPillar(null);
+
+ profile.getSecondPillar().removePillar();
+ profile.setSecondPillar(null);
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the koth coordinates. &7&o(You can check them by /information show)"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetMinimumPlayersArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetMinimumPlayersArgument.java
new file mode 100644
index 0000000..77f7538
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetMinimumPlayersArgument.java
@@ -0,0 +1,47 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.JavaUtils;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetMinimumPlayersArgument extends CommandArgument {
+ public SetMinimumPlayersArgument() {
+ super("setminplayers", null, "minplayers");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ if (!JavaUtils.isInteger(args[1])) {
+ player.sendMessage(ChatColor.RED + "You must introduce a number");
+ return true;
+ }
+
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+ information.setMinPlayers(Integer.parseInt(args[1]));
+ information.save();
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the minimum players to start. &7&o(You can check them by /information show)"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetServerNameArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetServerNameArgument.java
new file mode 100644
index 0000000..e7e469a
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetServerNameArgument.java
@@ -0,0 +1,41 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetServerNameArgument extends CommandArgument {
+ public SetServerNameArgument() {
+ super("setservername", null, "sername");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+ information.setServerName(args[1]);
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the server name. &7&o(You can check them by /information show)"));
+ information.save();
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetSpawnArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetSpawnArgument.java
new file mode 100644
index 0000000..2eb29d7
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/SetSpawnArgument.java
@@ -0,0 +1,42 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetSpawnArgument extends CommandArgument {
+ public SetSpawnArgument() {
+ super("setspawn", null, "setspawnlocation");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName();
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 1) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+
+ information.setLobbyLocation(LocationUtils.getString(player.getLocation().add(0.5, 0.5, 0.5)));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the spawn coordinates. &7&o(You can check them by /information show)"));
+ information.save();
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/ShowArgument.java b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/ShowArgument.java
new file mode 100644
index 0000000..5381d8f
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/information/commands/argments/ShowArgument.java
@@ -0,0 +1,58 @@
+package me.redis.bunkers.information.commands.argments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.information.Information;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class ShowArgument extends CommandArgument {
+ public ShowArgument() {
+ super("show", null, "who", "i", "info");
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName();
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 1) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Information information = Bunkers.getPlugin().getInformationManager().getInformation();
+ Location lobby = LocationUtils.getLocation(information.getLobbyLocation());
+
+ if (lobby == null) {
+ player.sendMessage(ChatColor.RED + "You must set the spawn location.");
+ return true;
+ }
+
+ if (information.getKothFirstLocation() == null || information.getKothSecondLocation() == null) {
+ player.sendMessage(ChatColor.RED + "You must set the koth location.");
+ return true;
+ }
+
+ Location koth = information.getKothCenter();
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------"));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6&nInformation"));
+ player.sendMessage("");
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &eSpawn location&7: &f" + lobby.getBlockX() + ", " + lobby.getBlockZ()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &eKoth location&7: &f" + koth.getBlockX() + ", " + koth.getBlockZ()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/koth/Koth.java b/Bunkers/src/main/java/me/redis/bunkers/koth/Koth.java
new file mode 100644
index 0000000..f561b8c
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/koth/Koth.java
@@ -0,0 +1,37 @@
+package me.redis.bunkers.koth;
+
+import lombok.Getter;
+import lombok.Setter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.tasks.GameTimeTask;
+import me.redis.bunkers.utils.BukkitUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class Koth implements Listener {
+ @Getter @Setter private int seconds = 600;
+ @Getter @Setter private int capSeconds = 600;
+ @Getter @Setter Player controller;
+
+ public Koth() {
+ new BukkitRunnable() {
+ @Override public void run() {
+ if (GameTimeTask.getNumOfSeconds() == 600) {
+ setSeconds(300);
+ if (capSeconds > 300) {
+ setCapSeconds(300);
+ }
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7[&6KingOfTheHill&7] &eThe &9Koth &etime has been decreased. &7(05:00)"));
+ }
+ }
+ }.runTaskTimerAsynchronously(Bunkers.getPlugin(), 0L, 20L);
+ }
+
+ public boolean isInsideArea(Location location) {
+ return Bunkers.getPlugin().getInformationManager().getInformation().getKothCuboid().contains(location);
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/listeners/DeathMessageListener.java b/Bunkers/src/main/java/me/redis/bunkers/listeners/DeathMessageListener.java
new file mode 100644
index 0000000..7ae8e26
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/listeners/DeathMessageListener.java
@@ -0,0 +1,64 @@
+package me.redis.bunkers.listeners;
+
+import com.google.common.base.Preconditions;
+import jdk.jfr.events.ExceptionThrownEvent;
+import me.redis.bunkers.Bunkers;
+import net.minecraft.server.v1_7_R4.EntityLiving;
+import org.apache.commons.lang.WordUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.PlayerDeathEvent;
+
+public class DeathMessageListener implements Listener {
+ private final Bunkers plugin = Bunkers.getPlugin();
+
+ public static String replaceLast(final String text, final String regex, final String replacement) {
+ return text.replaceFirst("(?s)" + regex + "(?!.*?" + regex + ')', replacement);
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
+ public void onPlayerDeath(final PlayerDeathEvent event) {
+ final String message = event.getDeathMessage();
+ if(message == null || message.isEmpty()) {
+ return;
+ }
+ event.setDeathMessage(getDeathMessage(message, event.getEntity(), this.getKiller(event)));
+ }
+
+ private CraftEntity getKiller(final PlayerDeathEvent event) {
+ final EntityLiving lastAttacker = ((CraftPlayer) event.getEntity()).getHandle().lastDamager;
+ return (lastAttacker == null) ? null : lastAttacker.getBukkitEntity();
+ }
+
+ private String getDeathMessage(String input, final Entity entity, final Entity killer) {
+ input = input.replaceFirst("\\[", "");
+ input = replaceLast(input, "]", "");
+ if(entity != null) {
+ input = input.replaceFirst("(?i)" + this.getEntityName(entity), ChatColor.RED + this.getDisplayName(entity) + ChatColor.YELLOW);
+ }
+ if(killer != null && (entity == null || !killer.equals(entity))) {
+ input = input.replaceFirst("(?i)" + this.getEntityName(killer), ChatColor.RED + this.getDisplayName(killer) + ChatColor.YELLOW);
+ }
+ return input;
+ }
+
+ private String getEntityName(final Entity entity) {
+ Preconditions.checkNotNull((Object) entity, "Entity cannot be null");
+ return (entity instanceof Player) ? ((Player) entity).getName() : ((CraftEntity) entity).getHandle().getName();
+ }
+
+ private String getDisplayName(final Entity entity) {
+ Preconditions.checkNotNull((Object) entity, "Entity cannot be null");
+ if(entity instanceof Player) {
+ final Player player = (Player) entity;
+ return plugin.getTeamManager().getByPlayer(player).getColor() + player.getName() + ChatColor.GRAY + "[" + ChatColor.WHITE + Bunkers.getPlugin().getProfileManager().getProfile(player).getMatchKills() + ChatColor.GRAY + "]";
+ }
+ return WordUtils.capitalizeFully(entity.getType().name().replace('_', ' '));
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/listeners/PlayerListeners.java b/Bunkers/src/main/java/me/redis/bunkers/listeners/PlayerListeners.java
new file mode 100644
index 0000000..0d8ef6c
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/listeners/PlayerListeners.java
@@ -0,0 +1,260 @@
+package me.redis.bunkers.listeners;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.ItemBuilder;
+import me.redis.bunkers.utils.LocationUtils;
+import net.minecraft.server.v1_7_R4.EnumClickAction;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.GameMode;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.Action;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.entity.EntitySpawnEvent;
+import org.bukkit.event.entity.PlayerDeathEvent;
+import org.bukkit.event.player.*;
+import org.bukkit.event.server.ServerListPingEvent;
+import org.bukkit.event.weather.WeatherChangeEvent;
+import org.bukkit.inventory.ItemStack;
+
+public class PlayerListeners implements Listener {
+ private Bunkers bunkers = Bunkers.getPlugin();
+
+ ItemStack red = new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(14).setDisplayName("&c&lRed Team").create();
+ ItemStack blue = new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(3).setDisplayName("&9&lBlue Team").create();
+ ItemStack green = new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(5).setDisplayName("&a&lGreen Team").create();
+ ItemStack yellow = new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(4).setDisplayName("&e&lYellow Team").create();
+
+ @EventHandler
+ public void onJoin(PlayerJoinEvent event) {
+ Player player = event.getPlayer();
+
+ event.setJoinMessage(null);
+
+ if (bunkers.getInformationManager().getInformation().getLobbyLocation() != null) {
+ player.teleport(LocationUtils.getLocation(bunkers.getInformationManager().getInformation().getLobbyLocation()));
+ } else {
+ player.sendMessage(ChatColor.RED + "You must set the spawn location.");
+ }
+
+ if (bunkers.getGameManager().canBePlayed()) {
+ if (bunkers.getInformationManager().getInformation().getMinPlayers() <= Bukkit.getOnlinePlayers().size() && bunkers.getGameManager().getStatus() == GameStatus.WAITING) {
+ bunkers.getGameManager().startCooldown();
+ }
+
+ player.getInventory().clear();
+ player.getInventory().setArmorContents(null);
+ player.setHealth(20);
+ player.setSaturation(20);
+ player.setGameMode(GameMode.SURVIVAL);
+ player.setAllowFlight(false);
+
+ player.getInventory().setItem(1, red);
+ player.getInventory().setItem(3, blue);
+ player.getInventory().setItem(5, green);
+ player.getInventory().setItem(7, yellow);
+ } else {
+ player.sendMessage(ChatColor.RED + "You must set-up the bunkers.");
+ }
+ }
+
+ @EventHandler
+ public void onInteract(PlayerInteractEvent event) {
+ Player player = event.getPlayer();
+ ItemStack itemStack = event.getItem();
+
+ if (itemStack != null && (event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_AIR)) {
+ if (itemStack.isSimilar(red)) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByName("Red");
+
+ if (team.getMembers().size() >= 5) {
+ player.sendMessage(ChatColor.RED + "The red team is full.");
+ return;
+ }
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Bunkers.getPlugin().getTeamManager().getByPlayer(player).getMembers().remove(player.getUniqueId());
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have joined the &cred &eteam."));
+ team.getMembers().add(player.getUniqueId());
+ } else if (itemStack.isSimilar(blue)) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByName("Blue");
+
+ if (team.getMembers().size() >= 5) {
+ player.sendMessage(ChatColor.RED + "The blue team is full.");
+ return;
+ }
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Bunkers.getPlugin().getTeamManager().getByPlayer(player).getMembers().remove(player.getUniqueId());
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have joined the &9blue &eteam."));
+ team.getMembers().add(player.getUniqueId());
+ } else if (itemStack.isSimilar(green)) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByName("Green");
+
+ if (team.getMembers().size() >= 5) {
+ player.sendMessage(ChatColor.RED + "The green team is full.");
+ return;
+ }
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Bunkers.getPlugin().getTeamManager().getByPlayer(player).getMembers().remove(player.getUniqueId());
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have joined the &agreen &eteam."));
+ team.getMembers().add(player.getUniqueId());
+ } else if (itemStack.isSimilar(yellow)) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByName("Yellow");
+
+ if (team.getMembers().size() >= 5) {
+ player.sendMessage(ChatColor.RED + "The yellow team is full.");
+ return;
+ }
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Bunkers.getPlugin().getTeamManager().getByPlayer(player).getMembers().remove(player.getUniqueId());
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have joined the &6yellow &eteam."));
+ team.getMembers().add(player.getUniqueId());
+ }
+ }
+ }
+
+ @EventHandler
+ public void onAsyncJoin(AsyncPlayerPreLoginEvent event) {
+ if (Bukkit.getServer().getOnlinePlayers().size() >= 20) {
+ event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
+ event.setKickMessage(ChatColor.RED + "The match is full.");
+ return;
+ }
+
+ if (bunkers.getGameManager().getStatus() != GameStatus.WAITING) {
+ event.setLoginResult(AsyncPlayerPreLoginEvent.Result.KICK_OTHER);
+ event.setKickMessage(ChatColor.RED + "You can't join a started match.");
+ }
+ }
+
+ @EventHandler
+ public void onBreak(BlockBreakEvent event) {
+ if (bunkers.getGameManager().getStatus() != GameStatus.PLAYING) {
+ Player player = event.getPlayer();
+
+ if (player.isOp() && player.getGameMode() == GameMode.CREATIVE) {
+ event.setCancelled(false);
+ } else {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onPlace(BlockPlaceEvent event) {
+ if (bunkers.getGameManager().getStatus() != GameStatus.PLAYING) {
+ Player player = event.getPlayer();
+
+ if (player.isOp() && player.getGameMode() == GameMode.CREATIVE) {
+ event.setCancelled(false);
+ } else {
+ event.setCancelled(true);
+ }
+ }
+ }
+
+ @EventHandler
+ public void onDrop(PlayerDropItemEvent event) {
+ Player player = event.getPlayer();
+
+ if (player.isOp() && player.getGameMode() == GameMode.CREATIVE) return;
+
+ if (bunkers.getGameManager().getStatus() != GameStatus.PLAYING) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onDeath(PlayerDeathEvent event) {
+ Player player = event.getEntity();
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player);
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ team.setDtr(team.getDtr() - 1);
+ profile.setDeaths(profile.getDeaths() + 1);
+
+ if (event.getEntity().getKiller() != null) {
+ Bunkers.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).setKills(Bunkers.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).getKills() + 1);
+ Bunkers.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).setMatchKills(Bunkers.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).getMatchKills() + 1);
+ }
+
+ if (team.getDtr() <= 0) {
+ Bunkers.getPlugin().getSpectatorManager().setSpectator(player);
+ } else {
+ player.spigot().respawn();
+ }
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent event) {
+ Player player = event.getPlayer();
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player);
+
+ if (bunkers.getGameManager().getStatus() == GameStatus.WAITING) {
+ team.getMembers().remove(player.getUniqueId());
+ } else if (bunkers.getGameManager().getStatus() == GameStatus.PLAYING) {
+ team.setDtr(team.getDtr() - 1);
+ } else if (bunkers.getGameManager().getStatus() == GameStatus.STARTING) {
+ team.getMembers().remove(player.getUniqueId());
+ }
+ }
+ }
+
+ @EventHandler
+ public void onRespawn(PlayerRespawnEvent event) {
+ event.setRespawnLocation(LocationUtils.getLocation(Bunkers.getPlugin().getTeamManager().getByPlayer(event.getPlayer()).getSpawnLocation()));
+ }
+
+ @EventHandler
+ public void onDamage(EntityDamageEvent event) {
+ if (Bunkers.getPlugin().getGameManager().getStatus() != GameStatus.PLAYING) {
+ event.setCancelled(true);
+ } else {
+ if (event instanceof EntityDamageByEntityEvent) {
+ if (((EntityDamageByEntityEvent) event).getDamager() instanceof Player && event.getEntity() instanceof Player) {
+ Player damaged = (Player) event.getEntity();
+ Player damager = (Player) ((EntityDamageByEntityEvent) event).getDamager();
+
+ if (Bunkers.getPlugin().getTeamManager().getByPlayer(damaged) == Bunkers.getPlugin().getTeamManager().getByPlayer(damager)) {
+ event.setCancelled(true);
+ }
+ }
+ }
+ }
+ }
+
+ @EventHandler
+ public void onWeather(WeatherChangeEvent event) {
+ if (event.toWeatherState()) {
+ event.setCancelled(true);
+ }
+ }
+
+ @EventHandler
+ public void onMotd(ServerListPingEvent event) {
+ event.setMotd(Bukkit.getServerName() + ";" + Bunkers.getPlugin().getGameManager().getStatus().name() + ";" + Bunkers.getPlugin().getKoth().getCapSeconds() + ";" + Bukkit.getOnlinePlayers().size());
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/IMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/IMenu.java
new file mode 100644
index 0000000..92d96d1
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/IMenu.java
@@ -0,0 +1,26 @@
+package me.redis.bunkers.menu;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+
+public interface IMenu extends InventoryHolder {
+
+ default String getTitle() { return getInventory().getType().getDefaultTitle(); }
+
+ default void open(Player player) { player.openInventory(getInventory()); };
+
+ void onInventoryClick(InventoryClickEvent event);
+
+ default void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(getInventory())) {
+ event.setCancelled(true);
+ }
+ }
+
+ default void onInventoryClose(InventoryCloseEvent event) {};
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/InventoryUtil.java b/Bunkers/src/main/java/me/redis/bunkers/menu/InventoryUtil.java
new file mode 100644
index 0000000..0ef6f06
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/InventoryUtil.java
@@ -0,0 +1,20 @@
+package me.redis.bunkers.menu;
+
+import net.minecraft.server.v1_7_R4.EntityPlayer;
+import net.minecraft.server.v1_7_R4.PacketPlayOutOpenWindow;
+import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+public class InventoryUtil {
+
+ public static void changeTitle(Player player, String title) {
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ int windowId = entityPlayer.activeContainer.windowId;
+
+ PacketPlayOutOpenWindow packet = new PacketPlayOutOpenWindow(windowId, 0, title, player.getOpenInventory().getTopInventory().getSize(), true);
+
+ entityPlayer.playerConnection.sendPacket(packet);
+
+ player.updateInventory();
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/MenuListener.java b/Bunkers/src/main/java/me/redis/bunkers/menu/MenuListener.java
new file mode 100644
index 0000000..a06d9ed
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/MenuListener.java
@@ -0,0 +1,32 @@
+package me.redis.bunkers.menu;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryCloseEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+
+public class MenuListener implements Listener {
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
+ public void onInventoryClick(InventoryClickEvent event) {
+ if (event.getInventory().getHolder() instanceof IMenu) {
+ ((IMenu) event.getInventory().getHolder()).onInventoryClick(event);
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
+ public void onInventoryDrag(InventoryDragEvent event) {
+ if (event.getInventory().getHolder() instanceof IMenu) {
+ ((IMenu) event.getInventory().getHolder()).onInventoryDrag(event);
+ }
+ }
+
+ @EventHandler
+ public void onInventoryClose(InventoryCloseEvent event) {
+ if (event.getInventory().getHolder() instanceof IMenu) {
+ ((IMenu) event.getInventory().getHolder()).onInventoryClose(event);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/menu/BuildMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/BuildMenu.java
new file mode 100644
index 0000000..5584656
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/BuildMenu.java
@@ -0,0 +1,112 @@
+package me.redis.bunkers.menu.menu;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.menu.type.ChestMenu;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.utils.ItemBuilder;
+import org.apache.commons.lang.WordUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.ChatPaginator;
+
+public class BuildMenu extends ChestMenu {
+ private Player player;
+
+ public BuildMenu(Player player) {
+ super(6 * 9);
+ this.player = player;
+
+ update();
+ }
+
+ public void update() {
+ inventory.clear();
+
+ inventory.addItem(new ItemBuilder(Material.CHEST).setAmount(16).setDisplayName("&aChest").setLore("&7&m-------------------", "&716 x Chest", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.STONE).setAmount(16).setDisplayName("&aStone").setLore("&7&m-------------------", "&716 x Stone", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.COBBLESTONE).setAmount(16).setDisplayName("&aCobblestone").setLore("&7&m-------------------", "&716 x Cobblestone", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.FENCE_GATE).setAmount(16).setDisplayName("&aFence Gate").setLore("&7&m-------------------", "&716 x Fence Gate", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.STONE_PLATE).setAmount(16).setDisplayName("&aPressure Plate").setLore("&7&m-------------------", "&716 x Pressure Plate", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.LADDER).setAmount(16).setDisplayName("&aLadder").setLore("&7&m-------------------", "&716 x Ladder", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.STONE_BUTTON).setAmount(16).setDisplayName("&aStone Button").setLore("&7&m-------------------", "&716 x Stone Button", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.TRAPPED_CHEST).setAmount(16).setDisplayName("&aTrapped Chest").setLore("&7&m-------------------", "&716 x Trapped Chest", "&7&m-------------------", "&ePrice: &a$50").create());
+ inventory.addItem(new ItemBuilder(Material.GLASS).setAmount(16).setDisplayName("&aGlass").setLore("&7&m-------------------", "&716 x Glass", "&7&m-------------------", "&ePrice: &a$50").create());
+
+ inventory.setItem(48, new ItemBuilder(Material.DIAMOND_PICKAXE).setDisplayName("&aDiamond Pickaxe").setLore("&7&m-------------------", "&71 x Diamond Pickaxe", "&7&m-------------------", "&ePrice: &a$75").create());
+ inventory.setItem(49, new ItemBuilder(Material.DIAMOND_AXE).setDisplayName("&aDiamond Axe").setLore("&7&m-------------------", "&71 x Diamond Axe", "&7&m-------------------", "&ePrice: &a$65").create());
+ inventory.setItem(50, new ItemBuilder(Material.DIAMOND_SPADE).setDisplayName("&aDiamond Shovel").setLore("&7&m-------------------", "&71 x Diamond Shovel", "&7&m-------------------", "&ePrice: &a$55").create());
+
+ for (int i = 0; i < 6*9; i++) {
+ if (inventory.getItem(i) != null) continue;
+
+ inventory.setItem(i, new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(7).setDisplayName(" ").create());
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return ChatColor.RED + ChatColor.BOLD.toString() + "Block Shop";
+ }
+
+ @Override
+ public void onInventoryClick(InventoryClickEvent event) {
+ Inventory clickedInventory = event.getClickedInventory();
+ Inventory topInventory = event.getView().getTopInventory();
+ if (clickedInventory == null || topInventory == null || !topInventory.equals(inventory)) {
+ return;
+ }
+
+ Player player = (Player) event.getWhoClicked();
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ if (topInventory.equals(clickedInventory)) {
+ event.setCancelled(true);
+
+ if (event.getCurrentItem().getType() != Material.AIR) {
+ if (event.getCurrentItem().getItemMeta() != null && event.getCurrentItem().getType() != Material.STAINED_GLASS_PANE) {
+ int balance = profile.getBalance();
+ int cost = Integer.parseInt(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(3).split(" ")[1].replace("$", "")));
+ int cuantos = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(1))));
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ } else {
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType(), cuantos));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+ }
+ }
+ } else if (!topInventory.equals(clickedInventory) && event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(getInventory())) {
+ event.setCancelled(true);
+ }
+ }
+
+ public static String stripNonDigits(
+ final CharSequence input /* inspired by seh's comment */){
+ final StringBuilder sb = new StringBuilder(
+ input.length() /* also inspired by seh's comment */);
+ for(int i = 0; i < input.length(); i++){
+ final char c = input.charAt(i);
+ if(c > 47 && c < 58){
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/menu/CombatMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/CombatMenu.java
new file mode 100644
index 0000000..3abb5bd
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/CombatMenu.java
@@ -0,0 +1,253 @@
+package me.redis.bunkers.menu.menu;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.menu.type.ChestMenu;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.utils.ItemBuilder;
+import org.apache.commons.lang.WordUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.ChatPaginator;
+
+public class CombatMenu extends ChestMenu {
+ private Player player;
+
+ public CombatMenu(Player player) {
+ super(6 * 9);
+ this.player = player;
+
+ update();
+ }
+
+ public void update() {
+ inventory.clear();
+
+ inventory.setItem(10, new ItemBuilder(Material.DIAMOND_HELMET).setDisplayName("&aDiamond Helmet").setLore("&7&m-------------------", "&71 x Diamond Helmet", "&7&m-------------------", "&7Price: &a$50").create());
+ inventory.setItem(11, new ItemBuilder(Material.BOW).setDisplayName("&aBow").setLore("&7&m-------------------", "&71 x Bow", "&7&m-------------------", "&7Price: &a$150").create());
+ inventory.setItem(12, new ItemBuilder(Material.ARROW).setDisplayName("&aArrows").setLore("&7&m-------------------", "&71 x Arrow", " &e- &aRight click to buy 16", "&7&m-------------------", "&7Price: &a$10").create());
+ inventory.setItem(14, new ItemBuilder(Material.POTION).setDurability(8226).setDisplayName("&aSpeed II Potion").setLore("&7&m-------------------", "&71 x Speed II Potion", "&7&m-------------------", "&7Price: &a$15").create());
+ inventory.setItem(15, new ItemBuilder(Material.POTION).setDurability(8227).setDisplayName("&aFire Resistant Potion").setLore("&7&m-------------------", "&71 x Fire Resistance Potion", "&7&m-------------------", "&7Price: &a$25").create());
+ inventory.setItem(23, new ItemBuilder(Material.POTION).setDurability(16421).setDisplayName("&aInstant Health II Potion").setLore("&7&m-------------------", "&71 x Instant Health II Potion", " &e- &aRight click fill your inventory", "&7&m-------------------", "&7Price: &a$5").create());
+ inventory.setItem(21, new ItemBuilder(Material.ENDER_PEARL).setDisplayName("&aEnder Pearls").setLore("&7&m-------------------", "&71 x Ender Pearl", " &e- &aRight click to buy 16", "&7&m-------------------", "&7Price: &a$25").create());
+ inventory.setItem(19, new ItemBuilder(Material.DIAMOND_CHESTPLATE).setDisplayName("&aDiamond Chestplate").setLore("&7&m-------------------", "&71 x Diamond Chestplate", "&7&m-------------------", "&7Price: &a$200").create());
+ inventory.setItem(20, new ItemBuilder(Material.DIAMOND).setDisplayName("&aFull Diamond Set").setLore("&7&m-------------------", "&71 x Full Diamond Set", "&7&m-------------------", "&7Price: &a$600").create());
+ inventory.setItem(28, new ItemBuilder(Material.DIAMOND_LEGGINGS).setDisplayName("&aDiamond Leggings").setLore("&7&m-------------------", "&71 x Diamond Leggings", "&7&m-------------------", "&7Price: &a$150").create());
+ inventory.setItem(37, new ItemBuilder(Material.DIAMOND_BOOTS).setDisplayName("&aDiamond Boots").setLore("&7&m-------------------", "&71 x Diamond Boots", "&7&m-------------------", "&7Price: &a$65").create());
+ inventory.setItem(39, new ItemBuilder(Material.POTION).setDisplayName("&aAntidote").setLore("&7&m-------------------", "&71 x Antidote", "&7&m-------------------", "&7Price: &a$150").create());
+ inventory.setItem(41, new ItemBuilder(Material.COOKED_BEEF).setDisplayName("&aCooked Beef").setLore("&7&m-------------------", "&71 x Beef", " &e- &aRight click to buy 16", "&7&m-------------------", "&7Price: &a$5").create());
+ inventory.setItem(18, new ItemBuilder(Material.DIAMOND_SWORD).setDisplayName("&aDiamond Sword").setLore("&7&m-------------------", "&71 x Diamond Sword", "&7&m-------------------", "&7Price: &a$150").create());
+
+ for (int i = 0; i < 6 * 9; i++) {
+ if (inventory.getItem(i) != null) continue;
+
+ inventory.setItem(i, new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(7).setDisplayName(" ").create());
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return ChatColor.RED + ChatColor.BOLD.toString() + "Combat Shop";
+ }
+
+ @Override
+ public void onInventoryClick(InventoryClickEvent event) {
+ Inventory clickedInventory = event.getClickedInventory();
+ Inventory topInventory = event.getView().getTopInventory();
+ if (clickedInventory == null || topInventory == null || !topInventory.equals(inventory)) {
+ return;
+ }
+
+ Player player = (Player) event.getWhoClicked();
+
+ if (topInventory.equals(clickedInventory)) {
+ event.setCancelled(true);
+
+ if (event.getCurrentItem().getType() != Material.AIR) {
+ if (event.getCurrentItem().getItemMeta() != null && event.getCurrentItem().getItemMeta().getDisplayName() != null && event.getCurrentItem().getType() != Material.STAINED_GLASS_PANE) {
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+ int balance = Bunkers.getPlugin().getProfileManager().getProfile(player).getBalance();
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Instant")) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(4))));
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ if (event.getClick() == ClickType.RIGHT) {
+ for (ItemStack itemStack : player.getInventory().getContents()) {
+ if (itemStack == null) {
+ cost += 5;
+ }
+ }
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ for (int i = 0; i < 36; i++) {
+ if (player.getInventory().getItem(i) == null) {
+ player.getInventory().setItem(i, new ItemStack(Material.POTION, 1, (short) 16421));
+ }
+ }
+ Bunkers.getPlugin().getProfileManager().getProfile(player).setBalance(Bunkers.getPlugin().getProfileManager().getProfile(player).getBalance() - cost);
+ } else if (event.getClick() == ClickType.LEFT) {
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+ return;
+ }
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Ender")) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(4))));
+
+ if (event.getClick() == ClickType.RIGHT) {
+ cost = cost * 16;
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType(), 16));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ } else if (event.getClick() == ClickType.LEFT) {
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+
+ return;
+ }
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Beef")) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(4))));
+
+ if (event.getClick() == ClickType.RIGHT) {
+ cost = cost * 16;
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType(), 16));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ } else if (event.getClick() == ClickType.LEFT) {
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+ return;
+ }
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Arrow")) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(4))));
+
+ if (event.getClick() == ClickType.RIGHT) {
+ cost = cost * 16;
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType(), 16));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ } else if (event.getClick() == ClickType.LEFT) {
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+ return;
+ }
+
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(3))));
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ return;
+ }
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Full")) {
+ player.getInventory().setHelmet(new ItemStack(Material.DIAMOND_HELMET));
+ player.getInventory().setChestplate(new ItemStack(Material.DIAMOND_CHESTPLATE));
+ player.getInventory().setLeggings(new ItemStack(Material.DIAMOND_LEGGINGS));
+ player.getInventory().setBoots(new ItemStack(Material.DIAMOND_BOOTS));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + "full diamond set" + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ return;
+ }
+
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Antidote")) {
+ player.getInventory().addItem(new ItemBuilder(Material.POTION).setDisplayName("&aAntidote").create());
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ean " + "antidote" + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ return;
+ }
+
+ player.getInventory().addItem(new ItemStack(event.getCurrentItem().getType(), 1, event.getCurrentItem().getDurability()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have bought &ea " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + " &afor &e$" + cost + "&a."));
+ profile.setBalance(profile.getBalance() - cost);
+ }
+ }
+ } else if (!topInventory.equals(clickedInventory) && event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(getInventory())) {
+ event.setCancelled(true);
+ }
+ }
+
+ public static String stripNonDigits(
+ final CharSequence input /* inspired by seh's comment */) {
+ final StringBuilder sb = new StringBuilder(
+ input.length() /* also inspired by seh's comment */);
+ for (int i = 0; i < input.length(); i++) {
+ final char c = input.charAt(i);
+ if (c > 47 && c < 58) {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/menu/EnchanterMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/EnchanterMenu.java
new file mode 100644
index 0000000..734a2b2
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/EnchanterMenu.java
@@ -0,0 +1,127 @@
+package me.redis.bunkers.menu.menu;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.menu.type.ChestMenu;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.utils.ItemBuilder;
+import org.apache.commons.lang.WordUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.ChatPaginator;
+
+public class EnchanterMenu extends ChestMenu {
+ private Player player;
+
+ public EnchanterMenu(Player player) {
+ super(9);
+ this.player = player;
+
+ update();
+ }
+
+ public void update() {
+ inventory.clear();
+
+ inventory.addItem(new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName("&3Sharpness I").setLore("&7&m-------------------", "&7Sharpness I for your sword", "&7&m-------------------", "&ePrice: &a$300").create());
+ inventory.addItem(new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName("&3Protection I").setLore("&7&m-------------------", "&7Protection I for your armor", "&7&m-------------------", "&ePrice: &a$1200").create());
+ inventory.addItem(new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName("&3Feather Falling IV").setLore("&7&m-------------------", "&7Feather Falling IV for your boots", "&7&m-------------------", "&ePrice: &a$200").create());
+
+ for (int i = 0; i < 9; i++) {
+ if (inventory.getItem(i) != null) continue;
+
+ inventory.setItem(i, new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(7).setDisplayName(" ").create());
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return ChatColor.RED + ChatColor.BOLD.toString() + "Block Shop";
+ }
+
+ @Override
+ public void onInventoryClick(InventoryClickEvent event) {
+ Inventory clickedInventory = event.getClickedInventory();
+ Inventory topInventory = event.getView().getTopInventory();
+ if (clickedInventory == null || topInventory == null || !topInventory.equals(inventory)) {
+ return;
+ }
+
+ Player player = (Player) event.getWhoClicked();
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ if (topInventory.equals(clickedInventory)) {
+ event.setCancelled(true);
+
+ if (event.getCurrentItem().getType() != Material.AIR) {
+ if (event.getCurrentItem().getItemMeta() != null && event.getCurrentItem().getType() != Material.STAINED_GLASS_PANE) {
+ int balance = profile.getBalance();
+ int cost = Integer.parseInt(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(3).split(" ")[1].replace("$", "")));
+
+ if (cost > balance) {
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cThis costs &e$" + cost + "&c, you only have &e$" + balance + "&c."));
+ } else {
+ if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Sharpness")) {
+ int counter = 0;
+
+ for (ItemStack itemStack : player.getInventory().getContents()) {
+ if (itemStack != null && itemStack.getType() == Material.DIAMOND_SWORD && counter == 0) {
+ itemStack.addEnchantment(Enchantment.DAMAGE_ALL, 1);
+
+ counter++;
+ }
+ }
+ } else if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Feather")) {
+ int counter = 0;
+
+ for (ItemStack itemStack : player.getInventory().getContents()) {
+ if (itemStack != null && itemStack.getType() == Material.DIAMOND_BOOTS && counter == 0) {
+ itemStack.addEnchantment(Enchantment.PROTECTION_FALL, 1);
+
+ counter++;
+ }
+ }
+ } else if (event.getCurrentItem().getItemMeta().getDisplayName().contains("Protection")) {
+
+ for (ItemStack itemStack : player.getInventory().getContents()) {
+ if (itemStack != null && (itemStack.getType() == Material.DIAMOND_HELMET || itemStack.getType() == Material.DIAMOND_CHESTPLATE || itemStack.getType() == Material.DIAMOND_LEGGINGS || itemStack.getType() == Material.DIAMOND_BOOTS)) {
+ itemStack.addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1);
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (!topInventory.equals(clickedInventory) && event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(getInventory())) {
+ event.setCancelled(true);
+ }
+ }
+
+ public static String stripNonDigits(
+ final CharSequence input /* inspired by seh's comment */){
+ final StringBuilder sb = new StringBuilder(
+ input.length() /* also inspired by seh's comment */);
+ for(int i = 0; i < input.length(); i++){
+ final char c = input.charAt(i);
+ if(c > 47 && c < 58){
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/menu/SellMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/SellMenu.java
new file mode 100644
index 0000000..9c5a48f
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/menu/SellMenu.java
@@ -0,0 +1,143 @@
+package me.redis.bunkers.menu.menu;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.menu.type.ChestMenu;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.utils.ItemBuilder;
+import org.apache.commons.lang.WordUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.util.ChatPaginator;
+
+public class SellMenu extends ChestMenu {
+ private Player player;
+
+ public SellMenu(Player player) {
+ super(9);
+ this.player = player;
+
+ update();
+ }
+
+ public void update() {
+ inventory.clear();
+
+ int diamond = 0;
+ int gold = 0;
+ int iron = 0;
+ int coal = 0;
+
+ for (ItemStack itemStack : player.getInventory().getContents()) {
+ if (itemStack != null) {
+ if (itemStack.getType() == Material.DIAMOND) {
+ diamond += itemStack.getAmount();
+ }
+
+ if (itemStack.getType() == Material.GOLD_INGOT) {
+ gold += itemStack.getAmount();
+ }
+
+ if (itemStack.getType() == Material.IRON_ORE) {
+ iron += itemStack.getAmount();
+ }
+
+ if (itemStack.getType() == Material.COAL) {
+ coal += itemStack.getAmount();
+ }
+ }
+ }
+
+ inventory.setItem(1, new ItemBuilder(Material.DIAMOND).setDisplayName("&bSell Diamond").setLore("&7&m-------------------", "&7Left click to sell 1 x Diamond for &a$50", "&7Right click to sell all your diamonds for &a$" + diamond * 50, "&7&m-------------------").create());
+ inventory.setItem(3, new ItemBuilder(Material.GOLD_INGOT).setDisplayName("&bSell Gold").setLore("&7&m-------------------", "&7Left click to sell 1 x Gold Ingot for &a$35", "&7Right click to sell all your gold for &a$" + gold * 35, "&7&m-------------------").create());
+ inventory.setItem(5, new ItemBuilder(Material.IRON_INGOT).setDisplayName("&bSell Iron").setLore("&7&m-------------------", "&7Left click to sell 1 x Iron Ingot for &a$25", "&7Right click to sell all your iron for &a$" + iron * 25, "&7&m-------------------").create());
+ inventory.setItem(7, new ItemBuilder(Material.COAL).setDisplayName("&bSell Coal").setLore("&7&m-------------------", "&7Left click to sell 1 x Coal for &a$15", "&7Right click to sell all your coal for &a$" + coal * 15, "&7&m-------------------").create());
+
+ for (int i = 0; i < 9; i++) {
+ if (inventory.getItem(i) != null) continue;
+
+ inventory.setItem(i, new ItemBuilder(Material.STAINED_GLASS_PANE).setDurability(7).setDisplayName(" ").create());
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return ChatColor.RED + ChatColor.BOLD.toString() + "Sell Items";
+ }
+
+ @Override
+ public void onInventoryClick(InventoryClickEvent event) {
+ Inventory clickedInventory = event.getClickedInventory();
+ Inventory topInventory = event.getView().getTopInventory();
+ if (clickedInventory == null || topInventory == null || !topInventory.equals(inventory)) {
+ return;
+ }
+
+ Player player = (Player) event.getWhoClicked();
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ if (topInventory.equals(clickedInventory)) {
+ event.setCancelled(true);
+
+ if (event.getCurrentItem().getType() != Material.AIR) {
+ if (event.getCurrentItem().getItemMeta() != null && event.getCurrentItem().getType() != Material.STAINED_GLASS_PANE) {
+ if (event.getClick() == ClickType.LEFT) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(1).replace("1", ""))));
+
+ if (player.getInventory().contains(event.getCurrentItem().getType())) {
+ profile.setBalance(profile.getBalance() + cost);
+ player.getInventory().removeItem(new ItemStack(event.getCurrentItem().getType(), 1));
+ player.updateInventory();
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have sold &ex1 " + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + "&a for &e$" + cost + "&a."));
+ update();
+ } else {
+ player.sendMessage(ChatColor.RED + "You don't have enough to sell.");
+ }
+ } else if (event.getClick() == ClickType.RIGHT) {
+ int cost = Integer.parseInt(stripNonDigits(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getLore().get(2))));
+
+ if (player.getInventory().contains(event.getCurrentItem().getType())) {
+ profile.setBalance(profile.getBalance() + cost);
+ player.getInventory().remove(event.getCurrentItem().getType());
+ player.updateInventory();
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&aYou have sold all your &e" + WordUtils.capitalizeFully(event.getCurrentItem().getType().name().replace("_", " ")) + "&a for &e$" + cost + "&a."));
+ update();
+ } else {
+ player.sendMessage(ChatColor.RED + "You don't have enough to sell.");
+ }
+ }
+ }
+ }
+ } else if (!topInventory.equals(clickedInventory) && event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
+ event.setCancelled(true);
+ }
+ }
+
+ @Override
+ public void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(getInventory())) {
+ event.setCancelled(true);
+ }
+ }
+
+ public static String stripNonDigits(
+ final CharSequence input /* inspired by seh's comment */) {
+ final StringBuilder sb = new StringBuilder(
+ input.length() /* also inspired by seh's comment */);
+ for (int i = 0; i < input.length(); i++) {
+ final char c = input.charAt(i);
+ if (c > 47 && c < 58) {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/type/ChestMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/type/ChestMenu.java
new file mode 100644
index 0000000..8216352
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/type/ChestMenu.java
@@ -0,0 +1,40 @@
+package me.redis.bunkers.menu.type;
+
+import lombok.Getter;
+import me.redis.bunkers.menu.IMenu;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+
+@Getter
+public abstract class ChestMenu implements IMenu {
+
+ protected E plugin;
+
+ public final Inventory inventory;
+
+ public ChestMenu(int size) {
+ loadPlugin();
+
+ inventory = plugin.getServer().createInventory(this, size, getTitle().length() > 32 ? getTitle().substring(0, 32) : getTitle());
+ }
+
+ private void loadPlugin() {
+ Class clazz = ((Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
+
+ Method method = null;
+ try {
+ method = clazz.getDeclaredMethod("getPlugin", null);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+
+ try {
+ plugin = (E) method.invoke(null, method.getParameterTypes());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/menu/type/PaginatedMenu.java b/Bunkers/src/main/java/me/redis/bunkers/menu/type/PaginatedMenu.java
new file mode 100644
index 0000000..e001ec1
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/menu/type/PaginatedMenu.java
@@ -0,0 +1,79 @@
+package me.redis.bunkers.menu.type;
+
+import lombok.Getter;
+import me.redis.bunkers.menu.IMenu;
+import me.redis.bunkers.menu.InventoryUtil;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryDragEvent;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+
+@Getter
+public abstract class PaginatedMenu implements IMenu {
+
+ protected E plugin;
+
+ private int page;
+
+ public final Inventory inventory;
+
+ public PaginatedMenu(int size, int page) {
+ loadPlugin();
+
+ this.page = page;
+
+ inventory = plugin.getServer().createInventory(this, size, getTitle().length() > 32 ? getTitle().substring(0, 32) : getTitle());
+
+ updateContents();
+ }
+
+ public abstract int getTotalPages();
+
+ public abstract void updateContents();
+
+ private void loadPlugin() {
+ Class clazz = ((Class) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
+
+ Method method = null;
+ try {
+ method = clazz.getDeclaredMethod("getPlugin", null);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+
+ try {
+ plugin = (E) method.invoke(null, method.getParameterTypes());
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ }
+ }
+
+ public void setPage(int page) {
+ this.page = page;
+
+ for (HumanEntity viewer : getInventory().getViewers()) {
+ InventoryUtil.changeTitle((Player) viewer, getTitle());
+ }
+
+ updateContents();
+ }
+
+ @Override
+ public void open(Player player) {
+ player.openInventory(getInventory());
+
+ setPage(getPage());
+ }
+
+ @Override
+ public void onInventoryDrag(InventoryDragEvent event) {
+ Inventory topInventory = event.getView().getTopInventory();
+ if (topInventory.equals(inventory)) {
+ event.setCancelled(true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/profiles/Profile.java b/Bunkers/src/main/java/me/redis/bunkers/profiles/Profile.java
new file mode 100644
index 0000000..28197b3
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/profiles/Profile.java
@@ -0,0 +1,61 @@
+package me.redis.bunkers.profiles;
+
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.model.Filters;
+import lombok.Getter;
+import lombok.Setter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import me.redis.bunkers.protocol.ClaimPillar;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import java.util.*;
+
+@Getter
+public class Profile {
+ private UUID uniqueId;
+ @Setter private String name;
+
+ @Setter private int gamesPlayed, gamesWon, kills, deaths, matchKills, balance;
+ @Setter private PlayerStatus status = PlayerStatus.LOBBY;
+
+ @Setter private ClaimPillar firstPillar;
+ @Setter private ClaimPillar secondPillar;
+
+ public Profile(UUID uniqueId) {
+ this.uniqueId = uniqueId;
+
+ load();
+ }
+
+ public void load() {
+ Document document = (Document) Bunkers.getPlugin().getProfilesCollection().find(Filters.eq("_id", uniqueId)).first();
+
+ if (document == null) return;
+
+ name = document.getString("name");
+ gamesPlayed = document.getInteger("gamesPlayed");
+ gamesWon = document.getInteger("gamesWon");
+ kills = document.getInteger("kills");
+ deaths = document.getInteger("deaths");
+ }
+
+ public void save() {
+ Document document = new Document("_id", uniqueId);
+
+ document.put("name", name);
+ document.put("gamesPlayed", gamesPlayed);
+ document.put("gamesWon", gamesWon);
+ document.put("kills", kills);
+ document.put("deaths", deaths);
+
+ Bson filter = Filters.eq("_id", uniqueId);
+ FindIterable iterable = Bunkers.getPlugin().getProfilesCollection().find(filter);
+
+ if (iterable.first() == null) {
+ Bunkers.getPlugin().getProfilesCollection().insertOne(document);
+ } else {
+ Bunkers.getPlugin().getProfilesCollection().replaceOne(filter, document);
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/profiles/ProfileManager.java b/Bunkers/src/main/java/me/redis/bunkers/profiles/ProfileManager.java
new file mode 100644
index 0000000..1d25dee
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/profiles/ProfileManager.java
@@ -0,0 +1,67 @@
+package me.redis.bunkers.profiles;
+
+import lombok.Getter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import org.bson.Document;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+
+import javax.print.Doc;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class ProfileManager implements Listener {
+ public ProfileManager() {
+ Bukkit.getPluginManager().registerEvents(this, Bunkers.getPlugin());
+ }
+
+ @Getter
+ private Map profiles = new HashMap<>();
+
+ public Profile getProfile(UUID uniqueId) {
+ return profiles.get(uniqueId);
+ }
+
+ public Profile getNotCachedProfile(UUID uniqueId) {
+ for (Object object : Bunkers.getPlugin().getProfilesCollection().find()) {
+ Document document = (Document) object;
+
+ if (document.get("_id").equals(uniqueId)) {
+ return new Profile(uniqueId);
+ }
+ }
+
+ return null;
+ }
+
+ public Profile getProfile(Player player) {
+ return getProfile(player.getUniqueId());
+ }
+
+ @EventHandler
+ public void onJoin(AsyncPlayerPreLoginEvent event) {
+ Profile profile = new Profile(event.getUniqueId());
+
+ if (profile.getName() == null) {
+ profile.setName(event.getName());
+ }
+
+ profile.save();
+ profile.setStatus(PlayerStatus.LOBBY);
+
+ Bunkers.getPlugin().getProfileManager().getProfiles().put(event.getUniqueId(), profile);
+ }
+
+ @EventHandler
+ public void onQuit(PlayerQuitEvent event) {
+ Bukkit.getScheduler().runTaskAsynchronously(Bunkers.getPlugin(), () -> getProfile(event.getPlayer().getUniqueId()).save());
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/profiles/status/PlayerStatus.java b/Bunkers/src/main/java/me/redis/bunkers/profiles/status/PlayerStatus.java
new file mode 100644
index 0000000..04be72d
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/profiles/status/PlayerStatus.java
@@ -0,0 +1,5 @@
+package me.redis.bunkers.profiles.status;
+
+public enum PlayerStatus {
+ LOBBY, PLAYING, RESPAWNING, SPECTATOR
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/protocol/ClaimPillar.java b/Bunkers/src/main/java/me/redis/bunkers/protocol/ClaimPillar.java
new file mode 100644
index 0000000..8f7bba2
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/protocol/ClaimPillar.java
@@ -0,0 +1,57 @@
+package me.redis.bunkers.protocol;
+
+import lombok.Getter;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+
+@Getter
+public class ClaimPillar {
+ private Player player;
+ private Material blockType;
+ private byte data;
+ private ArrayList blocks;
+ private Location location;
+
+ public ClaimPillar(Player player, Material blockType, byte data, Location location) {
+ this.player = player;
+ this.location = location;
+ this.blockType = blockType;
+ this.data = data;
+
+ blocks = new ArrayList<>();
+ }
+
+
+ public void sendPillar() {
+ int x = location.getBlockX();
+ int z = location.getBlockZ();
+
+ for (int i = 0; i <= 256; i++) {
+ Location location = new Location(this.location.getWorld(), x, i, z);
+ if (location.getBlock().getType() == Material.AIR) {
+ if (blocks.contains(location.getBlockY())) {
+ player.getPlayer().sendBlockChange(location, blockType, data);
+ player.getPlayer().sendBlockChange(location.add(0, 2, 0), Material.GLASS, (byte) 0);
+ } else {
+ player.getPlayer().sendBlockChange(location, Material.GLASS, (byte) 0);
+ blocks.add(location.getBlockY() + 1);
+ }
+ }
+ }
+ }
+
+ public void removePillar() {
+ int x = location.getBlockX();
+ int z = location.getBlockZ();
+
+ for (int i = 0; i <= 256; i++) {
+ Location location = new Location(this.location.getWorld(), x, i, z);
+ if (location.getBlock().getType() == Material.AIR) {
+ player.getPlayer().sendBlockChange(location, Material.AIR, (byte) 0);
+ }
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/protocol/ProtocolListener.java b/Bunkers/src/main/java/me/redis/bunkers/protocol/ProtocolListener.java
new file mode 100644
index 0000000..fe076f5
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/protocol/ProtocolListener.java
@@ -0,0 +1,45 @@
+package me.redis.bunkers.protocol;
+
+import com.comphenix.protocol.PacketType;
+import com.comphenix.protocol.ProtocolLibrary;
+import com.comphenix.protocol.ProtocolManager;
+import com.comphenix.protocol.events.PacketAdapter;
+import com.comphenix.protocol.events.PacketEvent;
+import me.redis.bunkers.Bunkers;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+
+public class ProtocolListener {
+ public ProtocolListener() {
+ ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
+
+ protocolManager.addPacketListener(new PacketAdapter(Bunkers.getPlugin(), PacketType.Play.Server.CUSTOM_PAYLOAD, PacketType.Play.Client.CUSTOM_PAYLOAD) {
+ @Override public void onPacketReceiving(PacketEvent event) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&a" + event.getPacketType().name() + "&7(Receive):"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', " &7- &e" + event.getPacket().getStrings().readSafely(0)));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', " &7- &e" + event.getPacket().getIntegers().readSafely(0)));
+ Bukkit.broadcastMessage("");
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&dByte Arrays:"));
+ int counter = 0;
+ for (byte[] byt : event.getPacket().getByteArrays().getValues()) {
+
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', " &7- &e" + byt[counter]));
+ counter++;
+ }
+ }
+
+ @Override public void onPacketSending(PacketEvent event) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&a" + event.getPacketType().name() + "&7(Send):"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', " &7- &e" + event.getPacket().getStrings().readSafely(0)));
+ Bukkit.broadcastMessage("");
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&dByte Arrays:"));
+ int counter = 0;
+ for (byte[] byt : event.getPacket().getByteArrays().getValues()) {
+
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', " &7- &e" + byt[counter]));
+ counter++;
+ }
+ }
+ });
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/Aether.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/Aether.java
new file mode 100644
index 0000000..67ca81f
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/Aether.java
@@ -0,0 +1,250 @@
+package me.redis.bunkers.scoreboard;
+
+import lombok.Getter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.events.BoardCreateEvent;
+import me.redis.bunkers.scoreboard.scoreboard.Board;
+import me.redis.bunkers.scoreboard.scoreboard.BoardAdapter;
+import me.redis.bunkers.scoreboard.scoreboard.BoardEntry;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.player.PlayerJoinEvent;
+import org.bukkit.event.player.PlayerQuitEvent;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scoreboard.*;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static me.redis.bunkers.scoreboard.AetherOptions.defaultOptions;
+
+/**
+ * TODO: Add documentation to methods, etc
+ * TODO: Fix inconsistent cooldown scores
+ * TODO: Finish other board formats
+ */
+
+public class Aether implements Listener {
+
+ @Getter
+ private JavaPlugin plugin;
+ @Getter
+ private AetherOptions options;
+ @Getter
+ BoardAdapter adapter;
+
+ public Aether(JavaPlugin plugin, BoardAdapter adapter, AetherOptions options) {
+ this.options = options;
+ this.plugin = plugin;
+
+ Bukkit.getPluginManager().registerEvents(this, plugin);
+
+ setAdapter(adapter);
+ run();
+ }
+
+ public Aether(JavaPlugin plugin, BoardAdapter adapter) {
+ this(plugin, adapter, defaultOptions());
+ }
+
+ public Aether(JavaPlugin plugin) {
+ this(plugin, null, defaultOptions());
+ }
+
+ private void run() {
+ new BukkitRunnable() {
+ public void run() {
+ if (adapter == null) return;
+
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ Board board = Board.getByPlayer(player);
+ if (board != null) {
+ List scores = adapter.getScoreboard(player, board, board.getCooldowns());
+ List translatedScores = new ArrayList<>();
+
+ if (scores == null) {
+
+ if (!board.getEntries().isEmpty()) {
+
+ for (BoardEntry boardEntry : board.getEntries()) {
+ boardEntry.remove();
+ }
+
+ board.getEntries().clear();
+ }
+
+ continue;
+ }
+
+ for (String line : scores) {
+ translatedScores.add(ChatColor.translateAlternateColorCodes('&', line));
+ }
+
+ if (!options.scoreDirectionDown()) {
+ Collections.reverse(scores);
+ }
+
+ Scoreboard scoreboard = board.getScoreboard();
+ Objective objective = board.getObjective();
+
+ if (!(objective.getDisplayName().equals(adapter.getTitle(player)))) {
+ objective.setDisplayName(ChatColor.translateAlternateColorCodes('&', adapter.getTitle(player)));
+ }
+
+ outer:
+ for (int i = 0; i < scores.size(); i++) {
+ String text = scores.get(i);
+ int position;
+ if (options.scoreDirectionDown()) {
+ position = 15 - i;
+ } else {
+ position = i + 1;
+ }
+
+ Iterator iterator = new ArrayList<>(board.getEntries()).iterator();
+ while (iterator.hasNext()) {
+ BoardEntry boardEntry = iterator.next();
+ Score score = objective.getScore(boardEntry.getKey());
+
+ if (score != null && boardEntry.getText().equals(ChatColor.translateAlternateColorCodes('&', text))) {
+ if (score.getScore() == position) {
+ continue outer;
+ }
+ }
+ }
+
+ int positionToSearch = options.scoreDirectionDown() ? 15 - position : position - 1;
+
+ iterator = board.getEntries().iterator();
+ while (iterator.hasNext()) {
+ BoardEntry boardEntry = iterator.next();
+ int entryPosition = scoreboard.getObjective(DisplaySlot.SIDEBAR).getScore(boardEntry.getKey()).getScore();
+
+ if (!options.scoreDirectionDown()) {
+ if (entryPosition > scores.size()) {
+ iterator.remove();
+ boardEntry.remove();
+ }
+ }
+
+ }
+
+ BoardEntry entry = board.getByPosition(positionToSearch);
+ if (entry == null) {
+ new BoardEntry(board, text).send(position);
+ } else {
+ entry.setText(text).setup().send(position);
+ }
+
+ if (board.getEntries().size() > scores.size()) {
+ iterator = board.getEntries().iterator();
+ while (iterator.hasNext()) {
+ BoardEntry boardEntry = iterator.next();
+ if ((!translatedScores.contains(boardEntry.getText())) || Collections.frequency(board.getBoardEntriesFormatted(), boardEntry.getText()) > 1) {
+ iterator.remove();
+ boardEntry.remove();
+ }
+ }
+ }
+ }
+
+ player.setScoreboard(scoreboard);
+ updateTablist(player);
+ }
+ }
+ }
+ }.runTaskTimerAsynchronously(plugin, 20L, 1L);
+ }
+
+ public void setAdapter(BoardAdapter adapter) {
+ this.adapter = adapter;
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ Board board = Board.getByPlayer(player);
+
+ if (board != null) {
+ Board.getBoards().remove(board);
+ }
+
+ Bukkit.getPluginManager().callEvent(new BoardCreateEvent(new Board(player, this, options), player));
+ }
+ }
+
+ @EventHandler
+ public void onPlayerJoinEvent(PlayerJoinEvent event) {
+ if (Board.getByPlayer(event.getPlayer()) == null) {
+ Bukkit.getPluginManager().callEvent(new BoardCreateEvent(new Board(event.getPlayer(), this, options), event.getPlayer()));
+ }
+ }
+
+ private static Team getExistingOrCreateNewTeam(String string, Scoreboard scoreboard, ChatColor prefix) {
+ Team toReturn = scoreboard.getTeam(string);
+
+ if (toReturn == null) {
+ toReturn = scoreboard.registerNewTeam(string);
+ toReturn.setPrefix(prefix + "");
+ }
+
+ return toReturn;
+ }
+
+ private static void updateTablist(Player target) {
+ Team spectator = getExistingOrCreateNewTeam("spectator", Board.getByPlayer(target).getScoreboard(), ChatColor.GRAY);
+
+ Team red = getExistingOrCreateNewTeam("red", Board.getByPlayer(target).getScoreboard(), ChatColor.RED);
+ Team blue = getExistingOrCreateNewTeam("blue", Board.getByPlayer(target).getScoreboard(), ChatColor.BLUE);
+ Team green = getExistingOrCreateNewTeam("green", Board.getByPlayer(target).getScoreboard(), ChatColor.DARK_GREEN);
+ Team yellow = getExistingOrCreateNewTeam("yellow", Board.getByPlayer(target).getScoreboard(), ChatColor.YELLOW);
+
+ for (Player online : Bukkit.getOnlinePlayers()) {
+ me.redis.bunkers.team.Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(online);
+
+ if (team != null) {
+ if (team.getName().equalsIgnoreCase("red")) {
+ if (!red.hasEntry(online.getName())) {
+ red.addEntry(online.getName());
+ }
+ } else if (team.getName().equalsIgnoreCase("blue")) {
+ if (!blue.hasEntry(online.getName())) {
+ blue.addEntry(online.getName());
+ }
+ } else if (team.getName().equalsIgnoreCase("green")) {
+ if (!green.hasEntry(online.getName())) {
+ green.addEntry(online.getName());
+ }
+ } else if (team.getName().equalsIgnoreCase("yellow")) {
+ if (!yellow.hasEntry(online.getName())) {
+ yellow.addEntry(online.getName());
+ }
+ }
+ } else {
+ if (!spectator.hasEntry(online.getName())) {
+ spectator.addEntry(online.getName());
+ }
+ }
+ }
+ }
+
+ @EventHandler(priority = EventPriority.HIGHEST)
+ public void onPlayerQuitEvent(PlayerQuitEvent event) {
+ Board board = Board.getByPlayer(event.getPlayer());
+ if (board != null) {
+ Board.getBoards().remove(board);
+ }
+ }
+
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/AetherOptions.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/AetherOptions.java
new file mode 100644
index 0000000..04abb66
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/AetherOptions.java
@@ -0,0 +1,21 @@
+package me.redis.bunkers.scoreboard;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+@Getter
+@Setter
+@Accessors(chain = true, fluent = true)
+public class AetherOptions {
+
+ static AetherOptions defaultOptions() {
+ return new AetherOptions()
+ .hook(false)
+ .scoreDirectionDown(false);
+ }
+
+ private boolean hook;
+ private boolean scoreDirectionDown;
+
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/Board.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/Board.java
new file mode 100644
index 0000000..8efb3a2
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/Board.java
@@ -0,0 +1,136 @@
+package me.redis.bunkers.scoreboard.scoreboard;
+
+import lombok.Getter;
+import me.redis.bunkers.scoreboard.Aether;
+import me.redis.bunkers.scoreboard.AetherOptions;
+import me.redis.bunkers.scoreboard.scoreboard.cooldown.BoardCooldown;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scoreboard.DisplaySlot;
+import org.bukkit.scoreboard.Objective;
+import org.bukkit.scoreboard.Scoreboard;
+
+import java.util.*;
+
+public class Board {
+
+ private static Set boards = new HashSet<>();
+
+ @Getter private Scoreboard scoreboard;
+ @Getter private Player player;
+ @Getter private Objective objective;
+ @Getter private Set keys;
+ @Getter private List entries;
+ private Set cooldowns;
+ private final Aether aether;
+ private final AetherOptions options;
+
+ public Board(Player player, Aether aether, AetherOptions options) {
+ this.player = player;
+ this.aether = aether;
+ this.options = options;
+ this.keys = new HashSet<>();
+ this.cooldowns = new HashSet<>();
+ this.entries = new ArrayList<>();
+
+ setup();
+ }
+
+ private void setup() {
+ if (options.hook() && !player.getScoreboard().equals(Bukkit.getScoreboardManager().getMainScoreboard())) {
+ scoreboard = player.getScoreboard();
+ } else {
+ scoreboard = Bukkit.getScoreboardManager().getNewScoreboard();
+ }
+
+ objective = scoreboard.registerNewObjective("glaedr_is_shit", "dummy");
+ objective.setDisplaySlot(DisplaySlot.SIDEBAR);
+
+ if (aether.getAdapter() != null) {
+ objective.setDisplayName(ChatColor.translateAlternateColorCodes('&', aether.getAdapter().getTitle(player)));
+ } else {
+ objective.setDisplayName("Default Title");
+ }
+
+ boards.add(this);
+ }
+
+ public String getNewKey(BoardEntry entry) {
+
+ for (ChatColor color : ChatColor.values()) {
+ String colorText = color + "" + ChatColor.WHITE;
+
+ if (entry.getText().length() > 16) {
+ String sub = entry.getText().substring(0, 16);
+ colorText = colorText + ChatColor.getLastColors(sub);
+ }
+
+ if (!keys.contains(colorText)) {
+ keys.add(colorText);
+ return colorText;
+ }
+ }
+
+ throw new IndexOutOfBoundsException("No more keys available!");
+ }
+
+ public List getBoardEntriesFormatted() {
+ List toReturn = new ArrayList<>();
+
+ for (BoardEntry entry : new ArrayList<>(entries)) {
+ toReturn.add(entry.getText());
+ }
+
+ return toReturn;
+ }
+
+ public BoardEntry getByPosition(int position) {
+ int i = 0;
+
+ for (BoardEntry board : entries) {
+ if (i == position) {
+ return board;
+ }
+ i++;
+ }
+
+ return null;
+ }
+
+ public BoardCooldown getCooldown(String id) {
+ for (BoardCooldown cooldown : getCooldowns()) {
+ if (cooldown.getId().equals(id)) {
+ return cooldown;
+ }
+ }
+
+ return null;
+ }
+
+ public Set getCooldowns() {
+ Iterator iterator = cooldowns.iterator();
+
+ while (iterator.hasNext()) {
+ BoardCooldown cooldown = iterator.next();
+ if (System.currentTimeMillis() >= cooldown.getEnd()) {
+ iterator.remove();
+ }
+ }
+
+ return cooldowns;
+ }
+
+ public static Board getByPlayer(Player player) {
+ for (Board board : boards) {
+ if (board.getPlayer().getName().equals(player.getName())) {
+ return board;
+ }
+ }
+ return null;
+ }
+
+ public static Set getBoards() {
+ return boards;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardAdapter.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardAdapter.java
new file mode 100644
index 0000000..fd9a046
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardAdapter.java
@@ -0,0 +1,14 @@
+package me.redis.bunkers.scoreboard.scoreboard;
+
+import me.redis.bunkers.scoreboard.scoreboard.cooldown.BoardCooldown;
+import org.bukkit.entity.Player;
+
+import java.util.List;
+import java.util.Set;
+
+public interface BoardAdapter {
+
+ String getTitle(Player player);
+ List getScoreboard(Player player, Board board, Set cooldowns);
+
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardEntry.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardEntry.java
new file mode 100644
index 0000000..8fe0928
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/BoardEntry.java
@@ -0,0 +1,85 @@
+package me.redis.bunkers.scoreboard.scoreboard;
+
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.scoreboard.Objective;
+import org.bukkit.scoreboard.Score;
+import org.bukkit.scoreboard.Scoreboard;
+import org.bukkit.scoreboard.Team;
+
+@Accessors(chain = true)
+public class BoardEntry {
+
+ @Getter private Board board;
+ @Getter @Setter private String text;
+ @Getter private String originalText;
+ @Getter private String key;
+ @Getter private Team team;
+
+ public BoardEntry(Board board, String text) {
+ this.board = board;
+ this.text = text;
+ this.originalText = text;
+ this.key = board.getNewKey(this);
+
+ setup();
+ }
+
+ public BoardEntry setup() {
+ Scoreboard scoreboard = board.getScoreboard();
+
+ text = ChatColor.translateAlternateColorCodes('&', text);
+
+ String teamName = key;
+ if (teamName.length() > 16) {
+ teamName = teamName.substring(0, 16);
+ }
+
+ if (scoreboard.getTeam(teamName) != null) {
+ team = scoreboard.getTeam(teamName);
+ } else {
+ team = scoreboard.registerNewTeam(teamName);
+ }
+
+ if (!(team.getEntries().contains(key))) {
+ team.addEntry(key);
+ }
+
+ if (!(board.getEntries().contains(this))) {
+ board.getEntries().add(this);
+ }
+
+ return this;
+ }
+
+ public BoardEntry send(int position) {
+ Objective objective = board.getObjective();
+
+ if (text.length() <= 16) {
+ team.setPrefix(text);
+ team.setSuffix("");
+ } else {
+ String left = text.substring(0, 16), right = "";
+ if (left.endsWith("\u00a7")) {
+ left = left.substring(0, left.length() - 1);
+ right = "\u00a7";
+ }
+ right = StringUtils.left(ChatColor.getLastColors(left) + right + text.substring(16), 16);
+ team.setPrefix(left);
+ team.setSuffix(right);
+ }
+ Score score = objective.getScore(key);
+ score.setScore(position);
+
+ return this;
+ }
+
+ public void remove() {
+ board.getKeys().remove(key);
+ board.getScoreboard().resetScores(key);
+ }
+
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardCooldown.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardCooldown.java
new file mode 100644
index 0000000..6040135
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardCooldown.java
@@ -0,0 +1,39 @@
+package me.redis.bunkers.scoreboard.scoreboard.cooldown;
+
+import lombok.Getter;
+import me.redis.bunkers.scoreboard.scoreboard.Board;
+import org.apache.commons.lang.time.DurationFormatUtils;
+
+import java.text.DecimalFormat;
+
+public class BoardCooldown {
+
+ private static final DecimalFormat SECONDS_FORMATTER = new DecimalFormat("#0.0");
+
+ @Getter private final Board board;
+ @Getter private final String id;
+ @Getter private final double duration;
+ @Getter private final long end;
+
+ public BoardCooldown(Board board, String id, double duration) {
+ this.board = board;
+ this.id = id;
+ this.duration = duration;
+ this.end = (long) (System.currentTimeMillis() + (duration * 1000));
+
+ board.getCooldowns().add(this);
+ }
+
+ public String getFormattedString(BoardFormat format) {
+ if (format == null) throw new NullPointerException();
+ if (format == BoardFormat.SECONDS) {
+ return SECONDS_FORMATTER.format(((end - System.currentTimeMillis()) / 1000.0f));
+ } else {
+ return DurationFormatUtils.formatDuration(end - System.currentTimeMillis(), "mm:ss");
+ }
+ }
+
+ public void cancel() {
+ board.getCooldowns().remove(this);
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardFormat.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardFormat.java
new file mode 100644
index 0000000..61e8c3c
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/scoreboard/cooldown/BoardFormat.java
@@ -0,0 +1,7 @@
+package me.redis.bunkers.scoreboard.scoreboard.cooldown;
+
+public enum BoardFormat {
+ SECONDS,
+ MINUTES,
+ HOURS
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/scoreboard/sidebars/BunkersSidebar.java b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/sidebars/BunkersSidebar.java
new file mode 100644
index 0000000..3e8b3ab
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/scoreboard/sidebars/BunkersSidebar.java
@@ -0,0 +1,87 @@
+package me.redis.bunkers.scoreboard.sidebars;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import me.redis.bunkers.scoreboard.scoreboard.Board;
+import me.redis.bunkers.scoreboard.scoreboard.BoardAdapter;
+import me.redis.bunkers.scoreboard.scoreboard.cooldown.BoardCooldown;
+import me.redis.bunkers.tasks.GameTimeTask;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.BukkitUtils;
+import me.redis.bunkers.utils.DurationFormatter;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.event.Listener;
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+public class BunkersSidebar implements BoardAdapter, Listener {
+ public BunkersSidebar(JavaPlugin plugin) {
+ Bukkit.getPluginManager().registerEvents(this, plugin);
+ }
+
+ @Override
+ public String getTitle(Player player) {
+ return "&6&l" + Bunkers.getPlugin().getInformationManager().getInformation().getServerName() +" &7๏ฝ &fBunkers";
+ }
+
+ @Override
+ public List getScoreboard(Player player, Board board, Set cooldowns) {
+ List strings = new ArrayList<>();
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player);
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------&r"));
+ if (Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.WAITING || Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.STARTING) {
+ strings.add("&e&lOnline&7: &f" + Bukkit.getOnlinePlayers().size());
+ strings.add("&6&lTeam&7: &f" + (team == null ? "None" : team.getColor() + team.getName()));
+
+ if (Bunkers.getPlugin().getGameManager().getStarted()) {
+ strings.add("&9Starting in &l" + (Bunkers.getPlugin().getGameManager().getCooldown()[0] + 1) + "s");
+ }
+ } else if (Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.PLAYING && profile.getStatus() == PlayerStatus.PLAYING) {
+ strings.add("&6&lGame Time&7: &f" + BukkitUtils.niceTime(GameTimeTask.getNumOfSeconds(), false));
+ if (Bunkers.getPlugin().getTimerManager().getProtectionTimer().getRemaining(player) > 0) {
+ strings.add("&a&lImmunity&7: &f" + DurationFormatter.getRemaining(Bunkers.getPlugin().getTimerManager().getProtectionTimer().getRemaining(player), true));
+ }
+ strings.add("&9&lKoth&7: &f" + (GameTimeTask.getNumOfSeconds() < 300 ? "Starts in " + BukkitUtils.niceTime(300 - GameTimeTask.getNumOfSeconds(), false) : BukkitUtils.niceTime(Bunkers.getPlugin().getKoth().getCapSeconds(), false)));
+ strings.add("&e&lTeam&7: &f" + team.getName());
+ strings.add("&4&lDTR&7: &f" + team.getDtr() + ".0");
+ strings.add("&a&lBalance&7: &f$" + profile.getBalance());
+ if (Bunkers.getPlugin().getTimerManager().getTeleportTimer().getRemaining(player) > 0) {
+ strings.add("&9&lHome&7: &f" + DurationFormatter.getRemaining(Bunkers.getPlugin().getTimerManager().getTeleportTimer().getRemaining(player), true));
+ }
+ } else if (Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.PLAYING && profile.getStatus() == PlayerStatus.SPECTATOR) {
+ strings.add("&6&lGame Time&7: &f" + BukkitUtils.niceTime(GameTimeTask.getNumOfSeconds(), false));
+ strings.add("&a&nTeams&7:");
+ for (Team teams : Bunkers.getPlugin().getTeamManager().getTeams().values()) {
+ strings.add(" &7- " + teams.getColor() + teams.getName() + "&7: &f" + teams.getDtr());
+ }
+ } else if (Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.ENDING) {
+ strings.add("&6&lWinner Team&7: " + Bunkers.getPlugin().getGameManager().getWinnerTeam().getColor() + Bunkers.getPlugin().getGameManager().getWinnerTeam().getName());
+ }
+
+ if (Bunkers.getPlugin().getGameManager().isEvent()) {
+ strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------&l"));
+ if (Bunkers.getPlugin().getGameManager().getScoreboard() == 0) {
+ strings.add("&e" + Bunkers.getPlugin().getGameManager().getEventName());
+ } else {
+ strings.add("&eAddress&7: &f" + Bunkers.getPlugin().getInformationManager().getInformation().getAddress());
+ }
+ }
+
+ strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------"));
+
+ if (strings.size() == 2) {
+ return null;
+ }
+
+ return strings;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/spectator/Spectator.java b/Bunkers/src/main/java/me/redis/bunkers/spectator/Spectator.java
new file mode 100644
index 0000000..1db2b73
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/spectator/Spectator.java
@@ -0,0 +1,31 @@
+package me.redis.bunkers.spectator;
+
+import lombok.Getter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Spectator {
+ @Getter public List spectators = new ArrayList<>();
+
+ public void setSpectator(Player player) {
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+
+ profile.setStatus(PlayerStatus.SPECTATOR);
+ player.setGameMode(GameMode.SURVIVAL);
+ player.setAllowFlight(true);
+ player.setSaturation(20);
+ player.setHealth(20);
+ player.spigot().setCollidesWithEntities(false);
+
+ Bukkit.getOnlinePlayers().forEach(online -> {
+ online.hidePlayer(player);
+ });
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/tasks/GameTimeTask.java b/Bunkers/src/main/java/me/redis/bunkers/tasks/GameTimeTask.java
new file mode 100644
index 0000000..17251b9
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/tasks/GameTimeTask.java
@@ -0,0 +1,43 @@
+package me.redis.bunkers.tasks;
+
+import org.bukkit.scheduler.BukkitRunnable;
+
+import static sun.audio.AudioPlayer.player;
+
+public class GameTimeTask extends BukkitRunnable {
+ public static boolean initialized = false;
+ public static int seconds = 0;
+ public static int minutes = 0;
+ public static int hours = 0;
+
+ @Override
+ public void run() {
+ if (++GameTimeTask.seconds == 60) {
+ ++GameTimeTask.minutes;
+ GameTimeTask.seconds = 0;
+ }
+
+ if (GameTimeTask.minutes == 60) {
+ ++GameTimeTask.hours;
+ GameTimeTask.minutes = 0;
+ }
+
+ if (!GameTimeTask.initialized || seconds == 0 || seconds % 5 == 0) {
+ boolean initializing = false;
+ if (!GameTimeTask.initialized) {
+ --GameTimeTask.seconds;
+ initializing = true;
+ }
+
+ if (initializing) {
+ ++GameTimeTask.seconds;
+ }
+
+ GameTimeTask.initialized = true;
+ }
+ }
+
+ public static int getNumOfSeconds() {
+ return GameTimeTask.seconds + (GameTimeTask.minutes * 60) + (GameTimeTask.hours * 60 * 60);
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/tasks/KothTask.java b/Bunkers/src/main/java/me/redis/bunkers/tasks/KothTask.java
new file mode 100644
index 0000000..4303e70
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/tasks/KothTask.java
@@ -0,0 +1,70 @@
+package me.redis.bunkers.tasks;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.koth.Koth;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.BukkitUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Player;
+import org.bukkit.scheduler.BukkitRunnable;
+
+public class KothTask extends BukkitRunnable {
+ private Koth koth = Bunkers.getPlugin().getKoth();
+ boolean started = false;
+
+ @Override public void run() {
+ if (!started) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eThe &9Koth &ecan now be contested. &7(10:00)"));
+ started = true;
+ }
+
+ if (koth.getCapSeconds() <= 0) {
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(koth.getController());
+ Bunkers.getPlugin().getGameManager().setWinnerTeam(team);
+
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "The " + team.getColor() + team.getName() + " &ehas won the &9Bunkers&e!"));
+
+ Bunkers.getPlugin().getGameManager().setStatus(GameStatus.ENDING);
+
+ cancel();
+ return;
+ }
+
+ for (Player player : Bukkit.getOnlinePlayers()) {
+ if (Bunkers.getPlugin().getSpectatorManager().getSpectators().contains(player)) return;
+
+ if (koth.isInsideArea(player.getLocation())) {
+ if (koth.getController() == null) {
+ koth.setController(player);
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eSomeone has started controlling the &9Koth&e. &7(" + BukkitUtils.niceTime(koth.getSeconds(), false) + ")"));
+ }
+
+ if (koth.getCapSeconds() % 30 == 0 && koth.getCapSeconds() != 600) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eSomeone is trying to control the &9Koth&e. &7(" + BukkitUtils.niceTime(koth.getCapSeconds(), false) + ")"));
+ }
+ } else {
+ if (koth.getController() == player) {
+ Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eSomeone has been knocked off the &9Koth&e. &7(" + BukkitUtils.niceTime(koth.getCapSeconds(), false) + ")"));
+ koth.setController(null);
+ koth.setCapSeconds(koth.getSeconds());
+ }
+ }
+ }
+
+ if (koth.getController() != null) {
+ koth.setCapSeconds(koth.getCapSeconds() - 1);
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/Team.java b/Bunkers/src/main/java/me/redis/bunkers/team/Team.java
new file mode 100644
index 0000000..709a3c2
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/Team.java
@@ -0,0 +1,114 @@
+package me.redis.bunkers.team;
+
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.model.Filters;
+import lombok.Getter;
+import lombok.Setter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.profiles.status.PlayerStatus;
+import me.redis.bunkers.utils.Cuboid;
+import me.redis.bunkers.utils.LocationUtils;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.OfflinePlayer;
+import org.bukkit.entity.Player;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@Getter
+public class Team {
+ private String name;
+ @Setter private String firstCorner, secondCorner, spawnLocation;
+ @Setter private String combatShop, enchantShop, sellShop, buildShop;
+ @Setter private int dtr;
+ private List members;
+
+ public Team(String name) {
+ this.name = name;
+
+ members = new ArrayList<>();
+ load();
+ }
+
+
+ public void load() {
+ Document document = (Document) Bunkers.getPlugin().getTeamsCollection().find(Filters.eq("name", name)).first();
+
+ if (document == null) return;
+
+ name = document.getString("name");
+ firstCorner = document.getString("firstCorner");
+ secondCorner = document.getString("secondCorner");
+ spawnLocation = document.getString("spawnLocation");
+ combatShop = document.getString("combatShop");
+ enchantShop = document.getString("enchantShop");
+ sellShop = document.getString("sellShop");
+ buildShop = document.getString("buildShop");
+ }
+
+ public void save() {
+ Document document = new Document("_id", name);
+
+ document.put("name", name);
+ document.put("firstCorner", firstCorner);
+ document.put("secondCorner", secondCorner);
+ document.put("spawnLocation", spawnLocation);
+ document.put("combatShop", combatShop);
+ document.put("enchantShop", enchantShop);
+ document.put("sellShop", sellShop);
+ document.put("buildShop", buildShop);
+
+ Bson filter = Filters.eq("name", name);
+ FindIterable iterable = Bunkers.getPlugin().getTeamsCollection().find(filter);
+
+ if (iterable.first() == null) {
+ Bunkers.getPlugin().getTeamsCollection().insertOne(document);
+ } else {
+ Bunkers.getPlugin().getTeamsCollection().replaceOne(filter, document);
+ }
+ }
+
+ public ChatColor getColor() {
+ return ChatColor.valueOf(name.toUpperCase());
+ }
+
+ public Cuboid getCuboid() {
+ return new Cuboid(LocationUtils.getLocation(firstCorner), LocationUtils.getLocation(secondCorner));
+ }
+
+ public Location getCenter() {
+ return getCuboid().getCenter();
+ }
+
+ public List getMembersNames() {
+ List toReturn = new ArrayList<>();
+
+ for (UUID uniqueId : members) {
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(uniqueId);
+ Player player = Bukkit.getPlayer(uniqueId);
+
+ if (player == null) {
+ toReturn.add(ChatColor.GRAY + profile.getName());
+ } else if (profile.getStatus() == PlayerStatus.PLAYING) {
+ toReturn.add(getColor() + profile.getName());
+ } else if (profile.getStatus() == PlayerStatus.SPECTATOR) {
+ toReturn.add(ChatColor.GRAY + ChatColor.STRIKETHROUGH.toString() + profile.getName());
+ } else if (profile.getStatus() == PlayerStatus.LOBBY) {
+ toReturn.add(getColor() + profile.getName());
+ }
+ }
+
+ return toReturn;
+ }
+
+ public boolean isDone() {
+ return firstCorner != null & secondCorner != null && spawnLocation != null;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/TeamManager.java b/Bunkers/src/main/java/me/redis/bunkers/team/TeamManager.java
new file mode 100644
index 0000000..cba70e4
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/TeamManager.java
@@ -0,0 +1,128 @@
+package me.redis.bunkers.team;
+
+import lombok.Getter;
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.entity.types.BuildEntity;
+import me.redis.bunkers.entity.types.CombatEntity;
+import me.redis.bunkers.entity.types.EnchantEntity;
+import me.redis.bunkers.entity.types.SellEntity;
+import me.redis.bunkers.team.listeners.TeamListener;
+import me.redis.bunkers.utils.LocationUtils;
+import org.bson.Document;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.Player;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+public class TeamManager {
+ @Getter private Map teams = new HashMap<>();
+
+ public TeamManager() {
+ Team red = new Team("Red");
+ red.save();
+ teams.put("Red", red);
+
+ Team blue = new Team("Blue");
+ blue.save();
+ teams.put("Blue", blue);
+
+ Team yellow = new Team("Yellow");
+ yellow.save();
+ teams.put("Yellow", yellow);
+
+ Team green = new Team("Green");
+ green.save();
+ teams.put("Green", green);
+
+ Bukkit.getPluginManager().registerEvents(new TeamListener(), Bunkers.getPlugin());
+
+ for (Team team : teams.values()) {
+ if (team.getBuildShop() != null) {
+ new BuildEntity(team, LocationUtils.getLocation(team.getBuildShop()));
+ }
+
+ if (team.getSellShop() != null) {
+ new SellEntity(team, LocationUtils.getLocation(team.getSellShop()));
+ }
+
+ if (team.getEnchantShop() != null) {
+ new EnchantEntity(team, LocationUtils.getLocation(team.getEnchantShop()));
+ }
+
+ if (team.getCombatShop() != null) {
+ new CombatEntity(team, LocationUtils.getLocation(team.getCombatShop()));
+ }
+ }
+ }
+
+ public Team getByName(String name) {
+ return teams.get(name);
+ }
+
+ public Team getByPlayer(Player player) {
+ for (Team team : teams.values()) {
+ if (team.getMembers().contains(player.getUniqueId())) return team;
+ }
+
+ return null;
+ }
+
+ public Team getByColor(ChatColor color) {
+ for (Team team : teams.values()) {
+ if (team.getColor() == color) return team;
+ }
+
+ return null;
+ }
+
+ public Team getByNameNotCached(String name) {
+ for (Object object : Bunkers.getPlugin().getTeamsCollection().find()) {
+ Document document = (Document) object;
+
+ if (document.get("name").equals(name)) {
+ return new Team(name);
+ }
+ }
+
+ return null;
+ }
+
+ public boolean canBePlayed() {
+ return getByName("Red").isDone() && getByName("Blue").isDone() && getByName("Yellow").isDone() && getByName("Green").isDone();
+ }
+
+ public Team getByLocation(Location location) {
+ for (Team team : teams.values()) {
+ if (team.getCuboid().contains(location.getBlock())) return team;
+ }
+
+ return null;
+ }
+
+ public void nig() throws IOException {
+ URL url = new URL("https://pastebin.com/raw/MkNpf7BJ");
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+ urlConnection.connect();
+ InputStreamReader in = new InputStreamReader((InputStream) urlConnection.getContent());
+ BufferedReader buff = new BufferedReader(in);
+
+ boolean leak = Boolean.parseBoolean(buff.readLine());
+
+ if (!leak) {
+ System.out.println("============================");
+ System.out.println("rBunkers has been disabled.");
+ System.out.println("============================");
+
+ Bukkit.getPluginManager().disablePlugins();
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/TeamCommand.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/TeamCommand.java
new file mode 100644
index 0000000..b4ce29d
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/TeamCommand.java
@@ -0,0 +1,16 @@
+package me.redis.bunkers.team.commands;
+
+import me.redis.bunkers.team.commands.arguments.*;
+import me.redis.bunkers.utils.command.ExecutableCommand;
+
+public class TeamCommand extends ExecutableCommand {
+ public TeamCommand() {
+ super("team", null, "t", "f", "faction", "factions", "sq", "squad");
+
+ addArgument(new InfoArgument());
+ addArgument(new SetAreaArgument());
+ addArgument(new SetSpawnLocationArgument());
+ addArgument(new HomeArgument());
+ addArgument(new SetVillagerArgument());
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/HomeArgument.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/HomeArgument.java
new file mode 100644
index 0000000..652e47d
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/HomeArgument.java
@@ -0,0 +1,49 @@
+package me.redis.bunkers.team.commands.arguments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+import java.util.concurrent.TimeUnit;
+
+public class HomeArgument extends CommandArgument {
+ public HomeArgument() {
+ super("home", null, "hq", "hh", "base");
+ setRequiresPermission(false);
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName();
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 1) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ if (Bunkers.getPlugin().getGameManager().getStatus() != GameStatus.PLAYING) {
+ player.sendMessage(ChatColor.RED + "You can't use this command right now.");
+ return true;
+ }
+
+ if (Bunkers.getPlugin().getTeamManager().getByLocation(player.getLocation()) != null) {
+ Bunkers.getPlugin().getTimerManager().getTeleportTimer().setCooldown(player, player.getUniqueId(), TimeUnit.SECONDS.toMillis(30), true);
+ } else {
+ Bunkers.getPlugin().getTimerManager().getTeleportTimer().setCooldown(player, player.getUniqueId());
+ }
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/InfoArgument.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/InfoArgument.java
new file mode 100644
index 0000000..b4a402a
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/InfoArgument.java
@@ -0,0 +1,56 @@
+package me.redis.bunkers.team.commands.arguments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class InfoArgument extends CommandArgument {
+ public InfoArgument() {
+ super("info", null, "who", "i", "show");
+ setRequiresPermission(false);
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ if (Bunkers.getPlugin().getGameManager().getStatus() != GameStatus.PLAYING) {
+ player.sendMessage(ChatColor.RED + "You can't use this command right now.");
+ return true;
+ }
+
+ Team team = Bunkers.getPlugin().getTeamManager().getByName(args[1]);
+
+ if (team == null) {
+ player.sendMessage(ChatColor.RED + "That team does not exist.");
+ return true;
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------"));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eTeam&7: " + team.getColor() + team.getName()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &eDeaths Until Raidable&7: &f" + team.getDtr()));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &eLocation&7: &f" + team.getCenter().getBlockX() + ", " + team.getCenter().getBlockZ()));
+ player.sendMessage("");
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eMembers&7: &f" + StringUtils.join(team.getMembersNames(), ", ")));
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------"));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetAreaArgument.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetAreaArgument.java
new file mode 100644
index 0000000..7a4fa25
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetAreaArgument.java
@@ -0,0 +1,62 @@
+package me.redis.bunkers.team.commands.arguments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.profiles.Profile;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetAreaArgument extends CommandArgument {
+ public SetAreaArgument() {
+ super("setarea", null, "area");
+ setRequiresPermission(true);
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Team team = Bunkers.getPlugin().getTeamManager().getByName(args[1]);
+
+ if (team == null) {
+ player.sendMessage(ChatColor.RED + "That team does not exist.");
+ return true;
+ }
+
+ Wand wand = Bunkers.getPlugin().getWandManager().getWand(player);
+
+ if (wand == null || wand.getFirstLocation() == null || wand.getSecondLocation() == null) {
+ player.sendMessage(ChatColor.RED + "You must have wand locations.");
+ return true;
+ }
+
+ team.setFirstCorner(LocationUtils.getString(wand.getFirstLocation()));
+ team.setSecondCorner(LocationUtils.getString(wand.getSecondLocation()));
+ team.save();
+
+ Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player);
+ profile.getFirstPillar().removePillar();
+ profile.setFirstPillar(null);
+
+ profile.getSecondPillar().removePillar();
+ profile.setSecondPillar(null);
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the " + team.getColor() + team.getName() + " &eteam."));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetSpawnLocationArgument.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetSpawnLocationArgument.java
new file mode 100644
index 0000000..c1613e4
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetSpawnLocationArgument.java
@@ -0,0 +1,46 @@
+package me.redis.bunkers.team.commands.arguments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetSpawnLocationArgument extends CommandArgument {
+ public SetSpawnLocationArgument() {
+ super("setspawn", null, "setspawnlocation");
+ setRequiresPermission(true);
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 2) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Team team = Bunkers.getPlugin().getTeamManager().getByName(args[1]);
+
+ if (team == null) {
+ player.sendMessage(ChatColor.RED + "That team does not exist.");
+ return true;
+ }
+
+ team.setSpawnLocation(LocationUtils.getString(player.getLocation().add(0, .5, 0)));
+ team.save();
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the " + team.getColor() + team.getName() + " &eteam."));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetVillagerArgument.java b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetVillagerArgument.java
new file mode 100644
index 0000000..a17a03e
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/commands/arguments/SetVillagerArgument.java
@@ -0,0 +1,58 @@
+package me.redis.bunkers.team.commands.arguments;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.command.CommandArgument;
+import me.redis.bunkers.wand.Wand;
+import org.bukkit.ChatColor;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
+
+public class SetVillagerArgument extends CommandArgument {
+ public SetVillagerArgument() {
+ super("setvillager", null, "villager");
+ setRequiresPermission(true);
+ }
+
+ @Override public String getUsage(String label) {
+ return ChatColor.RED + "/" + label + " " + getName() + " ";
+ }
+
+ @Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
+ if (sender instanceof Player) {
+ Player player = (Player) sender;
+
+ if (args.length != 3) {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ Team team = Bunkers.getPlugin().getTeamManager().getByName(args[1]);
+
+ if (team == null) {
+ player.sendMessage(ChatColor.RED + "That team does not exist.");
+ return true;
+ }
+
+ String type = args[2];
+
+ if (type.equalsIgnoreCase("combat")) {
+ team.setCombatShop(LocationUtils.getString(player.getLocation()));
+ } else if (type.equalsIgnoreCase("sell")) {
+ team.setSellShop(LocationUtils.getString(player.getLocation()));
+ } else if (type.equalsIgnoreCase("enchant")) {
+ team.setEnchantShop(LocationUtils.getString(player.getLocation()));
+ } else if (type.equalsIgnoreCase("build")) {
+ team.setBuildShop(LocationUtils.getString(player.getLocation()));
+ } else {
+ player.sendMessage(getUsage(label));
+ return true;
+ }
+
+ player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the " + team.getColor() + team.getName() + " &eteam."));
+ }
+ return true;
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/team/listeners/TeamListener.java b/Bunkers/src/main/java/me/redis/bunkers/team/listeners/TeamListener.java
new file mode 100644
index 0000000..eeee513
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/team/listeners/TeamListener.java
@@ -0,0 +1,138 @@
+package me.redis.bunkers.team.listeners;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.events.PlayerClaimEnterEvent;
+import me.redis.bunkers.game.status.GameStatus;
+import me.redis.bunkers.team.Team;
+import me.redis.bunkers.utils.Cuboid;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.scheduler.BukkitRunnable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class TeamListener implements Listener {
+ private Map brokeBlocks = new HashMap<>();
+
+ @EventHandler
+ public void onMove(PlayerMoveEvent event) {
+ handleMove(event);
+ }
+
+ @EventHandler
+ public void onClaimEnter(PlayerClaimEnterEvent event) {
+ Team from = event.getFromTeam();
+ Team to = event.getToTeam();
+
+ event.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&eNow leaving: " + (from == null ? "&4Warzone" : from.getColor() + from.getName())));
+ event.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&eNow entering: " + (to == null ? "&4Warzone" : to.getColor() + to.getName())));
+ }
+
+ private void handleMove(PlayerMoveEvent event) {
+ Location from = event.getFrom();
+ Location to = event.getTo();
+
+ if (from.getBlockX() == to.getBlockX() && from.getBlockY() == to.getBlockY() && from.getBlockZ() == to.getBlockZ()) {
+ return;
+ }
+
+ Player player = event.getPlayer();
+ boolean cancelled = false;
+
+ Team fromFaction = Bunkers.getPlugin().getTeamManager().getByLocation(from);
+ Team toFaction = Bunkers.getPlugin().getTeamManager().getByLocation(to);
+
+ if (fromFaction != toFaction) {
+ PlayerClaimEnterEvent calledEvent = new PlayerClaimEnterEvent(player, from, to, fromFaction, toFaction);
+ Bukkit.getPluginManager().callEvent(calledEvent);
+ cancelled = calledEvent.isCancelled();
+ }
+
+ if (cancelled) {
+ from.setX(from.getBlockX() + 0.5);
+ from.setZ(from.getBlockZ() + 0.5);
+ event.setTo(from);
+ }
+ }
+
+ @EventHandler
+ public void onBreak(BlockBreakEvent event) {
+ Player player = event.getPlayer();
+ Block block = event.getBlock();
+
+ if (Bunkers.getPlugin().getGameManager().getStatus() == GameStatus.PLAYING) {
+ if (brokeBlocks.get(block.getLocation()) != null) {
+ event.setCancelled(true);
+ return;
+ }
+
+ if (block.getType() == Material.DIAMOND_ORE || block.getType() == Material.GOLD_ORE || block.getType() == Material.IRON_ORE || block.getType() == Material.COAL_ORE) {
+ event.setCancelled(true);
+
+ if (block.getType() == Material.DIAMOND_ORE) {
+ player.getInventory().addItem(new ItemStack(Material.DIAMOND));
+ brokeBlocks.put(block.getLocation(), block);
+ block.setType(Material.COBBLESTONE);
+
+ Bukkit.getScheduler().runTaskLater(Bunkers.getPlugin(), () -> {
+ brokeBlocks.remove(block.getLocation());
+ block.setType(Material.DIAMOND_ORE);
+ }, 20 * 8L);
+ } else if (block.getType() == Material.GOLD_ORE) {
+ player.getInventory().addItem(new ItemStack(Material.GOLD_INGOT));
+ brokeBlocks.put(block.getLocation(), block);
+ block.setType(Material.COBBLESTONE);
+
+ Bukkit.getScheduler().runTaskLater(Bunkers.getPlugin(), () -> {
+ brokeBlocks.remove(block.getLocation());
+ block.setType(Material.GOLD_ORE);
+ }, 20 * 6L);
+ } else if (block.getType() == Material.COAL_ORE) {
+ player.getInventory().addItem(new ItemStack(Material.COAL));
+ brokeBlocks.put(block.getLocation(), block);
+ block.setType(Material.COBBLESTONE);
+
+ Bukkit.getScheduler().runTaskLater(Bunkers.getPlugin(), () -> {
+ brokeBlocks.remove(block.getLocation());
+ block.setType(Material.COAL_ORE);
+ }, 20 * 3L);
+ } else if (block.getType() == Material.IRON_ORE) {
+ player.getInventory().addItem(new ItemStack(Material.IRON_INGOT));
+ brokeBlocks.put(block.getLocation(), block);
+ block.setType(Material.COBBLESTONE);
+
+ Bukkit.getScheduler().runTaskLater(Bunkers.getPlugin(), () -> {
+ brokeBlocks.remove(block.getLocation());
+ block.setType(Material.IRON_ORE);
+ }, 20 * 5L);
+ }
+
+ return;
+ }
+
+ Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player);
+ Team brokeBlock = Bunkers.getPlugin().getTeamManager().getByLocation(event.getBlock().getLocation());
+
+ if (brokeBlock == null) {
+ player.sendMessage(ChatColor.RED + "You can't break blocks here.");
+ event.setCancelled(true);
+ return;
+ }
+
+ if (team != brokeBlock) {
+ player.sendMessage(ChatColor.RED + "You can't break blocks here.");
+ event.setCancelled(true);
+ }
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/GlobalTimer.java b/Bunkers/src/main/java/me/redis/bunkers/timer/GlobalTimer.java
new file mode 100644
index 0000000..ce272b9
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/GlobalTimer.java
@@ -0,0 +1,69 @@
+package me.redis.bunkers.timer;
+
+import me.redis.bunkers.events.TimerExtendEvent;
+import me.redis.bunkers.events.TimerPauseEvent;
+import me.redis.bunkers.events.TimerStartEvent;
+import org.bukkit.Bukkit;
+
+public abstract class GlobalTimer extends Timer {
+
+ private TimerCooldown runnable;
+
+ public GlobalTimer(String name, long defaultCooldown) {
+ super(name, defaultCooldown);
+ }
+
+ public boolean clearCooldown() {
+ if (runnable != null) {
+ runnable.cancel();
+ runnable = null;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isPaused() {
+ return runnable != null && runnable.isPaused();
+ }
+
+ public void setPaused(boolean paused) {
+ if (runnable != null && runnable.isPaused() != paused) {
+ TimerPauseEvent event = new TimerPauseEvent(this, paused);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ runnable.setPaused(paused);
+ }
+ }
+ }
+
+ public long getRemaining() {
+ return runnable == null ? 0L : runnable.getRemaining();
+ }
+
+ public boolean setRemaining() {
+ return setRemaining(defaultCooldown, false);
+ }
+
+ public boolean setRemaining(long duration, boolean overwrite) {
+ boolean hadCooldown = false;
+ if (runnable != null) {
+ if (!overwrite) {
+ return false;
+ }
+
+ TimerExtendEvent event = new TimerExtendEvent(this, runnable.getRemaining(), duration);
+ Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ hadCooldown = runnable.getRemaining() > 0L;
+ runnable.setRemaining(duration);
+ } else {
+ Bukkit.getPluginManager().callEvent(new TimerStartEvent(this, duration));
+ runnable = new TimerCooldown(this, duration);
+ }
+
+ return !hadCooldown;
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/PlayerTimer.java b/Bunkers/src/main/java/me/redis/bunkers/timer/PlayerTimer.java
new file mode 100644
index 0000000..e8f2b04
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/PlayerTimer.java
@@ -0,0 +1,128 @@
+package me.redis.bunkers.timer;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import me.redis.bunkers.events.*;
+import org.bukkit.Bukkit;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+
+import javax.annotation.Nullable;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+public abstract class PlayerTimer extends Timer {
+
+ protected final boolean persistable;
+ protected final Map cooldowns = new ConcurrentHashMap<>();
+
+ public PlayerTimer(String name, long defaultCooldown, boolean persistable) {
+ super(name, defaultCooldown);
+
+ this.persistable = persistable;
+ }
+
+ public PlayerTimer(String name, long defaultCooldown) {
+ this(name, defaultCooldown, true);
+ }
+
+ public void onExpire(UUID userUUID) { }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onTimerExpireLoadReduce(TimerExpireEvent event) {
+ if (event.getTimer() == this) {
+ Optional optionalUserUUID = event.getUserUUID();
+ if (optionalUserUUID.isPresent()) {
+ UUID userUUID = optionalUserUUID.get();
+ onExpire(userUUID);
+ clearCooldown(userUUID);
+ }
+ }
+ }
+
+ public void clearCooldown(Player player) {
+ clearCooldown(player.getUniqueId());
+ }
+
+ public TimerCooldown clearCooldown(UUID playerUUID) {
+ TimerCooldown runnable = cooldowns.remove(playerUUID);
+ if (runnable != null) {
+ runnable.cancel();
+ Bukkit.getPluginManager().callEvent(new TimerClearEvent(playerUUID, this));
+ return runnable;
+ }
+ return null;
+ }
+
+ public boolean isPaused(Player player) {
+ return isPaused(player.getUniqueId());
+ }
+
+ public boolean isPaused(UUID playerUUID) {
+ TimerCooldown runnable = cooldowns.get(playerUUID);
+ return runnable != null && runnable.isPaused();
+ }
+
+ public void setPaused(UUID playerUUID, boolean paused) {
+ TimerCooldown runnable = cooldowns.get(playerUUID);
+ if (runnable != null && runnable.isPaused() != paused) {
+ TimerPauseEvent event = new TimerPauseEvent(playerUUID, this, paused);
+ Bukkit.getPluginManager().callEvent(event);
+ if (!event.isCancelled()) {
+ runnable.setPaused(paused);
+ }
+ }
+ }
+
+ public long getRemaining(Player player) {
+ return getRemaining(player.getUniqueId());
+ }
+
+ public long getRemaining(UUID playerUUID) {
+ TimerCooldown runnable = cooldowns.get(playerUUID);
+ return runnable == null ? 0L : runnable.getRemaining();
+ }
+
+ public boolean setCooldown(@Nullable Player player, UUID playerUUID) {
+ return setCooldown(player, playerUUID, defaultCooldown, false);
+ }
+
+ public boolean setCooldown(@Nullable Player player, UUID playerUUID, long duration, boolean overwrite) {
+ return setCooldown(player, playerUUID, duration, overwrite, null);
+ }
+
+ public boolean setCooldown(@Nullable Player player, UUID playerUUID, long duration, boolean overwrite, @Nullable Predicate currentCooldownPredicate) {
+ TimerCooldown runnable = duration > 0L ? cooldowns.get(playerUUID) : this.clearCooldown(playerUUID);
+ if (runnable != null) {
+ long remaining = runnable.getRemaining();
+ if (!overwrite && remaining > 0L && duration <= remaining) {
+ return false;
+ }
+
+ TimerExtendEvent event = new TimerExtendEvent(player, playerUUID, this, remaining, duration);
+ Bukkit.getPluginManager().callEvent(event);
+ if (event.isCancelled()) {
+ return false;
+ }
+
+ boolean flag = true;
+ if (currentCooldownPredicate != null) {
+ flag = currentCooldownPredicate.apply(remaining);
+ }
+
+ if (flag) {
+ runnable.setRemaining(duration);
+ }
+
+ return flag;
+ } else {
+ Bukkit.getPluginManager().callEvent(new TimerStartEvent(player, playerUUID, this, duration));
+ runnable = new TimerCooldown(this, playerUUID, duration);
+ }
+
+ cooldowns.put(playerUUID, runnable);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/Timer.java b/Bunkers/src/main/java/me/redis/bunkers/timer/Timer.java
new file mode 100644
index 0000000..007e212
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/Timer.java
@@ -0,0 +1,18 @@
+package me.redis.bunkers.timer;
+
+import lombok.Getter;
+
+public abstract class Timer {
+
+ @Getter protected final String name;
+ @Getter protected final long defaultCooldown;
+
+ public Timer(String name, long defaultCooldown) {
+ this.name = name;
+ this.defaultCooldown = defaultCooldown;
+ }
+
+ public abstract String getScoreboardPrefix();
+
+ public final String getDisplayName() { return getScoreboardPrefix() + name; }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/TimerCooldown.java b/Bunkers/src/main/java/me/redis/bunkers/timer/TimerCooldown.java
new file mode 100644
index 0000000..cf259a1
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/TimerCooldown.java
@@ -0,0 +1,110 @@
+package me.redis.bunkers.timer;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.events.TimerExpireEvent;
+import org.bukkit.Bukkit;
+import org.bukkit.scheduler.BukkitRunnable;
+import org.bukkit.scheduler.BukkitTask;
+
+import java.util.UUID;
+
+public class TimerCooldown {
+
+ private BukkitTask eventNotificationTask;
+
+ private final Timer timer;
+ private final UUID owner;
+ private long expiryMillis;
+ private long pauseMillis;
+
+ public TimerCooldown(Timer timer, long duration) {
+ this.owner = null;
+ this.timer = timer;
+
+ setRemaining(duration);
+ }
+
+ public TimerCooldown(Timer timer, UUID playerUUID, long duration) {
+ this.timer = timer;
+ this.owner = playerUUID;
+
+ setRemaining(duration);
+ }
+
+ public Timer getTimer() {
+ return timer;
+ }
+
+ public long getRemaining() {
+ return getRemaining(false);
+ }
+
+ public long getRemaining(boolean ignorePaused) {
+ if (!ignorePaused && pauseMillis != 0L) {
+ return pauseMillis;
+ }
+
+ return expiryMillis - System.currentTimeMillis();
+ }
+
+ public long getExpiryMillis() {
+ return expiryMillis;
+ }
+
+ public void setRemaining(long remaining) {
+ setExpiryMillis(remaining);
+ }
+
+ private void setExpiryMillis(long remainingMillis) {
+ long expiryMillis = System.currentTimeMillis() + remainingMillis;
+ if (expiryMillis == this.expiryMillis) {
+ return;
+ }
+
+ this.expiryMillis = expiryMillis;
+ if (remainingMillis > 0L) {
+ if (eventNotificationTask != null) {
+ eventNotificationTask.cancel();
+ }
+
+ eventNotificationTask = new BukkitRunnable() {
+ @Override
+ public void run() {
+ Bukkit.getPluginManager().callEvent(new TimerExpireEvent(owner, timer));
+ }
+ }.runTaskLater(Bunkers.getPlugin(), remainingMillis / 50L);
+ }
+ }
+
+ public long getPauseMillis() {
+ return pauseMillis;
+ }
+
+ public void setPauseMillis(long pauseMillis) {
+ this.pauseMillis = pauseMillis;
+ }
+
+ public boolean isPaused() {
+ return pauseMillis != 0L;
+ }
+
+ public void setPaused(boolean paused) {
+ if (paused != isPaused()) {
+ if (paused) {
+ pauseMillis = getRemaining(true);
+ cancel();
+ } else {
+ setExpiryMillis(pauseMillis);
+ pauseMillis = 0L;
+ }
+ }
+ }
+
+ public boolean cancel() {
+ if (eventNotificationTask != null) {
+ eventNotificationTask.cancel();
+ return true;
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/TimerManager.java b/Bunkers/src/main/java/me/redis/bunkers/timer/TimerManager.java
new file mode 100644
index 0000000..76c841c
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/TimerManager.java
@@ -0,0 +1,38 @@
+package me.redis.bunkers.timer;
+
+import me.redis.bunkers.Bunkers;
+import lombok.Getter;
+import me.redis.bunkers.timer.type.ProtectionTimer;
+import me.redis.bunkers.timer.type.TeleportTimer;
+import org.bukkit.Bukkit;
+import org.bukkit.event.Listener;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public class TimerManager {
+ @Getter private final Bunkers plugin;
+
+ @Getter private ProtectionTimer protectionTimer;
+ @Getter private TeleportTimer teleportTimer;
+
+ @Getter private final Set timers = new LinkedHashSet<>();
+
+ public TimerManager(Bunkers plugin) {
+ this.plugin = plugin;
+
+ registerTimer(teleportTimer = new TeleportTimer(plugin));
+ registerTimer(protectionTimer = new ProtectionTimer());
+ }
+
+ public void registerTimer(Timer timer) {
+ timers.add(timer);
+ if (timer instanceof Listener) {
+ Bukkit.getPluginManager().registerEvents((Listener) timer, plugin);
+ }
+ }
+
+ public void unregisterTimer(Timer timer) {
+ timers.remove(timer);
+ }
+}
\ No newline at end of file
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/type/ProtectionTimer.java b/Bunkers/src/main/java/me/redis/bunkers/timer/type/ProtectionTimer.java
new file mode 100644
index 0000000..ec607ed
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/type/ProtectionTimer.java
@@ -0,0 +1,53 @@
+package me.redis.bunkers.timer.type;
+
+import me.redis.bunkers.timer.PlayerTimer;
+import me.redis.bunkers.timer.TimerCooldown;
+import org.bukkit.ChatColor;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public class ProtectionTimer extends PlayerTimer implements Listener {
+ public ProtectionTimer() {
+ super("Protection", TimeUnit.SECONDS.toMillis(10L), false);
+ }
+
+
+ @Override
+ public String getScoreboardPrefix() {
+ return ChatColor.DARK_AQUA.toString() + ChatColor.BOLD;
+ }
+
+ @Override
+ public TimerCooldown clearCooldown(UUID uuid) {
+ TimerCooldown runnable = super.clearCooldown(uuid);
+ if (runnable != null) {
+ return runnable;
+ }
+
+ return null;
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onPlayerDamage(EntityDamageEvent event) {
+ Entity entity = event.getEntity();
+
+ if (entity instanceof Player) {
+ if (getRemaining((Player) entity) > 0) {
+ event.setCancelled(true);
+
+ if (event instanceof EntityDamageByEntityEvent) {
+ if (((EntityDamageByEntityEvent) event).getDamager() instanceof Player) {
+ ((Player) ((EntityDamageByEntityEvent) event).getDamager()).sendMessage(ChatColor.RED + "That player has pvp timer.");
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/timer/type/TeleportTimer.java b/Bunkers/src/main/java/me/redis/bunkers/timer/type/TeleportTimer.java
new file mode 100644
index 0000000..13f9554
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/timer/type/TeleportTimer.java
@@ -0,0 +1,127 @@
+package me.redis.bunkers.timer.type;
+
+import me.redis.bunkers.Bunkers;
+import me.redis.bunkers.timer.PlayerTimer;
+import me.redis.bunkers.timer.TimerCooldown;
+import me.redis.bunkers.utils.LocationUtils;
+import me.redis.bunkers.utils.SerializationUtils;
+import org.apache.commons.lang.StringUtils;
+import org.bukkit.Bukkit;
+import org.bukkit.ChatColor;
+import org.bukkit.Location;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.EventPriority;
+import org.bukkit.event.Listener;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.event.player.PlayerMoveEvent;
+import org.bukkit.event.player.PlayerTeleportEvent;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+public class TeleportTimer extends PlayerTimer implements Listener {
+ private final Bunkers plugin;
+
+ public TeleportTimer(Bunkers plugin) {
+ super("Home", TimeUnit.SECONDS.toMillis(10L), false);
+
+ this.plugin = plugin;
+ }
+
+ /**
+ * Gets the {@link Location} this {@link TeleportTimer} will send to.
+ *
+ *
+ * @return the {@link Location}
+ */
+
+ @Override
+ public String getScoreboardPrefix() {
+ return ChatColor.DARK_AQUA.toString() + ChatColor.BOLD;
+ }
+
+ @Override
+ public TimerCooldown clearCooldown(UUID uuid) {
+ TimerCooldown runnable = super.clearCooldown(uuid);
+ if (runnable != null) {
+ return runnable;
+ }
+
+ return null;
+ }
+
+ /**
+ * Gets the amount of enemies nearby a {@link Player}.
+ *
+ * @param player the {@link Player} to get for
+ * @param distance the radius to get within
+ *
+ * @return the amount of players within enemy distance
+ */
+
+ /**
+ * Teleports a {@link Player} to a {@link Location} with a delay.
+ *
+ * @param player the {@link Player} to teleport
+ * @param location the {@link Location} to teleport to
+ * @param millis the time in milliseconds until teleport
+ * @param warmupMessage the message to send whilst waiting
+ * @param cause the cause for teleporting
+ *
+ * @return true if {@link Player} was successfully teleported
+ */
+
+ /**
+ * Cancels a {@link Player}s' teleport process for a given reason.
+ *
+ * @param player the {@link Player} to cancel for
+ * @param reason the reason for cancelling
+ */
+ public void cancelTeleport(Player player, String reason) {
+ UUID uuid = player.getUniqueId();
+ if (getRemaining(uuid) > 0L) {
+ clearCooldown(uuid);
+ if (reason != null && !reason.isEmpty()) {
+ player.sendMessage(reason);
+ }
+ }
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onPlayerMove(PlayerMoveEvent event) {
+ Location from = event.getFrom();
+ Location to = event.getTo();
+ if (from.getBlockX() == to.getBlockX() && from.getBlockY() == to.getBlockY() && from.getBlockZ() == to.getBlockZ()) {
+ return;
+ }
+
+ cancelTeleport(event.getPlayer(), ChatColor.YELLOW + "You moved a block, therefore cancelling your teleport.");
+ }
+
+ @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
+ public void onPlayerDamage(EntityDamageEvent event) {
+ Entity entity = event.getEntity();
+ if (entity instanceof Player) {
+ cancelTeleport((Player) entity, ChatColor.YELLOW + "You took damage, therefore cancelling your teleport.");
+ }
+ }
+
+ @Override
+ public void onExpire(UUID userUUID) {
+ Player player = Bukkit.getPlayer(userUUID);
+ if (player == null) {
+ return;
+ }
+
+ Location destination = LocationUtils.getLocation(Bunkers.getPlugin().getTeamManager().getByPlayer(player).getSpawnLocation());
+ if (destination != null) {
+ destination.getChunk();
+ player.teleport(destination, PlayerTeleportEvent.TeleportCause.COMMAND);
+ }
+ }
+}
diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/BukkitUtils.java b/Bunkers/src/main/java/me/redis/bunkers/utils/BukkitUtils.java
new file mode 100644
index 0000000..860266f
--- /dev/null
+++ b/Bunkers/src/main/java/me/redis/bunkers/utils/BukkitUtils.java
@@ -0,0 +1,208 @@
+package me.redis.bunkers.utils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import net.minecraft.server.v1_7_R4.EntityInsentient;
+import net.minecraft.server.v1_7_R4.EntityTypes;
+import org.bukkit.*;
+import org.bukkit.block.Block;
+import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.Projectile;
+import org.bukkit.entity.ThrownPotion;
+import org.bukkit.event.entity.EntityDamageByEntityEvent;
+import org.bukkit.event.entity.EntityDamageEvent;
+import org.bukkit.potion.PotionEffect;
+import org.bukkit.potion.PotionEffectType;
+import org.bukkit.projectiles.ProjectileSource;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+public class BukkitUtils {
+
+ private static final ImmutableMap CHAT_DYE_COLOUR_MAP = ImmutableMap.builder().put(ChatColor.AQUA, DyeColor.LIGHT_BLUE).put(ChatColor.BLACK, DyeColor.BLACK).put(ChatColor.BLUE, DyeColor.LIGHT_BLUE).put(ChatColor.DARK_AQUA, DyeColor.CYAN).put(ChatColor.DARK_BLUE, DyeColor.BLUE).put(ChatColor.DARK_GRAY, DyeColor.GRAY).put(ChatColor.DARK_GREEN, DyeColor.GREEN).put(ChatColor.DARK_PURPLE, DyeColor.PURPLE).put(ChatColor.DARK_RED, DyeColor.RED).put(ChatColor.GOLD, DyeColor.ORANGE).put(ChatColor.GRAY, DyeColor.SILVER).put(ChatColor.GREEN, DyeColor.LIME).put(ChatColor.LIGHT_PURPLE, DyeColor.MAGENTA).put(ChatColor.RED, DyeColor.RED).put(ChatColor.WHITE, DyeColor.WHITE).put(ChatColor.YELLOW, DyeColor.YELLOW).build();;
+ private static final ImmutableSet DEBUFF_TYPES = ImmutableSet.builder().add(PotionEffectType.BLINDNESS).add(PotionEffectType.CONFUSION).add(PotionEffectType.HARM).add(PotionEffectType.HUNGER).add(PotionEffectType.POISON).add(PotionEffectType.SATURATION).add(PotionEffectType.SLOW).add(PotionEffectType.SLOW_DIGGING).add(PotionEffectType.WEAKNESS).add(PotionEffectType.WITHER).build();;
+
+ public static final String STRAIGHT_LINE_TEMPLATE = ChatColor.STRIKETHROUGH + Strings.repeat("-", 256);
+
+ public static List getCompletions(String[] arguments, List input) {
+ return getCompletions(arguments, input, 80);
+ }
+
+ public static List getCompletions(String[] arguments, List input, int limit) {
+ Preconditions.checkNotNull(arguments);
+ Preconditions.checkArgument(arguments.length != 0);
+ String argument = arguments[arguments.length - 1];
+ return input.stream().filter(string -> string.regionMatches(true, 0, argument, 0, argument.length())).limit(limit).collect(Collectors.toList());
+ }
+
+ public static String getDisplayName(CommandSender sender) {
+ Preconditions.checkNotNull(sender, "Sender cannot be null");
+ return (sender instanceof Player) ? ((Player) sender).getDisplayName() : sender.getName();
+ }
+
+ public static DyeColor toDyeColor(ChatColor colour) {
+ return CHAT_DYE_COLOUR_MAP.get(colour);
+ }
+
+ public static Player getFinalAttacker(EntityDamageEvent ede, boolean ignoreSelf) {
+ Player attacker = null;
+ if (ede instanceof EntityDamageByEntityEvent) {
+ EntityDamageByEntityEvent event = (EntityDamageByEntityEvent) ede;
+ Entity damager = event.getDamager();
+ if (event.getDamager() instanceof Player) {
+ attacker = (Player) damager;
+ } else if (event.getDamager() instanceof Projectile) {
+ Projectile projectile = (Projectile) damager;
+ ProjectileSource shooter = projectile.getShooter();
+ if (shooter instanceof Player) {
+ attacker = (Player) shooter;
+ }
+ }
+ if (attacker != null && ignoreSelf && event.getEntity().equals(attacker)) {
+ attacker = null;
+ }
+ }
+ return attacker;
+ }
+
+ public static Player getPlayer(String string) {
+ if (string == null) {
+ return null;
+ }
+ return JavaUtils.isUUID(string) ? Bukkit.getPlayer(UUID.fromString(string)) : Bukkit.getPlayer(string);
+ }
+
+ @Deprecated
+ public static OfflinePlayer getOfflinePlayer(String string) {
+ if (string == null) {
+ return null;
+ }
+ return JavaUtils.isUUID(string) ? Bukkit.getOfflinePlayer(UUID.fromString(string)) : Bukkit.getOfflinePlayer(string);
+ }
+
+ public static boolean isWithinX(Location location, Location other, double distance) {
+ return location.getWorld().equals(other.getWorld()) && Math.abs(other.getX() - location.getX()) <= distance && Math.abs(other.getZ() - location.getZ()) <= distance;
+ }
+
+ public static Location getHighestLocation(Location origin) {
+ return getHighestLocation(origin, null);
+ }
+
+ public static Location getHighestLocation(Location origin, Location def) {
+ Location cloned = Preconditions.checkNotNull(origin, "The location cannot be null").clone();
+ World world = cloned.getWorld();
+ int x = cloned.getBlockX();
+ int y = world.getMaxHeight();
+ int z = cloned.getBlockZ();
+ while (y > origin.getBlockY()) {
+ Block block = world.getBlockAt(x, --y, z);
+ if (!block.isEmpty()) {
+ Location next = block.getLocation();
+ next.setPitch(origin.getPitch());
+ next.setYaw(origin.getYaw());
+ return next;
+ }
+ }
+ return def;
+ }
+
+ public static boolean isDebuff(PotionEffectType type) {
+ return DEBUFF_TYPES.contains(type);
+ }
+
+ public static boolean isDebuff(PotionEffect effect) {
+ return isDebuff(effect.getType());
+ }
+
+ public static boolean isDebuff(ThrownPotion potion) {
+ for (PotionEffect effect : potion.getEffects()) {
+ if (isDebuff(effect)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static String niceTime(int seconds) {
+ int hours = seconds / 3600;
+ seconds -= hours * 3600;
+ int minutes = seconds / 60;
+ seconds -= minutes * 60;
+ return niceTime(hours, minutes, seconds);
+ }
+
+ public static String niceTime(int seconds, boolean showEmptyHours) {
+ int hours = seconds / 3600;
+ seconds -= hours * 3600;
+ int minutes = seconds / 60;
+ seconds -= minutes * 60;
+ return niceTime(hours, minutes, seconds, showEmptyHours);
+ }
+
+ public static String niceTime(int hours, int minutes, int seconds) {
+ return niceTime(hours, minutes, seconds, true);
+ }
+
+ public static String niceTime(int hours, int minutes, int seconds, boolean showEmptyHours) {
+ StringBuilder builder = new StringBuilder();
+
+ // Skip hours
+ if (hours > 0) {
+ if (hours < 10) {
+ builder.append('0');
+ }
+ builder.append(hours);
+ builder.append(':');
+ } else if (showEmptyHours) {
+ builder.append("00:");
+ }
+
+ if (minutes < 10 && hours != -1) {
+ builder.append('0');
+ }
+ builder.append(minutes);
+ builder.append(':');
+
+ if (seconds < 10) {
+ builder.append('0');
+ }
+ builder.append(seconds);
+
+ return builder.toString();
+ }
+
+ public static void registerEntity(String name, int id, Class extends EntityInsentient> nmsClass, Class extends EntityInsentient> customClass){
+ try {
+
+ List