From 233116061d17b14d10c4555b3ab4e6460ad7614c Mon Sep 17 00:00:00 2001 From: Mykyta Date: Fri, 21 Feb 2020 21:00:28 -0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=99=8C=20Bossbar=20feature=20+=20Robust?= =?UTF-8?q?=20AFK=20system?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/xyz/nkomarn/Harbor/Harbor.java | 13 +++++--- .../nkomarn/Harbor/command/HarborCommand.java | 9 ++++++ .../nkomarn/Harbor/listener/AfkListener.java | 32 +++++++++++++++++++ .../nkomarn/Harbor/listener/BedListener.java | 10 +++--- .../java/xyz/nkomarn/Harbor/task/Checker.java | 25 +++++++++------ .../java/xyz/nkomarn/Harbor/util/Afk.java | 28 ++++++++++++++++ .../xyz/nkomarn/Harbor/util/Messages.java | 20 +++++++++--- src/main/resources/config.yml | 13 ++++++-- 8 files changed, 125 insertions(+), 25 deletions(-) create mode 100644 src/main/java/xyz/nkomarn/Harbor/listener/AfkListener.java create mode 100644 src/main/java/xyz/nkomarn/Harbor/util/Afk.java diff --git a/src/main/java/xyz/nkomarn/Harbor/Harbor.java b/src/main/java/xyz/nkomarn/Harbor/Harbor.java index fda8920..3334129 100644 --- a/src/main/java/xyz/nkomarn/Harbor/Harbor.java +++ b/src/main/java/xyz/nkomarn/Harbor/Harbor.java @@ -4,6 +4,7 @@ import com.earth2me.essentials.Essentials; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import xyz.nkomarn.Harbor.command.HarborCommand; +import xyz.nkomarn.Harbor.listener.AfkListener; import xyz.nkomarn.Harbor.listener.BedListener; import xyz.nkomarn.Harbor.listener.JoinListener; import xyz.nkomarn.Harbor.task.Checker; @@ -18,10 +19,8 @@ public class Harbor extends JavaPlugin { public void onEnable() { instance = this; saveDefaultConfig(); - if (Config.getBoolean("features.skip")) { - Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, - new Checker(), 0L, Config.getInteger("values.timer") * 20); - } + Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, + new Checker(), 0L, Config.getInteger("values.timer") * 20); getCommand("harbor").setExecutor(new HarborCommand()); getServer().getPluginManager().registerEvents(new JoinListener(), this); @@ -32,5 +31,11 @@ public class Harbor extends JavaPlugin { // Essentials hook essentials = (Essentials) getServer().getPluginManager().getPlugin("Essentials"); + + // If Essentials isn't present, enable fallback AFK system + if (essentials == null) { + System.out.println("Registered Listener"); + getServer().getPluginManager().registerEvents(new AfkListener(), this); + } } } diff --git a/src/main/java/xyz/nkomarn/Harbor/command/HarborCommand.java b/src/main/java/xyz/nkomarn/Harbor/command/HarborCommand.java index 3f27b8f..2e112dd 100644 --- a/src/main/java/xyz/nkomarn/Harbor/command/HarborCommand.java +++ b/src/main/java/xyz/nkomarn/Harbor/command/HarborCommand.java @@ -2,9 +2,13 @@ package xyz.nkomarn.Harbor.command; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Sound; import org.bukkit.World; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -29,6 +33,11 @@ public class HarborCommand implements TabExecutor { if (args.length < 1) { sender.sendMessage(ChatColor.translateAlternateColorCodes('&', prefix + "&7Harbor version " + Harbor.version + " by TechToolbox (@nkomarn).")); + + BossBar bar = Bukkit.createBossBar("AAAAAAAAAAAA", BarColor.BLUE, BarStyle.SOLID); + bar.setProgress(1); + bar.addPlayer((Player) sender); // TODO remove + return true; } diff --git a/src/main/java/xyz/nkomarn/Harbor/listener/AfkListener.java b/src/main/java/xyz/nkomarn/Harbor/listener/AfkListener.java new file mode 100644 index 0000000..330a21b --- /dev/null +++ b/src/main/java/xyz/nkomarn/Harbor/listener/AfkListener.java @@ -0,0 +1,32 @@ +package xyz.nkomarn.Harbor.listener; + +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.event.player.AsyncPlayerChatEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import xyz.nkomarn.Harbor.util.Afk; + +public class AfkListener implements Listener { + @EventHandler + public void onChat(AsyncPlayerChatEvent event) { + Afk.updateActivity(event.getPlayer()); + } + + @EventHandler + public void onCommand(PlayerCommandPreprocessEvent event) { + Afk.updateActivity(event.getPlayer()); + } + + @EventHandler + public void onMove(PlayerMoveEvent event) { + Afk.updateActivity(event.getPlayer()); + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + Afk.updateActivity((Player) event.getWhoClicked()); + } +} diff --git a/src/main/java/xyz/nkomarn/Harbor/listener/BedListener.java b/src/main/java/xyz/nkomarn/Harbor/listener/BedListener.java index 9f299c2..ec5d3b4 100644 --- a/src/main/java/xyz/nkomarn/Harbor/listener/BedListener.java +++ b/src/main/java/xyz/nkomarn/Harbor/listener/BedListener.java @@ -15,12 +15,10 @@ public class BedListener implements Listener { public void onBedEnter(final PlayerBedEnterEvent event) { if (event.getBedEnterResult() != PlayerBedEnterEvent.BedEnterResult.OK) return; if (Checker.skippingWorlds.contains(event.getPlayer().getWorld())) return; - Bukkit.getScheduler().runTaskLater(Harbor.instance, () -> { - Messages.sendWorldChatMessage(event.getBed().getWorld(), - Config.getString("messages.chat.sleeping") - .replace("[player]", event.getPlayer().getName()) - .replace("[displayname]", event.getPlayer().getDisplayName())); - }, 1); + Bukkit.getScheduler().runTaskLater(Harbor.instance, () -> Messages.sendWorldChatMessage(event.getBed().getWorld(), + Config.getString("messages.chat.sleeping") + .replace("[player]", event.getPlayer().getName()) + .replace("[displayname]", event.getPlayer().getDisplayName())), 1); } @EventHandler(ignoreCancelled = true) diff --git a/src/main/java/xyz/nkomarn/Harbor/task/Checker.java b/src/main/java/xyz/nkomarn/Harbor/task/Checker.java index ea8c0d6..b60cf1c 100644 --- a/src/main/java/xyz/nkomarn/Harbor/task/Checker.java +++ b/src/main/java/xyz/nkomarn/Harbor/task/Checker.java @@ -3,9 +3,13 @@ package xyz.nkomarn.Harbor.task; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.World; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; import org.bukkit.entity.Player; import xyz.nkomarn.Harbor.Harbor; +import xyz.nkomarn.Harbor.util.Afk; import xyz.nkomarn.Harbor.util.Config; import xyz.nkomarn.Harbor.util.Messages; @@ -32,14 +36,17 @@ public class Checker implements Runnable { // Send actionbar sleeping notification if (sleeping > 0 && needed > 0) { - world.getPlayers().forEach(player -> Messages.sendActionBarMessage(player, - Config.getString("messages.actionbar.sleeping"))); + double percentage = Math.min(1, (double) sleeping / getSkipAmount(world)); + Messages.sendBossBarMessage(world, Config.getString("messages.bossbar.sleeping.message"), + BarColor.valueOf(Config.getString("messages.bossbar.sleeping.color")), percentage); + Messages.sendActionBarMessage(world, Config.getString("messages.actionbar.sleeping")); } else if (needed == 0 && sleeping > 0) { - world.getPlayers().forEach(player -> Messages.sendActionBarMessage(player, - Config.getString("messages.actionbar.everyone"))); - skippingWorlds.add(world); + Messages.sendBossBarMessage(world, Config.getString("messages.bossbar.everyone.message"), + BarColor.valueOf(Config.getString("messages.bossbar.everyone.color")), 1); + Messages.sendActionBarMessage(world, Config.getString("messages.actionbar.everyone")); if (!Config.getBoolean("features.skip")) return; + skippingWorlds.add(world); new AccelerateNightTask(world).runTaskTimer(Harbor.instance, 0L, 1); Messages.sendRandomChatMessage(world, "messages.chat.accelerateNight"); } @@ -81,10 +88,10 @@ public class Checker implements Runnable { return world.getPlayers().stream().filter(Checker::isExcluded).collect(toList()); } - private static boolean isExcluded(final Player p) { - final boolean excludedByGameMode = Config.getBoolean("features.ignore") && p.getGameMode() != GameMode.SURVIVAL; - final boolean excludedByPermission = Config.getBoolean("features.bypass") && p.hasPermission("harbor.bypass"); - final boolean excludedByAfk = Harbor.essentials != null && Harbor.essentials.getUser(p).isAfk(); // Essentials AFK detection + private static boolean isExcluded(final Player player) { + final boolean excludedByGameMode = Config.getBoolean("features.ignore") && player.getGameMode() != GameMode.SURVIVAL; + final boolean excludedByPermission = Config.getBoolean("features.bypass") && player.hasPermission("harbor.bypass"); + final boolean excludedByAfk = Afk.isAfk(player); return excludedByGameMode || excludedByPermission || excludedByAfk; } diff --git a/src/main/java/xyz/nkomarn/Harbor/util/Afk.java b/src/main/java/xyz/nkomarn/Harbor/util/Afk.java new file mode 100644 index 0000000..c851722 --- /dev/null +++ b/src/main/java/xyz/nkomarn/Harbor/util/Afk.java @@ -0,0 +1,28 @@ +package xyz.nkomarn.Harbor.util; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import xyz.nkomarn.Harbor.Harbor; + +import java.util.HashMap; +import java.util.concurrent.TimeUnit; + +public class Afk { + private static HashMap activity = new HashMap<>(); + + public static boolean isAfk(Player player) { + if (!Config.getBoolean("features.afk")) return false; + + if (Harbor.essentials != null) { + return Harbor.essentials.getUser(player).isAfk(); + } + + if (!activity.containsKey(player)) return false; + long minutes = TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis() - activity.get(player)); + return minutes >= Config.getInteger("values.timeout"); + } + + public static void updateActivity(Player player) { + activity.put(player, System.currentTimeMillis()); + } +} diff --git a/src/main/java/xyz/nkomarn/Harbor/util/Messages.java b/src/main/java/xyz/nkomarn/Harbor/util/Messages.java index 501ef9f..0177852 100644 --- a/src/main/java/xyz/nkomarn/Harbor/util/Messages.java +++ b/src/main/java/xyz/nkomarn/Harbor/util/Messages.java @@ -2,9 +2,14 @@ package xyz.nkomarn.Harbor.util; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; +import org.bukkit.boss.BarColor; +import org.bukkit.boss.BarStyle; +import org.bukkit.boss.BossBar; import org.bukkit.entity.Player; +import xyz.nkomarn.Harbor.Harbor; import xyz.nkomarn.Harbor.task.Checker; import java.util.List; @@ -24,11 +29,18 @@ public class Messages { prepareMessage(world, message)))); } - public static void sendActionBarMessage(final Player player, final String message) { - final World world = player.getWorld(); + public static void sendActionBarMessage(final World world, final String message) { if (!Config.getBoolean("messages.actionbar.actionbar") || message.length() < 1) return; - player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText( - prepareMessage(world, message))); + world.getPlayers().forEach(player -> player.spigot().sendMessage(ChatMessageType.ACTION_BAR, + TextComponent.fromLegacyText(prepareMessage(world, message)))); + } + + public static void sendBossBarMessage(final World world, final String message, final BarColor color, final double percentage) { + if (!Config.getBoolean("messages.bossbar.bossbar") || message.length() < 1) return; + BossBar bar = Bukkit.createBossBar(Messages.prepareMessage(world, message), color, BarStyle.SOLID); + bar.setProgress(percentage); + world.getPlayers().forEach(bar::addPlayer); + Bukkit.getScheduler().runTaskLater(Harbor.instance, bar::removeAll, Config.getInteger("values.timer") * 20); } private static String prepareMessage(final World world, final String message) { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4fcf41d..1ad234d 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -11,7 +11,8 @@ values: timer: 2 # How often (in seconds) to run the clock task (used to detect sleep, AFK players, time actionbar, etc.) percent: 50 # Percent of players that need to sleep to skip night (must be between 0 to 100) - interval: 60 # Time skip interval that is added when the night get accelerated. + interval: 60 # Time skip interval that is added when the night is accelerated. + timeout: 15 # Time (in minutes) until a player is considered AFK (for internal AFK detection system only- when Essentials isn't present) features: skip: true # Toggle night skipping feature. Configure amount of players needed to skip above (percent) @@ -19,7 +20,7 @@ features: phantoms: false # Reset the sleep statistic (practically disables phantom spawns - false = no phantoms) bypass: true # Toggle exclusion of operators/players with permission "harbor.bypass" from sleep count ignore: true # Toggle exclusion of players in creative and spectator mode - afk: true # Detect AFK players and remove them from the sleep count (Essentials API used for detection) + afk: true # Detect AFK players and remove them from the sleep count (Essentials API used for detection when possible) notifier: true # Displays a notification when a new update is released messages: @@ -38,6 +39,14 @@ messages: actionbar: true # Enable/disable actionbar messages sleeping: "&e[sleeping] out of [needed] players are sleeping ([more] more needed to skip)." # Shown when some players are in bed everyone: "&eEveryone is sleeping. Sweet dreams!" # Shown when all players are in bed + bossbar: # Use colors from https://hub.spigotmc.org/javadocs/spigot/org/bukkit/boss/BarColor.html + bossbar: true # Enable/disable bossbar messages + sleeping: + message: "&f&l[sleeping] out of [needed] are sleeping &7&l([more] more needed)" # Shown when some players are in bed + color: BLUE + everyone: + message: "&f&lEveryone is sleeping. Sweet dreams!" # Shown when all players are in bed + color: GREEN miscellaneous: prefix: "&8&l(&6&lHarbor&8&l)&r " # Prefix for Harbor command/miscellaneous messages permission: "&7Insufficient permissions." # Sent when player doesn't have permissions to run command