commit b0d07bed96c981c61ffd8f4193b71c941bb2bbcf Author: Erik Bročko Date: Thu Aug 15 02:10:05 2019 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e0df448 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +maven/ +target/ +.settings +.project +.classpath diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..d209b2a --- /dev/null +++ b/pom.xml @@ -0,0 +1,46 @@ + + 4.0.0 + cz.gamesites.mc + AntiAFK + 0.0.1-SNAPSHOT + AntiAFK + AntiAFK Spigot plugin + + + GameSites + https://gamesites.cz + + + + + org.spigotmc + spigot-api + 1.14.4-R0.1-SNAPSHOT + + + + + src + + + resources + + + + + maven-compiler-plugin + 3.8.0 + + 12 + + + + + + + + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/snapshots/ + + + \ No newline at end of file diff --git a/resources/plugin.yml b/resources/plugin.yml new file mode 100644 index 0000000..42f82d7 --- /dev/null +++ b/resources/plugin.yml @@ -0,0 +1,19 @@ +name: AntiAFK +main: cz.gamesites.mc.antiafk.AntiAFK +version: 0.0.1 +api-version: 1.14 +author: ericek111 +website: https://gamesites.cz/ +commands: + afklist: + aliases: whoisafk + description: Core plugin controls. + permission: antiafk.afklist +permissions: + antiafk.afklist: + description: Allows to list AFK players (including invisible admins). + default: true + antiafk.ignore: + description: With this permission, you are completely ignored by the AntiAFK plugin. + default: false + diff --git a/src/cz/gamesites/mc/antiafk/AntiAFK.java b/src/cz/gamesites/mc/antiafk/AntiAFK.java new file mode 100644 index 0000000..9c76635 --- /dev/null +++ b/src/cz/gamesites/mc/antiafk/AntiAFK.java @@ -0,0 +1,171 @@ +package cz.gamesites.mc.antiafk; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Random; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.Sound; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.HumanEntity; +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.inventory.InventoryCloseEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.bukkit.plugin.java.JavaPlugin; + +import net.md_5.bungee.api.ChatColor; + +public class AntiAFK extends JavaPlugin implements Listener { + + // frequency of checks + private static final int CHECK_INTERVAL = 2 * 20; + // how many times a check has to fail in order to mark the player as AFK + private static final int STRIKES_AFK = 3; + + private static AntiAFK INSTANCE = null; + private HashMap lastPositions = new HashMap<>(); + private HashMap strikes = new HashMap<>(); + private ArrayList inventories = new ArrayList<>(); + + private static final ItemStack yesItem = new ItemStack(Material.DIAMOND, 1); + private static final ItemStack noItem = new ItemStack(Material.GRAY_STAINED_GLASS_PANE, 1); + + static { + ItemMeta yesMeta = yesItem.getItemMeta(); + yesMeta.setDisplayName("§aAno, jsem tady."); + yesItem.setItemMeta(yesMeta); + + ItemMeta noMeta = yesItem.getItemMeta(); + noMeta.setDisplayName("§cNe, nejsem tady."); + noItem.setItemMeta(noMeta); + } + + @Override + public void onEnable() { + INSTANCE = this; + Bukkit.getServer().getPluginManager().registerEvents(this, this); + + createInventories(20); + + Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, () -> { + for (Player p : Bukkit.getServer().getOnlinePlayers()) { + if (p.hasPermission("antiafk.ignore")) + continue; + + int bX = p.getLocation().getBlockX(); + int bY = p.getLocation().getBlockY(); + int bZ = p.getLocation().getBlockZ(); + int[] newPos = new int[] { bX, bY, bZ }; + int[] lastPos = this.lastPositions.get(p); + + if (lastPos == null || !Arrays.equals(lastPos, newPos)) { + this.lastPositions.put(p, newPos); + this.strikes.put(p, 0); + continue; + } + + int strikenum = strikes.merge(p, 1, Integer::sum); + if (strikenum == STRIKES_AFK) { + int idx = ThreadLocalRandom.current().nextInt(0, inventories.size()); + p.openInventory(inventories.get(idx)); + p.playSound(p.getLocation(), Sound.ENTITY_EXPERIENCE_ORB_PICKUP, 0.5F, 0.5F); + } + + this.lastPositions.put(p, newPos); + } + }, CHECK_INTERVAL, CHECK_INTERVAL); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + this.lastPositions.remove(event.getPlayer()); + this.strikes.remove(event.getPlayer()); + } + + @Override + public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { + if (cmd.getName().equalsIgnoreCase("afklist")) { + + long playersAway = strikes.entrySet().stream().filter(x -> x.getValue() > STRIKES_AFK).count(); + if (playersAway > 0) { + sender.sendMessage( + ChatColor.GOLD + "[AntiAFK] " + + ChatColor.YELLOW + "Players away " + ChatColor.GRAY + "(" + playersAway + ")" + ChatColor.YELLOW + ": " + ); + } else { + sender.sendMessage(ChatColor.GOLD + "[AntiAFK] " + ChatColor.YELLOW + "There are no AFK players!"); + } + + strikes.entrySet().stream() + .filter(x -> x.getValue() > STRIKES_AFK) + .sorted((e1, e2) -> Integer.compare(e2.getValue(), e1.getValue())) + .forEach(x -> { + int awayMin = x.getValue() * CHECK_INTERVAL / 20 / 60; + sender.sendMessage(x.getKey().getDisplayName() + ChatColor.GRAY + ": " + awayMin + " min."); + }); + + return true; + } + return false; + } + + @EventHandler + public void onInventoryClick(InventoryClickEvent event) { + if (this.inventories.contains(event.getInventory())) { + event.setCancelled(true); + + HumanEntity ent = event.getWhoClicked(); + if (!(ent instanceof Player)) + return; + + ItemStack is = event.getCurrentItem(); + if (is != null && is.equals(yesItem)) { + strikes.put((Player) ent, 0); + ent.closeInventory(); + } + } + } + + @EventHandler + public void onInventoryClose(InventoryCloseEvent event) { + if (this.inventories.contains(event.getInventory()) && this.strikes.get(event.getPlayer()) > 0) { + Bukkit.getScheduler().runTask(this, () -> event.getPlayer().openInventory(event.getInventory())); + } + } + + private void createInventories(int count) { + for (int i = 0; i < count; i++) { + this.inventories.add(Bukkit.createInventory(null, 5 * 9, "AFK kontrola - klikni na diamant")); + } + + Random rand = new Random(); + for (Inventory inv : this.inventories) { + int rSlot = rand.nextInt(inv.getSize()); + + for (int i = 0; i < inv.getSize(); i++) { + inv.setItem(i, i == rSlot ? yesItem : noItem); + } + } + } + + public static List getAwayPlayers() { + return INSTANCE.strikes.entrySet() + .stream() + .filter(x -> x.getValue() > STRIKES_AFK) + .map(x -> x.getKey()) + .collect(Collectors.toList()); + } + +}