MineAlert/src/main/java/xyz/etztech/minealert/listeners/BlockBreakListener.java

218 lines
7.6 KiB
Java

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.Javacord;
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<Player, List<BlockEvent>> map = new HashMap<>();
private final Queue<BlockEvent> 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<BlockEvent> 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<Player> 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<BlockEvent> 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(Javacord.escapeFormat(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;
}
}