package xyz.etztech.minealert.listeners; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ComponentBuilder; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; import xyz.etztech.embed.Author; import xyz.etztech.embed.Embed; import xyz.etztech.embed.Webhook; import xyz.etztech.minealert.Color; import xyz.etztech.minealert.Lang; import xyz.etztech.minealert.MineAlert; import java.time.OffsetDateTime; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; public class BlockBreakListener implements Listener { private final MineAlert plugin; private final Map> map = new HashMap<>(); private final Queue queue = new ConcurrentLinkedQueue<>(); public BlockBreakListener(MineAlert plugin) { this.plugin = plugin; this.plugin.getServer().getPluginManager().registerEvents(this, plugin); this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, this::task); this.plugin.getServer().getScheduler().runTaskTimerAsynchronously(this.plugin, this::cleanup, 0, 20 * 60 * this.plugin.getConfig().getInt("ore.cleanup", 5)); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { queue.add(new BlockEvent(event.getPlayer(), event.getBlock().getType(), true)); int radius = this.plugin.getConfig().getInt("ore.radius", 3); for (int x = -radius; x < radius; x++) { for (int y = -radius; y < radius; y++) { for (int z = -radius; z < radius; z++) { if (x == 0 && y == 0 && z == 0) continue; queue.add(new BlockEvent(event.getPlayer(), event.getBlock().getRelative(x, y, z).getType(), false)); } } } } private void task() { while (this.plugin.isEnabled()) { BlockEvent event = this.queue.poll(); if (event != null) { for (String s: this.plugin.getConfig().getConfigurationSection("ore.blocks").getKeys(false)) { if (Lang.getMaterialKey(event.getMaterial()).equals(s)) { addStrike(event); if (event.isParent()) { check(event); } break; } } } } } private void addStrike(BlockEvent event) { List events = map.getOrDefault(event.getPlayer(), new ArrayList<>()); events.add(event); map.put(event.getPlayer(), events); } private void check(BlockEvent event) { String blockKey = Lang.getMaterialKey(event.getMaterial()); int start = this.plugin.getConfigIntFallback( 5, String.format("ore.blocks.%s.start", blockKey), "ore.start" ); int each = this.plugin.getConfigIntFallback( 5, String.format("ore.blocks.%s.each", blockKey), "ore.each" ); int ping = this.plugin.getConfigIntFallback( 5, String.format("ore.blocks.%s.ping", blockKey), "ore.ping" ); purge(map.getOrDefault(event.getPlayer(), new ArrayList<>()).iterator()); int strikes = 0; for (BlockEvent e : map.getOrDefault(event.getPlayer(), new ArrayList<>())) { if (e.isParent() && e.getMaterial().name().equals(event.getMaterial().name())) { strikes++; } } double alert = (double) strikes / start; if (alert == 1) { alert(event, strikes, true); } else if (alert > 1) { if (alert % ping == 0) { alert(event, strikes, true); } else if (alert % each == 0) { alert(event, strikes, false); } } } private void cleanup() { for (Iterator it = map.keySet().iterator(); it.hasNext(); ) { Player player = it.next(); purge(map.get(player).iterator()); if (map.get(player).isEmpty()) { it.remove(); } } } private void purge(Iterator events) { Date now = Calendar.getInstance().getTime(); while (events.hasNext()) { BlockEvent e = events.next(); int purge = 1000 * 60 * this.plugin.getConfigIntFallback( 30, String.format("ore.blocks.%s.purge", Lang.getMaterialKey(e.getMaterial())), "ore.purge" ); if (new Date(e.getTime().getTime() + purge).before(now)) { events.remove(); } } } private void alert(BlockEvent event, int strikes, boolean ping) { String message = String.format(Lang.ALERT.getMessage(), event.getPlayer().getName(), strikes, Lang.getMaterialName(event.getMaterial())); String hexColor = this.plugin.getConfigStringFallback( "#AAAAAA", String.format("ore.blocks.%s.color", Lang.getMaterialKey(event.getMaterial())), "ore.color" ); BaseComponent[] component = new ComponentBuilder() .append(message).color(ChatColor.of(hexColor)) .create(); for (Player player : Bukkit.getOnlinePlayers()) { if (player.hasPermission("minealert.alert")) { player.spigot().sendMessage(component); } } // Webhook String webhook = this.plugin.getConfigStringFallback( "", String.format("ore.blocks.%s.webhook", Lang.getMaterialKey(event.getMaterial())), "ore.webhook", "webhook" ); if (!"".equals(webhook)) { String embed = embed(event, message, ping, hexColor); this.plugin.getServer().getScheduler().runTaskAsynchronously(this.plugin, () -> { try { MineAlert.sendWebhook(webhook, embed); } catch (Exception e) { this.plugin.log(Lang.WEBHOOK_FAILED.getMessage()); } }); } } private String embed(BlockEvent event, String message, boolean ping, String hexColor) { Embed embed = new Embed() .color(Color.hexToInt(hexColor)) .description(message) .timestamp(OffsetDateTime.now()) .author(new Author(event.getPlayer().getName(), "", String.format("https://minotar.net/helm/%s/100.png", event.getPlayer().getName()), "")); return new Webhook(ping ? "@here": "", embed).toString(); } } class BlockEvent { private final Player player; private final Material material; private final Boolean parent; private final Date time; BlockEvent(Player player, Material material, Boolean parent) { this.player = player; this.material = material; this.parent = parent; this.time = Calendar.getInstance().getTime(); } public Player getPlayer() { return player; } public Material getMaterial() { return material; } public Boolean isParent() { return parent; } public Date getTime() { return time; } }