diff --git a/pom.xml b/pom.xml index 8f070f0..321c29c 100644 --- a/pom.xml +++ b/pom.xml @@ -14,8 +14,8 @@ com.destroystokyo.paper - paper - 1.14.1-R0.1-SNAPSHOT + paper-api + 1.14.2-R0.1-SNAPSHOT com.alttd diff --git a/src/main/java/com/alttd/altitudetag/AltitudeTag.java b/src/main/java/com/alttd/altitudetag/AltitudeTag.java index 3f939d5..23b9704 100644 --- a/src/main/java/com/alttd/altitudetag/AltitudeTag.java +++ b/src/main/java/com/alttd/altitudetag/AltitudeTag.java @@ -3,7 +3,15 @@ package com.alttd.altitudetag; import java.util.UUID; import java.util.function.Consumer; +import com.alttd.altitudeapi.commands.CommandHandler; +import com.alttd.altitudeapi.commands.CommandLang; +import com.alttd.altitudetag.commands.TagCommand; +import com.alttd.altitudetag.configuration.Config; +import com.alttd.altitudetag.configuration.Lang; +import com.alttd.altitudetag.listeners.ConnectionListener; +import com.alttd.altitudetag.listeners.InteractListener; import org.bukkit.Bukkit; +import org.bukkit.boss.BossBar; import org.bukkit.plugin.java.JavaPlugin; public class AltitudeTag extends JavaPlugin @@ -12,6 +20,8 @@ public class AltitudeTag extends JavaPlugin private UUID tagger; + private BossBar bossBar; + /** * Enable the plugin */ @@ -27,12 +37,34 @@ public class AltitudeTag extends JavaPlugin return; } - Bukkit.getScheduler().runTaskTimerAsynchronously(this, this::updateLeaderboard, 20, 10); + Lang.update(); + + // update the CommandLang values + CommandLang.NO_PERMISSION.setValue(Lang.NO_PERMS.getRawMessage()[0]); + CommandLang.HEADER_FOOTER.setValue(Lang.HEADER_FOOTER.getRawMessage()[0]); + CommandLang.NO_SUBS.setValue(Lang.NO_SUBS.getRawMessage()[0]); + CommandLang.ONLY_PLAYERS.setValue(Lang.ONLY_PLAYERS.getRawMessage()[0]); + CommandLang.USAGE_FORMAT.setValue(Lang.USAGE.getRawMessage()[0]); + + Config.update(); + TagConnection.initialize(); + Leaderboard.initialize(); + + CommandHandler.initialize(); + CommandHandler.getInstance().registerCommand(new TagCommand(), this); + + Bukkit.getPluginManager().registerEvents(new ConnectionListener(), this); + Bukkit.getPluginManager().registerEvents(new InteractListener(), this); } - private void updateLeaderboard() + public static BossBar getBossBar() { + return instance.bossBar; + } + public static void setBossBar(BossBar bossBar) + { + instance.bossBar = bossBar; } /** diff --git a/src/main/java/com/alttd/altitudetag/Leaderboard.java b/src/main/java/com/alttd/altitudetag/Leaderboard.java index 3d97e7a..5e60a4e 100644 --- a/src/main/java/com/alttd/altitudetag/Leaderboard.java +++ b/src/main/java/com/alttd/altitudetag/Leaderboard.java @@ -4,22 +4,33 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import java.util.Objects; import java.util.UUID; import java.util.function.Consumer; +import com.alttd.altitudetag.configuration.Config; +import com.alttd.altitudetag.configuration.Lang; +import com.gmail.filoghost.holographicdisplays.api.Hologram; +import com.gmail.filoghost.holographicdisplays.api.HologramsAPI; +import com.gmail.filoghost.holographicdisplays.api.line.TextLine; import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.configuration.file.FileConfiguration; public class Leaderboard { + private static Hologram hologram; + public static void initialize() { //language=SQL - String sql = "CREATE TABLE IF NOT EXISTS Players (" - + " PlayerId INT NOT NULL AUTO_INCREMENT," - + " PlayerUuidMost BIGINT NOT NULL," - + " PlayerUuidLeast BIGINT NOT NULL," - + " PlayerTags INT NOT NULL DEFAULT(1)," - + " PRIMARY KEY (PlayerId)" + + String sql = "CREATE TABLE IF NOT EXISTS Player (" + + " player_id INT NOT NULL AUTO_INCREMENT," + + " player_uuid VARCHAR(36) NOT NULL," + + " player_tags INT NOT NULL DEFAULT 0," + + " player_active BIT NOT NULL DEFAULT 1," + + " PRIMARY KEY (player_id)," + + " CONSTRAINT uuid_unique UNIQUE (player_uuid)" + ");"; try @@ -31,6 +42,8 @@ public class Leaderboard { ex.printStackTrace(); } + + initializeLeaderboard(); } /** @@ -45,25 +58,19 @@ public class Leaderboard { String sql; // if they've tagged before we want to update rather than insert - if (hasTagged(uuid)) - { - sql = "UPDATE Players SET PlayerTags = PlayerTags + 1 WHERE PlayerUuidMost = ? AND PlayerUuidLeast = ?;"; - } - else - { - sql = "INSERT INTO Players (PlayerUuidMost, PlayerUuidLeast) VALUES (?, ?);"; + sql = "INSERT INTO Player (player_uuid, player_tags) VALUES (?, 1) ON DUPLICATE KEY UPDATE player_tags = player_tags + 1"; - } // prepare the statement try (PreparedStatement ps = TagConnection.getConnection().prepareStatement(sql)) { // set the parameters - ps.setLong(1, uuid.getMostSignificantBits()); - ps.setLong(2, uuid.getLeastSignificantBits()); + ps.setString(1, uuid.toString()); // execute the code ps.execute(); + refreshLeaderboard(); + // run the runnable if it's not null if (runnable != null) { @@ -86,12 +93,11 @@ public class Leaderboard { Bukkit.getScheduler().runTaskAsynchronously(AltitudeTag.getInstance(), () -> { - String sql = "SELECT PlayerTags FROM Players WHERE PlayerUuidMost = ? AND PlayerUuidLeast = ?;"; + String sql = "SELECT player_tags FROM Player WHERE player_uuid = ?;"; try (PreparedStatement ps = TagConnection.getConnection().prepareStatement(sql)) { - ps.setLong(1, uuid.getMostSignificantBits()); - ps.setLong(2, uuid.getLeastSignificantBits()); + ps.setString(1, uuid.toString()); ResultSet rs = ps.getResultSet(); @@ -109,24 +115,84 @@ public class Leaderboard }); } - public static boolean hasTagged(UUID uuid) + /** + * Sets the location of the leaderboard. Changes will also be saved to the config file. + * + * @param location the new location for the leaderboard. + */ + public static void setLocation(Location location) { - String sql = "SELECT COUNT(*) FROM Players WHERE PlayerUuidMost = ? AND PlayerUuidLeast = ?;"; + Config.LEADERBOARD_LOCATION_WORLD.setValue(location.getWorld().getName()); + Config.LEADERBOARD_LOCATION_X.setValue(location.getX()); + Config.LEADERBOARD_LOCATION_Y.setValue(location.getY()); + Config.LEADERBOARD_LOCATION_Z.setValue(location.getZ()); - try (PreparedStatement ps = TagConnection.getConnection().prepareStatement(sql)) + FileConfiguration config = AltitudeTag.getInstance().getConfig(); + config.set("leaderboard.location.world", Config.LEADERBOARD_LOCATION_WORLD.getValue()); + config.set("leaderboard.location.x", Config.LEADERBOARD_LOCATION_X.getValue()); + config.set("leaderboard.location.y", Config.LEADERBOARD_LOCATION_Y.getValue()); + config.set("leaderboard.location.z", Config.LEADERBOARD_LOCATION_Z.getValue()); + AltitudeTag.getInstance().saveConfig(); + + hologram.delete(); + initializeLeaderboard(); + } + + private static void initializeLeaderboard() + { + if (Config.LEADERBOARD_ENABLED.getValue()) { - ps.setLong(1, uuid.getMostSignificantBits()); - ps.setLong(2, uuid.getLeastSignificantBits()); + hologram = HologramsAPI.createHologram(AltitudeTag.getInstance(), + new Location(Bukkit.getWorld(Config.LEADERBOARD_LOCATION_WORLD.getValue()), + Config.LEADERBOARD_LOCATION_X.getValue(), + Config.LEADERBOARD_LOCATION_Y.getValue(), + Config.LEADERBOARD_LOCATION_Z.getValue())); + hologram.appendTextLine(Config.LEADERBOARD_TITLE.getValue()); - ResultSet rs = ps.getResultSet(); + for (int i = 0; i < Config.LEADERBOARD_TOP.getValue(); i++) + { + hologram.appendTextLine(""); + } - return rs.next() && rs.getInt(1) > 0; + refreshLeaderboard(); } - catch (SQLException ex) + } + + private static void refreshLeaderboard() + { + if (Config.LEADERBOARD_ENABLED.getValue()) { - ex.printStackTrace(); - } + Objects.requireNonNull(hologram); - return false; + Bukkit.getScheduler().runTaskAsynchronously(AltitudeTag.getInstance(), () -> + { + String sql = "SELECT player_uuid, player_tags FROM Player LIMIT ?"; + try (PreparedStatement ps = TagConnection.getConnection().prepareStatement(sql)) + { + ps.setInt(1, Config.LEADERBOARD_TOP.getValue()); + ResultSet rs = ps.getResultSet(); + for (int i = 0; i < Config.LEADERBOARD_TOP.getValue(); i++) + { + String text; + if (rs.next()) + { + text = Lang.renderString(Config.LEADERBOARD_FORMAT.getValue(), + "{rank}", i, + "{player}", Bukkit.getOfflinePlayer(UUID.fromString(rs.getString("player_uuid"))), + "{tags}", rs.getInt("player_tags")); + } + else + { + text = ""; + } + ((TextLine) hologram.getLine(i)).setText(text); + } + } + catch (SQLException ex) + { + ex.printStackTrace(); + } + }); + } } } diff --git a/src/main/java/com/alttd/altitudetag/NotificationHandler.java b/src/main/java/com/alttd/altitudetag/NotificationHandler.java new file mode 100644 index 0000000..888a967 --- /dev/null +++ b/src/main/java/com/alttd/altitudetag/NotificationHandler.java @@ -0,0 +1,95 @@ +package com.alttd.altitudetag; + +import com.alttd.altitudetag.configuration.Config; +import com.alttd.altitudetag.configuration.Lang; +import com.alttd.altitudetag.utils.BarUtils; +import com.destroystokyo.paper.Title; +import org.bukkit.Bukkit; +import org.bukkit.boss.BossBar; +import org.bukkit.entity.Player; + +public class NotificationHandler +{ + // TODO move all notifications here + public static void sendVictimTitle(final Player player, boolean connection) + { + if (Config.NOTIFICATION_VICTIM_TITLE_ENABLED.getValue()) + { + Runnable sendTitle = () -> + { + if (player.isOnline()) + { + Title.Builder builder = Title.builder() + .fadeIn(Config.NOTIFICATION_VICTIM_TITLE_FADE_IN.getValue()) + .fadeOut(Config.NOTIFICATION_VICTIM_TITLE_FADE_OUT.getValue()) + .stay(Config.NOTIFICATION_VICTIM_TITLE_DURATION.getValue()) + .title(Config.NOTIFICATION_VICTIM_TITLE_MESSAGE.getValue()); + + if (Config.NOTIFICATION_VICTIM_TITLE_SUB_TITLE_ENABLED.getValue()) + { + builder.subtitle(Config.NOTIFICATION_VICTIM_TITLE_SUB_TITLE_MESSAGE.getValue()); + } + + player.sendTitle(builder.build()); + } + }; + if (connection && Config.NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_ENABLED.getValue()) + { + Bukkit.getScheduler().runTaskLater(AltitudeTag.getInstance(), sendTitle, Config.NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_LENGTH.getValue()); + } + else + { + sendTitle.run(); + } + } + } + + public static void sendTaggerNotifications(Player tagger, String tagged) + { + // get their tags... + AltitudeTag.getTags(tagger.getUniqueId(), (tags) -> + { + // if they left, we can stop + if (!tagger.isOnline()) + { + return; + } + + if (Config.NOTIFICATION_ATTACKER_CHAT_ENABLED.getValue()) + { + tagger.sendMessage(Lang.renderString(Config.NOTIFICATION_ATTACKER_CHAT_MESSAGE.getValue(), + "{target}", tagged, + "{amount}", tags)); + } + }); + } + + public static void sendGlobalNotifications(String attacker, String victim) + { + if (attacker == null && Config.NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_ENABLED.getValue()) + { + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(Lang.renderString(Config.NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_MESSAGE.getValue(), + "{victim}", victim))); + } + if (attacker != null && Config.NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_ENABLED.getValue()) + { + Bukkit.getOnlinePlayers().forEach(p -> p.sendMessage(Lang.renderString(Config.NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_MESSAGE.getValue(), + "{victim}", victim, + "{attacker}", attacker))); + } + } + + public static void sendBossBar() + { + if (Config.NOTIFICATION_GLOBAL_BOSS_BAR_ENABLED.getValue()) + { + BossBar bossBar = Bukkit.createBossBar(Lang.renderString(Config.NOTIFICATION_GLOBAL_BOSS_BAR_MESSAGE.getValue(), "{player}", "No One"), + BarUtils.parseBarColor(Config.NOTIFICATION_GLOBAL_BOSS_BAR_COLOR.getValue()), + BarUtils.parseBarStyle(Config.NOTIFICATION_GLOBAL_BOSS_BAR_SEGMENTS.getValue())); + + bossBar.setProgress(Config.NOTIFICATION_GLOBAL_BOSS_BAR_PERCENT.getValue() / 100.0); + + AltitudeTag.setBossBar(bossBar); + } + } +} diff --git a/src/main/java/com/alttd/altitudetag/Permission.java b/src/main/java/com/alttd/altitudetag/Permission.java index 64eb2e6..84ceb4b 100644 --- a/src/main/java/com/alttd/altitudetag/Permission.java +++ b/src/main/java/com/alttd/altitudetag/Permission.java @@ -2,8 +2,8 @@ package com.alttd.altitudetag; public enum Permission { - PRIORITY_QUEUE("altiqueue.priority-queue"), - SKIP_QUEUE("altiqueue.skip-queue"), + COMMAND_ADMIN("tag.commands.admin"), + COMMAND_ADMIN_LOCATION("tag.commands.admin.location"), QUEUE_COMMAND("altiqueue.queue-command"); private String permission; diff --git a/src/main/java/com/alttd/altitudetag/TagConnection.java b/src/main/java/com/alttd/altitudetag/TagConnection.java index 5c4fa64..597904a 100644 --- a/src/main/java/com/alttd/altitudetag/TagConnection.java +++ b/src/main/java/com/alttd/altitudetag/TagConnection.java @@ -17,6 +17,7 @@ public class TagConnection private String username; private String password; private int port; + private String description; private TagConnection() { @@ -25,6 +26,7 @@ public class TagConnection this.username = Config.DATABASE_USERNAME.getValue(); this.password = Config.DATABASE_PASSWORD.getValue(); this.port = Config.DATABASE_PORT.getValue(); + this.description = Config.DATABASE_DESCRIPTION.getValue(); try { diff --git a/src/main/java/com/alttd/altitudetag/commands/TagAdminCommand.java b/src/main/java/com/alttd/altitudetag/commands/TagAdminCommand.java new file mode 100644 index 0000000..1ac1aa3 --- /dev/null +++ b/src/main/java/com/alttd/altitudetag/commands/TagAdminCommand.java @@ -0,0 +1,15 @@ +package com.alttd.altitudetag.commands; + +import com.alttd.altitudeapi.commands.ValidBaseCommand; +import com.alttd.altitudetag.Permission; +import com.alttd.altitudetag.commands.admin.TagAdminLocationCommand; + +public class TagAdminCommand extends ValidBaseCommand +{ + protected TagAdminCommand() + { + super("admin", "Management commands", Permission.COMMAND_ADMIN.getPermission(), new String[]{ "a" }); + + addSubCommand(new TagAdminLocationCommand()); + } +} diff --git a/src/main/java/com/alttd/altitudetag/commands/TagCommand.java b/src/main/java/com/alttd/altitudetag/commands/TagCommand.java new file mode 100644 index 0000000..2d1c1a6 --- /dev/null +++ b/src/main/java/com/alttd/altitudetag/commands/TagCommand.java @@ -0,0 +1,32 @@ +package com.alttd.altitudetag.commands; + +import com.alttd.altitudeapi.commands.ValidBaseCommand; +import com.alttd.altitudetag.AltitudeTag; +import com.alttd.altitudetag.configuration.Config; +import com.alttd.altitudetag.configuration.Lang; +import org.bukkit.Bukkit; +import org.bukkit.command.CommandSender; + +public class TagCommand extends ValidBaseCommand +{ + public TagCommand() + { + super("tag", "Tag, you're it!", new String[]{ "tags", "tagging", "tagger" }); + + addSubCommand(new TagAdminCommand()); + } + + @Override + public void help(CommandSender sender, String[] label) + { + if (sender.hasPermission(getSubCommand("admin").getPermission())) + { + sender.sendMessage(Lang.renderString(Config.NOTIFICATION_GLOBAL_BOSS_BAR_MESSAGE.getValue(), + "{player}", Bukkit.getOfflinePlayer(AltitudeTag.getTagger()).getName())); + } + else + { + super.help(sender, label); + } + } +} diff --git a/src/main/java/com/alttd/altitudetag/commands/admin/TagAdminLocationCommand.java b/src/main/java/com/alttd/altitudetag/commands/admin/TagAdminLocationCommand.java new file mode 100644 index 0000000..a37bd6c --- /dev/null +++ b/src/main/java/com/alttd/altitudetag/commands/admin/TagAdminLocationCommand.java @@ -0,0 +1,33 @@ +package com.alttd.altitudetag.commands.admin; + +import java.util.List; + +import com.alttd.altitudeapi.commands.CommandArgument; +import com.alttd.altitudeapi.commands.ValidCommand; +import com.alttd.altitudetag.Leaderboard; +import com.alttd.altitudetag.Permission; +import com.alttd.altitudetag.configuration.Lang; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public class TagAdminLocationCommand extends ValidCommand +{ + public TagAdminLocationCommand() + { + super("location", + "Sets the leaderboard location", + Permission.COMMAND_ADMIN_LOCATION.getPermission(), + true, + new String[]{ "loc", "setloc", "setlocation", "leaderboard", "board" }); + } + + @Override + public void validRun(CommandSender commandSender, String[] strings, List> list) + { + Player player = (Player) commandSender; + + Leaderboard.setLocation(player.getLocation()); + + Lang.SET_LEADERBOARD_LOCATION.send(player); + } +} diff --git a/src/main/java/com/alttd/altitudetag/configuration/Config.java b/src/main/java/com/alttd/altitudetag/configuration/Config.java index ccd06c7..9f7c5d9 100644 --- a/src/main/java/com/alttd/altitudetag/configuration/Config.java +++ b/src/main/java/com/alttd/altitudetag/configuration/Config.java @@ -4,6 +4,7 @@ import java.util.Objects; import com.alttd.altitudeapi.utils.MutableValue; import com.alttd.altitudetag.AltitudeTag; +import org.bukkit.ChatColor; import org.bukkit.configuration.file.FileConfiguration; public final class Config @@ -46,7 +47,45 @@ public final class Config /** * The description given to a connection if the DBMS supports that feature. */ - public static final MutableValue DATABASE_CONNECTION_DESCRIPTION = new MutableValue<>("Altitude Connection"); + public static final MutableValue DATABASE_DESCRIPTION = new MutableValue<>("Altitude Connection"); + + public static final MutableValue LEADERBOARD_ENABLED = new MutableValue<>(true); + public static final MutableValue LEADERBOARD_TITLE = new MutableValue<>("&b&lAltitude Tag Leaderboard"); + public static final MutableValue LEADERBOARD_FORMAT = new MutableValue<>("&6{rank}. &e{player} &7- &e{tags}"); + public static final MutableValue LEADERBOARD_TOP = new MutableValue<>(10); + + public static final MutableValue LEADERBOARD_LOCATION_WORLD = new MutableValue<>("world"); + public static final MutableValue LEADERBOARD_LOCATION_X = new MutableValue<>(10.0); + public static final MutableValue LEADERBOARD_LOCATION_Y = new MutableValue<>(50.0); + public static final MutableValue LEADERBOARD_LOCATION_Z = new MutableValue<>(10.0); + + public static final MutableValue NOTIFICATION_VICTIM_TITLE_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_MESSAGE = new MutableValue<>("&6Tag"); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_DURATION = new MutableValue<>(100); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_FADE_IN = new MutableValue<>(0); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_FADE_OUT = new MutableValue<>(0); + + public static final MutableValue NOTIFICATION_VICTIM_TITLE_SUB_TITLE_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_SUB_TITLE_MESSAGE = new MutableValue<>("&eYou're it!"); + + public static final MutableValue NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_LENGTH = new MutableValue<>(60); + + public static final MutableValue NOTIFICATION_ATTACKER_CHAT_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_ATTACKER_CHAT_MESSAGE = new MutableValue<>("&7You just tagged &e{target}&7! You have &e{amount}&7 total tags."); + + public static final MutableValue NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_MESSAGE = new MutableValue<>("&e* {attacker} tagged {target}, run!"); + + public static final MutableValue NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_MESSAGE = new MutableValue<>("&e*{target} is it now, run!"); + + public static final MutableValue NOTIFICATION_GLOBAL_BOSS_BAR_ENABLED = new MutableValue<>(true); + public static final MutableValue NOTIFICATION_GLOBAL_BOSS_BAR_SEGMENTS = new MutableValue<>(0); + public static final MutableValue NOTIFICATION_GLOBAL_BOSS_BAR_COLOR = new MutableValue<>("YELLOW"); + public static final MutableValue NOTIFICATION_GLOBAL_BOSS_BAR_PERCENT = new MutableValue<>(0); + public static final MutableValue NOTIFICATION_GLOBAL_BOSS_BAR_MESSAGE = new MutableValue<>("&e{player} is 'it'! Don't let them tag you!"); + /** * Update the values from the config file. @@ -67,10 +106,39 @@ public final class Config updateValue(config, save, "database.password", DATABASE_PASSWORD); updateValue(config, save, "database.database", DATABASE_DATABASE); updateValue(config, save, "database.timeout", DATABASE_TIMEOUT); - updateValue(config, save, "database.description", DATABASE_CONNECTION_DESCRIPTION); + updateValue(config, save, "database.description", DATABASE_DESCRIPTION); - // Notification information + // leaderboard values + updateValue(config, save, "leaderboard.enabled", LEADERBOARD_ENABLED); + updateValue(config, save, "leaderboard.title", LEADERBOARD_TITLE); + updateValue(config, save, "leaderboard.format", LEADERBOARD_FORMAT); + updateValue(config, save, "leaderboard.top", LEADERBOARD_TOP); + updateValue(config, save, "leaderboard.location.world", LEADERBOARD_LOCATION_WORLD); + updateValue(config, save, "leaderboard.location.x", LEADERBOARD_LOCATION_X); + updateValue(config, save, "leaderboard.location.y", LEADERBOARD_LOCATION_Y); + updateValue(config, save, "leaderboard.location.z", LEADERBOARD_LOCATION_Z); + // notification values + updateValue(config, save, "notification.victim.title.enabled", NOTIFICATION_VICTIM_TITLE_ENABLED); + updateValue(config, save, "notification.victim.title.message", NOTIFICATION_VICTIM_TITLE_MESSAGE); + updateValue(config, save, "notification.victim.title.duration", NOTIFICATION_VICTIM_TITLE_DURATION); + updateValue(config, save, "notification.victim.title.fade-in", NOTIFICATION_VICTIM_TITLE_FADE_IN); + updateValue(config, save, "notification.victim.title.fade-out", NOTIFICATION_VICTIM_TITLE_FADE_OUT); + updateValue(config, save, "notification.victim.title.sub-title.enabled", NOTIFICATION_VICTIM_TITLE_SUB_TITLE_ENABLED); + updateValue(config, save, "notification.victim.title.sub-title.message", NOTIFICATION_VICTIM_TITLE_SUB_TITLE_MESSAGE); + updateValue(config, save, "notification.victim.title.join-delay.enabled", NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_ENABLED); + updateValue(config, save, "notification.victim.title.join-delay.length", NOTIFICATION_VICTIM_TITLE_JOIN_DELAY_LENGTH); + updateValue(config, save, "notification.attacker.chat.enabled", NOTIFICATION_ATTACKER_CHAT_ENABLED); + updateValue(config, save, "notification.attacker.chat.message", NOTIFICATION_ATTACKER_CHAT_MESSAGE); + updateValue(config, save, "notification.global.chat.after-tag.enabled", NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_ENABLED); + updateValue(config, save, "notification.global.chat.after-tag.message", NOTIFICATION_GLOBAL_CHAT_AFTER_TAG_MESSAGE); + updateValue(config, save, "notification.global.chat.other-reason.enabled", NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_ENABLED); + updateValue(config, save, "notification.global.chat.other-reason.message", NOTIFICATION_GLOBAL_CHAT_OTHER_REASON_MESSAGE); + updateValue(config, save, "notification.global.boss-bar.enabled", NOTIFICATION_GLOBAL_BOSS_BAR_ENABLED); + updateValue(config, save, "notification.global.boss-bar.segments", NOTIFICATION_GLOBAL_BOSS_BAR_SEGMENTS); + updateValue(config, save, "notification.global.boss-bar.color", NOTIFICATION_GLOBAL_BOSS_BAR_COLOR); + updateValue(config, save, "notification.global.boss-bar.percent", NOTIFICATION_GLOBAL_BOSS_BAR_PERCENT); + updateValue(config, save, "notification.global.boss-bar.message", NOTIFICATION_GLOBAL_BOSS_BAR_MESSAGE); if (save.getValue()) { @@ -149,7 +217,7 @@ public final class Config } else if (clazz == String.class) { - return (T) config.getString(location); + return (T) ChatColor.translateAlternateColorCodes('&', config.getString(location)); } else if (clazz == Boolean.class) { diff --git a/src/main/java/com/alttd/altitudetag/configuration/Lang.java b/src/main/java/com/alttd/altitudetag/configuration/Lang.java index ce0385e..f24bb78 100644 --- a/src/main/java/com/alttd/altitudetag/configuration/Lang.java +++ b/src/main/java/com/alttd/altitudetag/configuration/Lang.java @@ -26,14 +26,6 @@ public enum Lang * When a player misuses a command. */ USAGE("usage_message", "&6&lUSAGE &e» &f{usage}"), - /** - * The prefix to an error message. - */ - ERROR("error_message", "&4&lERROR &c» &7{message}"), - /** - * The prefix to a success message. - */ - SUCCESS("success_message", "&2&lSUCCESS &a» &f{message}"), /** * When players do not have permission to do something. */ @@ -54,18 +46,7 @@ public enum Lang * When the console tries to run a player-only command. */ ONLY_PLAYERS("only_players", "Only players can run that command."), - /** - * Sent to someone when they become it - */ - YOURE_IT("youre-it", "You're it! Try to tag someone!"), - /** - * When you tag someone - */ - TAGGED("tagged", "&7Nice tag! You're not it anymore. You're up to &b{tags}&7 tags!"), - /** - * Broadcast to the server when a new person becomes it. - */ - NEW_TAGGER("new_tagger", "Uh oh, {player} is it! Run!!"); + SET_LEADERBOARD_LOCATION("set_leaderboard_location", "Successfully set the leaderboard location."); private String[] message; @@ -130,48 +111,6 @@ public enum Lang sender.sendMessage(getMessage(parameters)); } - /** - * Sends this Lang object but prepended with the ERROR value as well. - * - * @param sender the CommandSender receiving the message. - * @param parameters all additional arguments to fill placeholders. - */ - public void sendError(CommandSender sender, Object... parameters) - { - for (String line : getMessage(parameters)) - { - ERROR.send(sender, "{message}", line); - } - } - - /** - * Sends this Lang object but prepended with the SUCCESS value as well. - * - * @param sender the CommandSender receiving the message. - * @param parameters all additional arguments to fill placeholders. - */ - public void sendSuccess(CommandSender sender, Object... parameters) - { - for (String line : getMessage(parameters)) - { - SUCCESS.send(sender, "{message}", line); - } - } - - /** - * Sends this Lang object but prepended with the PREFIX value as well. - * - * @param sender the CommandSender receiving the message. - * @param parameters all additional arguments to fill placeholders. - */ - public void sendInfo(CommandSender sender, Object... parameters) - { - for (String line : getMessage(parameters)) - { - PREFIX.send(sender, "{message}", line); - } - } - /** * Renders this message and returns it. Similar behavior to {@link #send(CommandSender, Object...)}, but instead of sending the message, it simply returns it. * @@ -197,7 +136,7 @@ public enum Lang * * @return the rendered string. */ - protected String renderString(String string, Object... args) + public static String renderString(String string, Object... args) { if (args.length % 2 != 0) { @@ -242,14 +181,4 @@ public enum Lang { AltitudeTag.getInstance().getLogger().severe("Error loading the lang value '" + location + "'. Reverted it to default."); } - - public static void sendUsageMessage(CommandSender sender, String[] label, String[] parameters) - { - StringBuilder args = new StringBuilder("/" + StringUtils.compile(label)); - for (String str : parameters) - { - args.append(" [").append(str).append("]"); - } - USAGE.send(sender, "{usage}", args.toString()); - } } diff --git a/src/main/java/com/alttd/altitudetag/listeners/ConnectionListener.java b/src/main/java/com/alttd/altitudetag/listeners/ConnectionListener.java index a401aac..7668432 100644 --- a/src/main/java/com/alttd/altitudetag/listeners/ConnectionListener.java +++ b/src/main/java/com/alttd/altitudetag/listeners/ConnectionListener.java @@ -4,7 +4,7 @@ import java.util.Optional; import java.util.UUID; import com.alttd.altitudetag.AltitudeTag; -import com.alttd.altitudetag.configuration.Lang; +import com.alttd.altitudetag.NotificationHandler; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; @@ -20,7 +20,8 @@ public class ConnectionListener implements Listener if (AltitudeTag.getTagger() == null) { AltitudeTag.setTagger(event.getPlayer().getUniqueId()); - Lang.YOURE_IT.send(event.getPlayer()); + + NotificationHandler.sendVictimTitle(event.getPlayer(), true); } } @@ -42,7 +43,7 @@ public class ConnectionListener implements Listener } UUID uuid = optional.get().getUniqueId(); AltitudeTag.setTagger(uuid); - Lang.YOURE_IT.send(event.getPlayer()); + NotificationHandler.sendVictimTitle(optional.get(), false); } } } diff --git a/src/main/java/com/alttd/altitudetag/listeners/InteractListener.java b/src/main/java/com/alttd/altitudetag/listeners/InteractListener.java index 4d9966c..3245a6e 100644 --- a/src/main/java/com/alttd/altitudetag/listeners/InteractListener.java +++ b/src/main/java/com/alttd/altitudetag/listeners/InteractListener.java @@ -1,7 +1,7 @@ package com.alttd.altitudetag.listeners; import com.alttd.altitudetag.AltitudeTag; -import com.alttd.altitudetag.configuration.Lang; +import com.alttd.altitudetag.NotificationHandler; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -14,31 +14,25 @@ public class InteractListener implements Listener { if (event.getDamager() instanceof Player && event.getEntity() instanceof Player) { - Player tagger = (Player) event.getDamager(); - Player tagged = (Player) event.getEntity(); + final Player tagger = (Player) event.getDamager(); + final Player tagged = (Player) event.getEntity(); // add the new tag AltitudeTag.addTag(tagger.getUniqueId(), () -> { - // if they're still online... - if (tagger.isOnline()) + // if they left, we can stop + if (!tagger.isOnline()) { - // get their tags... - AltitudeTag.getTags(tagger.getUniqueId(), (tags) -> - { - // if they're still online... - if (tagger.isOnline()) - { - // let em know how they're doing! - Lang.TAGGED.send(tagger, "{tags}", tags); - } - }); + return; } + NotificationHandler.sendTaggerNotifications(tagger, tagged.getName()); }); AltitudeTag.setTagger(tagged.getUniqueId()); - Lang.YOURE_IT.send(tagged); + NotificationHandler.sendVictimTitle(tagged, false); + + NotificationHandler.sendGlobalNotifications(tagger.getName(), tagged.getName()); } } } diff --git a/src/main/java/com/alttd/altitudetag/utils/BarUtils.java b/src/main/java/com/alttd/altitudetag/utils/BarUtils.java new file mode 100644 index 0000000..8b5c351 --- /dev/null +++ b/src/main/java/com/alttd/altitudetag/utils/BarUtils.java @@ -0,0 +1,53 @@ +package com.alttd.altitudetag.utils; + +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; + +public class BarUtils +{ + + /** + * Parses the String and returns a {@link BarStyle}. If a style could not be parsed, this returns + * {@link BarStyle#SOLID}. + * + * @param style the String to parse + * + * @return the parsed {@link BarStyle}. + */ + public static BarStyle parseBarStyle(int style) + { + switch (style) + { + case 6: + return BarStyle.SEGMENTED_6; + case 10: + return BarStyle.SEGMENTED_10; + case 12: + return BarStyle.SEGMENTED_12; + case 20: + return BarStyle.SEGMENTED_20; + default: + return BarStyle.SOLID; + } + } + + /** + * Parses the String and returns a {@link BarColor}. If a color could not be parsed, this returns + * {@link BarColor#YELLOW}. + * + * @param color the String to parse + * + * @return the parsed {@link BarColor}. + */ + public static BarColor parseBarColor(String color) + { + try + { + return BarColor.valueOf(color.toUpperCase()); + } + catch (Exception ex) + { + return BarColor.YELLOW; + } + } +} diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a4845cc..95afcb4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -17,17 +17,37 @@ leaderboard: y: 50.0 z: 10.0 notification: - actionbar: - enabled: true - message: "&eTag: You're it - tag someone!" - duration: -1 - title: - enabled: true - message: '&6Tag' - duration: 100 - sub-title: + victim: + title: enabled: true - message: "&eYou're it!" - join-delay: + message: '&6Tag' + duration: 100 + fade-in: 0 + fade-out: 0 + sub-title: + enabled: true + message: "&eYou're it!" + join-delay: + enabled: true + length: 60 + attacker: + chat: enabled: true - length: 60 \ No newline at end of file + message: "&7You just tagged &e{target}&7! You have &e{amount}&7 total tags." + global: + chat: + after-tag: + enabled: true + message: "&e* {attacker} tagged {target}, run!" + other-reason: + enabled: true + message: "&e* {target} is now 'it'! Don't let them tag you!" + boss-bar: + enabled: true + # Options: 0, 6, 10, 12, 20 + segments: 0 + # Blue, Green, Pink, Purple, Red, White, Yellow + color: YELLOW + # 0-100 + percent: 0 + message: "&e{player} is 'it'! Don't let them tag you!" \ No newline at end of file diff --git a/src/main/resources/lang.yml b/src/main/resources/lang.yml index ba33006..2cc687f 100644 --- a/src/main/resources/lang.yml +++ b/src/main/resources/lang.yml @@ -1,9 +1,10 @@ -prefix: "§3[§bFortuneBlocks§3] §f{message}" -usage_message: "§6§lUSAGE §e» §f{usage}" -error_message: "§4§lERROR §c» §7{message}" -success_message: "§2§lSUCCESS §a» §f{message}" +prefix: "&3[&bAltitudeTag&3] &f{message}" +usage_message: "&6&lUSAGE &e» &f{usage}" +error_message: "&4&lERROR &c» &7{message}" +success_message: "&2&lSUCCESS &a» &f{message}" no_permissions: "You don't have permission to do that." no_sub_access: "You don't have access to any sub-commands." reload: "Reloaded the config and lang files." header_footer: "&7&m-----------------------------------" -only_players: "Only players can run that command." \ No newline at end of file +only_players: "Only players can run that command." +set_leaderboard_location: "Successfully set the leaderboard location." \ No newline at end of file diff --git a/src/test/java/com/alttd/altiqueue/configuration/ConfigTest.java b/src/test/java/com/alttd/altiqueue/configuration/ConfigTest.java new file mode 100644 index 0000000..04259be --- /dev/null +++ b/src/test/java/com/alttd/altiqueue/configuration/ConfigTest.java @@ -0,0 +1,56 @@ +package com.alttd.altiqueue.configuration; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +import org.bukkit.configuration.ConfigurationSection; +import org.bukkit.configuration.file.YamlConfiguration; +import org.junit.Test; + +public class ConfigTest +{ + private List updateStrings = new ArrayList<>(); + + private List declarationStrings = new ArrayList<>(); + + @Test + public void test_defaults() + { + YamlConfiguration config = YamlConfiguration.loadConfiguration(new File("src/main/resources/config.yml")); + + printChildren(config); + + //declarationStrings.forEach(System.out::println); + //updateStrings.forEach(System.out::println); + } + + private void printChildren(ConfigurationSection config) + { + for (String key : config.getKeys(false)) + { + if (config.isConfigurationSection(key)) + { + printChildren(Objects.requireNonNull(config.getConfigurationSection(key))); + } + else + { + String path = config.getCurrentPath() + "." + key; + String value = config.isString(key) ? "\"" + config.get(key) + "\"" : Objects.requireNonNull(config.get(key)).toString(); + String type = config.isBoolean(key) ? "Boolean" + : config.isDouble(key) + ? "Double" + : config.isInt(key) + ? "Integer" + : "String"; + String enumTitle = path.replace(".", "_").replace("-", "_").toUpperCase(); + + updateStrings.add(String.format("updateValue(config, save, \"%s\", %s);", path, enumTitle)); + declarationStrings.add(String.format("public static final MutableValue<%s> %s = new MutableValue<>(%s);", type, enumTitle, value)); + } + } + } + + +} diff --git a/src/test/java/com/alttd/altiqueue/configuration/LangTest.java b/src/test/java/com/alttd/altiqueue/configuration/LangTest.java index 42e2017..8fbc94d 100644 --- a/src/test/java/com/alttd/altiqueue/configuration/LangTest.java +++ b/src/test/java/com/alttd/altiqueue/configuration/LangTest.java @@ -26,7 +26,7 @@ public class LangTest { for (Lang lang : Lang.values()) { - System.out.println(lang.getPath() + ": \"" + lang.getRawMessageCompiled() + "\""); + //System.out.println(lang.getPath() + ": \"" + lang.getRawMessageCompiled() + "\""); } for (Lang lang : Lang.values()) { diff --git a/src/test/java/com/alttd/altiqueue/listeners/ConnectionListenerTest.java b/src/test/java/com/alttd/altiqueue/listeners/ConnectionListenerTest.java index 53d42bc..01a3212 100644 --- a/src/test/java/com/alttd/altiqueue/listeners/ConnectionListenerTest.java +++ b/src/test/java/com/alttd/altiqueue/listeners/ConnectionListenerTest.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.UUID; import com.alttd.altitudetag.AltitudeTag; -import com.alttd.altitudetag.configuration.Lang; +import com.alttd.altitudetag.NotificationHandler; import com.alttd.altitudetag.listeners.ConnectionListener; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -14,21 +14,24 @@ import org.bukkit.event.player.PlayerQuitEvent; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.*; import static org.powermock.api.mockito.PowerMockito.doReturn; -import static org.powermock.api.mockito.PowerMockito.*; +import static org.powermock.api.mockito.PowerMockito.mockStatic; +import static org.powermock.api.mockito.PowerMockito.verifyStatic; @RunWith(PowerMockRunner.class) -@PrepareForTest({ AltitudeTag.class, Bukkit.class }) +@PrepareForTest({ AltitudeTag.class, Bukkit.class, NotificationHandler.class }) public class ConnectionListenerTest { private ConnectionListener listener; @@ -74,6 +77,9 @@ public class ConnectionListenerTest mockStatic(AltitudeTag.class); when(AltitudeTag.setTagger(any())).thenCallRealMethod(); + // NotificationHandler is... ah you get the point + mockStatic(NotificationHandler.class); + // do return players when Bukkit.getOnlinePlayers() is called doReturn(players).when(Bukkit.class); Bukkit.getOnlinePlayers(); @@ -93,11 +99,9 @@ public class ConnectionListenerTest listener.onJoin(joinEvent); - ArgumentCaptor argument = ArgumentCaptor.forClass(String[].class); - verify(player, times(1)).sendMessage(argument.capture()); - assertArrayEquals(Lang.YOURE_IT.getMessage(), argument.getValue()); - assertSame(playerUuid, AltitudeTag.getTagger()); + verifyStatic(NotificationHandler.class, times(1)); + NotificationHandler.sendVictimTitle(player, true); } @Test diff --git a/src/test/java/com/alttd/altiqueue/listeners/InteractListenerTest.java b/src/test/java/com/alttd/altiqueue/listeners/InteractListenerTest.java index 4a40325..deda7f8 100644 --- a/src/test/java/com/alttd/altiqueue/listeners/InteractListenerTest.java +++ b/src/test/java/com/alttd/altiqueue/listeners/InteractListenerTest.java @@ -1,11 +1,12 @@ package com.alttd.altiqueue.listeners; +import java.util.Collections; import java.util.UUID; import java.util.function.Consumer; import com.alttd.altitudetag.AltitudeTag; -import com.alttd.altitudetag.configuration.Lang; import com.alttd.altitudetag.listeners.InteractListener; +import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.entity.Sheep; import org.bukkit.entity.Wolf; @@ -33,7 +34,7 @@ import static org.powermock.api.mockito.PowerMockito.verifyStatic; import static org.powermock.api.mockito.PowerMockito.when; @RunWith(PowerMockRunner.class) -@PrepareForTest({ AltitudeTag.class }) +@PrepareForTest({ AltitudeTag.class, Bukkit.class }) public class InteractListenerTest { private InteractListener listener; @@ -50,6 +51,9 @@ public class InteractListenerTest public void setup() { listener = new InteractListener(); + + mockStatic(Bukkit.class); + when(Bukkit.getOnlinePlayers()).thenReturn(Collections.emptyList()); } private void setup_both_players() @@ -100,9 +104,7 @@ public class InteractListenerTest Consumer getTagsConsumer = consumerCaptor.getValue(); getTagsConsumer.accept(10); - verify(attacker, times(1)).sendMessage(Lang.TAGGED.getMessage("{tags}", 10)); assertEquals(victimUuid, AltitudeTag.getTagger()); - verify(victim, times(1)).sendMessage(Lang.YOURE_IT.getMessage()); } @Test @@ -141,8 +143,6 @@ public class InteractListenerTest verify(attacker, never()).sendMessage((String[]) any()); assertEquals(victimUuid, AltitudeTag.getTagger()); - - verify(victim, times(1)).sendMessage(Lang.YOURE_IT.getMessage()); } @Test @@ -173,7 +173,6 @@ public class InteractListenerTest AltitudeTag.getTags(any(), any()); assertEquals(victimUuid, AltitudeTag.getTagger()); - verify(victim, times(1)).sendMessage(Lang.YOURE_IT.getMessage()); } @Test