diff --git a/src/main/java/xyz/etztech/orealert/Lang.java b/src/main/java/xyz/etztech/orealert/Lang.java index 93333c1..d5880b4 100644 --- a/src/main/java/xyz/etztech/orealert/Lang.java +++ b/src/main/java/xyz/etztech/orealert/Lang.java @@ -3,6 +3,8 @@ package xyz.etztech.orealert; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.chat.TextComponent; +import org.apache.commons.lang.WordUtils; +import org.bukkit.Material; import org.bukkit.command.CommandSender; public enum Lang { @@ -23,4 +25,15 @@ public enum Lang { text.setColor(this.color); sender.spigot().sendMessage(text); } + + public static String getMaterialName(Material material) { + String name = material.name(); + name = name.replaceAll("_", " "); + name = WordUtils.capitalize(name); + return name; + } + + public static String getMaterialKey(Material material) { + return material.name().toLowerCase(); + } } diff --git a/src/main/java/xyz/etztech/orealert/OreAlert.java b/src/main/java/xyz/etztech/orealert/OreAlert.java index f32ff60..a3a69d7 100644 --- a/src/main/java/xyz/etztech/orealert/OreAlert.java +++ b/src/main/java/xyz/etztech/orealert/OreAlert.java @@ -11,12 +11,9 @@ import java.util.logging.Logger; public class OreAlert extends JavaPlugin { - private static OreAlert instance; - public static FileConfiguration config; private final Logger log = Logger.getLogger( "Minecraft" ); public void onEnable() { - instance = this; saveDefaultConfig(); reloadConfig(); @@ -26,22 +23,8 @@ public class OreAlert extends JavaPlugin { } } - public void loadConfig() { - config = Bukkit.getPluginManager().getPlugin("OreAlert").getConfig(); - } - - @Override - public void reloadConfig() { - super.reloadConfig(); - loadConfig(); - } - public void log(String message) { log.info( "[OreAlert]: " + message ); } - - public static OreAlert getInstance() { - return instance; - } } diff --git a/src/main/java/xyz/etztech/orealert/listeners/BlockBreakListener.java b/src/main/java/xyz/etztech/orealert/listeners/BlockBreakListener.java index 60613a1..686c8bf 100644 --- a/src/main/java/xyz/etztech/orealert/listeners/BlockBreakListener.java +++ b/src/main/java/xyz/etztech/orealert/listeners/BlockBreakListener.java @@ -1,21 +1,131 @@ package xyz.etztech.orealert.listeners; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockBreakEvent; +import xyz.etztech.orealert.Lang; import xyz.etztech.orealert.OreAlert; +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.ConcurrentLinkedQueue; + public class BlockBreakListener implements Listener { private final OreAlert plugin; + private final Map> map = new HashMap<>(); + private final Queue queue = new ConcurrentLinkedQueue<>(); public BlockBreakListener(OreAlert 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("cleanup", 5)); } @EventHandler public void onBlockBreak(BlockBreakEvent event) { + queue.add(new BlockEvent(event.getPlayer(), event.getBlock(), true)); + int radius = this.plugin.getConfig().getInt("radius", 3); + for (int x = -radius; x < radius; x++) { + for (int y = -radius; y < radius; y++) { + for (int z = -radius; z < radius; z++) { + queue.add(new BlockEvent(event.getPlayer(), event.getBlock().getRelative(x, y, z), false)); + } + } + } + } + + private void task() { + while (true) { + BlockEvent event = this.queue.poll(); + if (event != null) { + List blocks = this.plugin.getConfig().getStringList("blocks"); + for (String s: blocks) { + if (Lang.getMaterialKey(event.getBlock().getType()).equals(s)) { + addStrike(event); + 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) { + List events = map.getOrDefault(event.getPlayer(), new ArrayList<>()); + FileConfiguration config = this.plugin.getConfig(); + String blockKey = Lang.getMaterialKey(event.getBlock().getType()); + int start = config.getInt(String.format("blocks.%s.start", blockKey), config.getInt("start", 5)); + int each = config.getInt(String.format("blocks.%s.each", blockKey), config.getInt("each", 5)); + int ping = config.getInt(String.format("blocks.%s.ping", blockKey), config.getInt("ping", 5)); + purge(map.getOrDefault(event.getPlayer(), new ArrayList<>()).iterator()); + + int strikes = map.getOrDefault(event.getPlayer(), new ArrayList<>()).size(); + } + + 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(); + int globalPurge = this.plugin.getConfig().getInt("purge", 30); + while (events.hasNext()) { + BlockEvent e = events.next(); + int purge = 1000 * 60 * this.plugin.getConfig().getInt(String.format("blocks.%s.purge", Lang.getMaterialKey(e.getBlock().getType())), globalPurge); + if (new Date(e.getTime().getTime() + purge).before(now)) { + events.remove(); + } + } + } +} + +class BlockEvent { + private final Player player; + private final Block block; + private final Boolean parent; + private final Date time; + + BlockEvent(Player player, Block block, Boolean parent) { + this.player = player; + this.block = block; + this.parent = parent; + this.time = Calendar.getInstance().getTime(); + } + + public Player getPlayer() { + return player; + } + + public Block getBlock() { + return block; + } + + public Boolean isParent() { + return parent; + } + + public Date getTime() { + return time; } } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index fd69d3e..456f968 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -1,5 +1,10 @@ -# Global settings, for less arthritis -# How long until we purge a node strike, in minutes +# Radius to search around block for similar blocks in the "vein" +radius: 3 +# How often to run cleanup task (in minutes) +cleanup: 5 + +# Global notification settings, for less arthritis +# How long until we purge a node strike (in minutes) purge: 30 # How many veins found within the above purge minutes to notify start: 5 @@ -14,12 +19,8 @@ webhook: '' # Each of the above notify settings can be overridden per-block if needed # Anything not overridden will default to the global setting blocks: - - - material: 'diamond_ore' - name: 'Diamond Ore' + diamond_ore: color: '#b9f2ff' - - - material: 'ancient_debris' - name: 'Ancient Debris' + ancient_debris: color: '#933A16' purge: 45 \ No newline at end of file