diff --git a/config.yml b/config.yml deleted file mode 100644 index 8972c40..0000000 --- a/config.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Ignore all stealing? -allow-stealing: false - -# Breaking these blocks don't cause alerts. (Material) -excluded-blocks: - - WHEAT - - CARROTS - - POTATOES - - BEETROOTS - - NETHER_WART - - PUMPKIN - - MELON - - SUGAR_CANE - - KELP_PLANT - - KELP - - SWEET_BERRY_BUSH - - COCOA - -# Taking items from these containers cause alerts. (InventoryType) -valid-containers: - - CHEST - - BARREL - - BLAST_FURNACE - - BREWING - - FURNACE - - DISPENSER - - DROPPER - - HOPPER - - SHULKER_BOX - - SMOKER - -# Which animals trigger an alert when killed on a build. -triggered-animals: - - ALLAY - - ARMADILLO - - AXOLOTL - - CAMEL - - CAT - - CHICKEN - - COW - - DONKEY - - FROG - - HORSE - - MOOSHROOM - - MULE - - OCELOT - - PARROT - - PIG - - RABBIT - - SHEEP - - SKELETON_HORSE - - SNIFFER - - SNOW_GOLEM - - TURTLE - - VILLAGER - - IRON_GOLEM - - WOLF - - LLAMA - - FOX - - GOAT - - PANDA - - POLAR_BEAR - -# [Optional] Dynmap link for external hooks. -map-link: "" \ No newline at end of file diff --git a/plugin.yml b/plugin.yml deleted file mode 100644 index 5670fcb..0000000 --- a/plugin.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: GriefAlert -main: net.ardakaz.griefalert.GriefAlert -version: 0.6 -api-version: 1.21 -depends: [CoreProtect] -softdepend: [DiscordSRV] -description: A simple grief alert plugin using the CoreProtect API. -authors: [Ardakaz, kleedje30] -commands: - griefalert: - description: GriefAlert staff commands - usage: /griefalert - permission: griefalert.staff - permission-message: You do not have permission to use this command. diff --git a/src/net/ardakaz/griefalert/GriefAlert.java b/src/net/ardakaz/griefalert/GriefAlert.java deleted file mode 100644 index 9b71803..0000000 --- a/src/net/ardakaz/griefalert/GriefAlert.java +++ /dev/null @@ -1,827 +0,0 @@ -package net.ardakaz.griefalert; - -import net.coreprotect.CoreProtect; -import net.coreprotect.CoreProtectAPI; -import net.coreprotect.CoreProtectAPI.ParseResult; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.block.Block; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.*; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.entity.EntityDamageByEntityEvent; -import org.bukkit.event.entity.EntityDeathEvent; -import org.bukkit.event.hanging.HangingBreakByEntityEvent; -import org.bukkit.event.inventory.InventoryAction; -import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.inventory.InventoryType; -import org.bukkit.event.player.PlayerInteractAtEntityEvent; -import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.EntityEquipment; -import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -import java.sql.*; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - - -public class GriefAlert extends JavaPlugin implements Listener { - - private static CoreProtectAPI coreProtectAPI; - private final String DB_FILE = "ignored_locations.db"; - private Integer identicalAlerts = 1; - private String lastAlert; - private Set EXCLUDED_BLOCKS; - private Set VALID_CONTAINERS; - private String MAP_LINK; - private Boolean ALLOW_STEALING; - private Connection connection; - - // Block inspector: only the most recent placement counts for ownership. - private static String inspectBlock(Block block, Player player) { - List lookup = coreProtectAPI.blockLookup(block, 50000000); - if (lookup == null || lookup.isEmpty()) { - // Natural block - return null; - } - // Find the most recent placement event only - for (String[] result : lookup) { - ParseResult parseResult = coreProtectAPI.parseResult(result); - if (parseResult == null) continue; - if (parseResult.getActionId() == 1 && !parseResult.isRolledBack() && !parseResult.getPlayer().startsWith("#")) { - // If the current player placed it, it's theirs (no alert) - if (parseResult.getPlayer().equals(player.getName())) { - return null; - } else { - return parseResult.getPlayer(); - } - } - // If we see a break before a placement, stop (block is gone) - if (parseResult.getActionId() == 0) { - break; - } - } - // No valid placement found - return null; - } - - private static String getHumanWorldName(String worldName) { - String world = ""; - - if (worldName.endsWith("_nether")) { - world = " in the Nether"; - } else if (worldName.endsWith("_the_end")) { - world = " in the End"; - } - - return world; - } - - // Init GriefAlert - @Override - public void onEnable() { - - coreProtectAPI = getCoreProtect(); - if (coreProtectAPI == null) { - getLogger().severe("CoreProtect not found! Disabling plugin."); - getServer().getPluginManager().disablePlugin(this); - return; - } - - getServer().getPluginManager().registerEvents(this, this); - - // Config - saveDefaultConfig(); - List excludedBlocks = getConfig().getStringList("excluded-blocks"); - EXCLUDED_BLOCKS = excludedBlocks.stream().map(Material::valueOf).collect(Collectors.toSet()); - List validContainers = getConfig().getStringList("valid-containers"); - VALID_CONTAINERS = validContainers.stream().map(InventoryType::valueOf).collect(Collectors.toSet()); - MAP_LINK = getConfig().getString("map-link"); - ALLOW_STEALING = getConfig().getBoolean("allow-stealing"); - - setupDatabase(); - - getCommand("griefalert").setTabCompleter(this); - - getLogger().info("GriefAlert has been enabled."); - } - - @Override - public void onDisable() { - getLogger().info("GriefAlert has been disabled."); - if (connection != null) { - try { - connection.close(); - } catch (SQLException ignored) { - } - } - } - - private void setupDatabase() { - try { - connection = DriverManager.getConnection("jdbc:sqlite:" + getDataFolder().getAbsolutePath() + "/" + DB_FILE); - Statement stmt = connection.createStatement(); - stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ignored_locations (x INTEGER, y INTEGER, z INTEGER, world TEXT, PRIMARY KEY (x, y, z, world))"); - stmt.close(); - } catch (SQLException e) { - getLogger().severe("Could not set up SQLite database: " + e.getMessage()); - } - } - - private boolean isLocationIgnored(int x, int y, int z, String world) { - try { - PreparedStatement ps = connection.prepareStatement("SELECT 1 FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?"); - ps.setInt(1, x); - ps.setInt(2, y); - ps.setInt(3, z); - ps.setString(4, world); - ResultSet rs = ps.executeQuery(); - boolean exists = rs.next(); - rs.close(); - ps.close(); - return exists; - } catch (SQLException e) { - getLogger().warning("DB error: " + e.getMessage()); - return false; - } - } - - private boolean addIgnoredLocation(int x, int y, int z, String world) { - try { - PreparedStatement ps = connection.prepareStatement("INSERT OR IGNORE INTO ignored_locations (x, y, z, world) VALUES (?, ?, ?, ?)"); - ps.setInt(1, x); - ps.setInt(2, y); - ps.setInt(3, z); - ps.setString(4, world); - int updated = ps.executeUpdate(); - ps.close(); - return updated > 0; - } catch (SQLException e) { - getLogger().warning("DB error: " + e.getMessage()); - return false; - } - } - - private boolean removeIgnoredLocation(int x, int y, int z, String world) { - try { - PreparedStatement ps = connection.prepareStatement("DELETE FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?"); - ps.setInt(1, x); - ps.setInt(2, y); - ps.setInt(3, z); - ps.setString(4, world); - int updated = ps.executeUpdate(); - ps.close(); - return updated > 0; - } catch (SQLException e) { - getLogger().warning("DB error: " + e.getMessage()); - return false; - } - } - - @EventHandler(ignoreCancelled = true) - // Block break alerts - public void onBlockBreak(BlockBreakEvent event) { - // Exclusion list - if (EXCLUDED_BLOCKS.contains(event.getBlock().getType())) { - return; - } - - // Event parser - String playerName = event.getPlayer().getName(); - String blockType = event.getBlock().getType().toString(); - int x = event.getBlock().getX(); - int y = event.getBlock().getY(); - int z = event.getBlock().getZ(); - String worldName = event.getBlock().getWorld().getName(); - - // Check if grief - String target = inspectBlock(event.getBlock(), event.getPlayer()); - if (target != null) { - String message = ChatColor.GRAY + playerName + " broke " + blockType + " placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } - } - - // Stealing alerts - @EventHandler(ignoreCancelled = true) - public void onInventoryClick(InventoryClickEvent event) { - if (ALLOW_STEALING) { - return; - } - boolean stealing; - - // Event parser for inv - if (!(event.getWhoClicked() instanceof Player player)) return; - Inventory inventory = event.getInventory(); - Inventory clickedInventory = event.getClickedInventory(); - ItemStack item = event.getCurrentItem(); - - if (item == null || inventory.getLocation() == null || item.getType() == Material.AIR) { - return; - } - - // Exclusion list - if (!VALID_CONTAINERS.contains(inventory.getType())) { - return; - } - - // Inv actions (needs fixing) - InventoryAction action = event.getAction(); - if ((action == InventoryAction.PICKUP_ALL || action == InventoryAction.PICKUP_HALF || - action == InventoryAction.PICKUP_ONE || action == InventoryAction.PICKUP_SOME || - action == InventoryAction.MOVE_TO_OTHER_INVENTORY) && clickedInventory == inventory) { - stealing = true; - } else if (action == InventoryAction.PLACE_ALL || action == InventoryAction.PLACE_SOME || action == InventoryAction.PLACE_ONE || action == InventoryAction.MOVE_TO_OTHER_INVENTORY) { - stealing = false; - } else { - return; - } - - // Event parser for container + check if grief - String target = inspectBlock(inventory.getLocation().getBlock(), player); - if (target != null) { - String playerName = player.getName(); - String itemName = item.getType().toString(); - int amount = item.getAmount(); - int x = inventory.getLocation().getBlockX(); - int y = inventory.getLocation().getBlockY(); - int z = inventory.getLocation().getBlockZ(); - String worldName = inventory.getLocation().getWorld().getName(); - if (stealing) { - String message = ChatColor.GRAY + playerName + " took " + amount + " " + itemName + " from " + target + "'s container at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } else { - String message = ChatColor.GRAY + playerName + " put " + amount + " " + itemName + " into " + target + "'s container at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } - } - } - - // Armor Stand break alerts - @EventHandler(ignoreCancelled = true) - public void onArmorStandBreak(EntityDamageByEntityEvent event) { - if (!(event.getEntity() instanceof ArmorStand armorStand)) return; - if (!(event.getDamager() instanceof Player player)) return; - int x = armorStand.getLocation().getBlockX(); - int y = armorStand.getLocation().getBlockY(); - int z = armorStand.getLocation().getBlockZ(); - String worldName = armorStand.getWorld().getName(); - if (isLocationIgnored(x, y, z, worldName)) { - event.setCancelled(true); - return; - } - String playerName = player.getName(); - String target = inspectBlock(armorStand.getLocation().getBlock(), player); - if (target != null) { - String message = ChatColor.GRAY + playerName + " broke an armor stand placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } - } - - // Armor Stand item interaction alerts - @EventHandler(ignoreCancelled = true) - public void onArmorStandInteract(PlayerInteractAtEntityEvent event) { - if (!(event.getRightClicked() instanceof ArmorStand armorStand)) return; - Player player = event.getPlayer(); - int x = armorStand.getLocation().getBlockX(); - int y = armorStand.getLocation().getBlockY(); - int z = armorStand.getLocation().getBlockZ(); - String worldName = armorStand.getWorld().getName(); - if (isLocationIgnored(x, y, z, worldName)) { - event.setCancelled(true); - return; - } - String target = inspectBlock(armorStand.getLocation().getBlock(), player); - if (target != null) { - String playerName = player.getName(); - ItemStack handItem = player.getInventory().getItemInMainHand(); - // Determine which slot is being interacted with - //org.bukkit.inventory.EquipmentSlot slot = event.getHand(); - EntityEquipment equipment = armorStand.getEquipment(); - ItemStack armorItem = null; - event.getClickedPosition();// Approximate slot by Y position (not perfect, but Bukkit API is limited so it is what it is :3) - double yPos = event.getClickedPosition().getY(); - if (yPos > 1.6) armorItem = equipment.getHelmet(); - else if (yPos > 1.2) armorItem = equipment.getChestplate(); - else if (yPos > 0.8) armorItem = equipment.getLeggings(); - else if (yPos > 0.1) armorItem = equipment.getBoots(); - else armorItem = equipment.getItemInMainHand(); - boolean handEmpty = handItem.getType() == Material.AIR; - boolean armorEmpty = armorItem == null || armorItem.getType() == Material.AIR; - String action; - //this works at the instance of interaction before items get moved around - if (handEmpty && !armorEmpty) { - action = "took " + armorItem.getType(); - } else if (!handEmpty && armorEmpty) { - action = "added " + handItem.getType(); - } else if (!handEmpty) { - action = "swapped " + armorItem.getType() + " with " + handItem.getType(); - } else { - action = "interacted with"; - } - String message = ChatColor.GRAY + playerName + " " + action + " on an armor stand placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } - } - - //event handler for item frames - @EventHandler(ignoreCancelled = true) - public void onPlayerInteractEntity(PlayerInteractEntityEvent event) { - if (!(event.getRightClicked() instanceof ItemFrame frame)) return; - - Player player = event.getPlayer(); - int x = frame.getLocation().getBlockX(); - int y = frame.getLocation().getBlockY(); - int z = frame.getLocation().getBlockZ(); - String worldName = frame.getWorld().getName(); - if (isLocationIgnored(x, y, z, worldName)) { - event.setCancelled(true); - return; - } - String target = inspectBlock(frame.getLocation().getBlock(), player); - if (target != null) { - ItemStack itemInFrame = frame.getItem(); - ItemStack handItem = player.getInventory().getItemInMainHand(); - boolean handEmpty = handItem == null || handItem.getType() == Material.AIR; - boolean frameEmpty = itemInFrame == null || itemInFrame.getType() == Material.AIR; - String playerName = player.getName(); - - String action; - if (!handEmpty && frameEmpty) { - action = "added " + handItem.getType(); - } else { - return; - } - - String message = ChatColor.GRAY + playerName + " " + action + " an item to an item frame placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - - } - } - - // Breaking item frame item (uses a different event then placing an item) - @EventHandler(ignoreCancelled = true) - public void onItemFrameDamage(EntityDamageByEntityEvent event) { - if (!(event.getEntity() instanceof ItemFrame frame)) return; - if (!(event.getDamager() instanceof Player player)) return; - - ItemStack item = frame.getItem(); - String playerName = player.getName(); - - int x = frame.getLocation().getBlockX(); - int y = frame.getLocation().getBlockY(); - int z = frame.getLocation().getBlockZ(); - String worldName = frame.getWorld().getName(); - - if (isLocationIgnored(x, y, z, worldName)) { - event.setCancelled(true); - return; - } - - String target = inspectBlock(frame.getLocation().getBlock(), player); - if (target == null || target.equals(player.getName())) return; - - if (item.getType() == Material.AIR) return; - // At this point, the player is removing the item - String action = "took " + item.getType(); - String message = ChatColor.GRAY + playerName + " " + action + " from an item frame placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - } - - @EventHandler(ignoreCancelled = true) - public void onItemFrameBreak(HangingBreakByEntityEvent event) { - if (!(event.getEntity() instanceof ItemFrame frame)) return; - if (!(event.getRemover() instanceof Player player)) return; - - String playerName = player.getName(); - - Location loc = frame.getLocation(); - int x = loc.getBlockX(); - int y = loc.getBlockY(); - int z = loc.getBlockZ(); - String worldName = loc.getWorld().getName(); - - if (isLocationIgnored(x, y, z, worldName)) { - event.setCancelled(true); - return; - } - String target = inspectBlock(loc.getBlock(), player); - if (target == null || target.equals(player.getName())) return; - - String action = "broke an item frame"; - String message = ChatColor.GRAY + playerName + " " + action + " placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName); - - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - if (!command.getName().equalsIgnoreCase("griefalert")) return false; - if (args.length == 0) return false; - String sub = args[0].toLowerCase(); - if (sub.equals("ignore")) { - if (!sender.hasPermission("griefalert.staff.ignore")) { - sender.sendMessage(ChatColor.RED + "You do not have a permission."); - return true; - } - String world; - int x, y, z; - if (args.length == 4) { - // /griefalert ignore x y z (use sender's world) - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world."); - return true; - } - world = ((Player) sender).getWorld().getName(); - try { - x = Integer.parseInt(args[1]); - y = Integer.parseInt(args[2]); - z = Integer.parseInt(args[3]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be numbers."); - return true; - } - } else if (args.length == 5) { - // /griefalert ignore world x y z - world = args[1]; - try { - x = Integer.parseInt(args[2]); - y = Integer.parseInt(args[3]); - z = Integer.parseInt(args[4]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be numbers."); - return true; - } - } else { - sender.sendMessage(ChatColor.RED + "Usage: /griefalert ignore or /griefalert ignore "); - return true; - } - boolean result = addIgnoredLocation(x, y, z, world); - if (result) { - sender.sendMessage(ChatColor.GREEN + "Location ignored."); - } else { - sender.sendMessage(ChatColor.YELLOW + "Location was already ignored."); - } - return true; - } else if (sub.equals("unignore")) { - if (!sender.hasPermission("griefalert.staff.UnIgnore")) { - sender.sendMessage(ChatColor.RED + "You do not have permission."); - return true; - } - String world; - int x, y, z; - if (args.length == 4) { - // /griefalert unignore x y z (use sender's world) - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world."); - return true; - } - world = ((Player) sender).getWorld().getName(); - try { - x = Integer.parseInt(args[1]); - y = Integer.parseInt(args[2]); - z = Integer.parseInt(args[3]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be valid."); - return true; - } - } else if (args.length == 5) { - // /griefalert unignore world x y z - world = args[1]; - try { - x = Integer.parseInt(args[2]); - y = Integer.parseInt(args[3]); - z = Integer.parseInt(args[4]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be numbers."); - return true; - } - } else { - sender.sendMessage(ChatColor.RED + "Usage: /griefalert unignore or /griefalert unignore "); - return true; - } - boolean result = removeIgnoredLocation(x, y, z, world); - if (result) { - sender.sendMessage(ChatColor.GREEN + "Location unignored."); - } else { - sender.sendMessage(ChatColor.YELLOW + "Location was not ignored."); - } - return true; - } else if (sub.equals("check")) { - // /griefalert check or /griefalert check - String world; - int x, y, z; - if (args.length == 4) { - // /griefalert check x y z (use sender's world) - if (!(sender instanceof Player)) { - sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world."); - return true; - } - world = ((Player) sender).getWorld().getName(); - try { - x = Integer.parseInt(args[1]); - y = Integer.parseInt(args[2]); - z = Integer.parseInt(args[3]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be numbers."); - return true; - } - } else if (args.length == 5) { - // /griefalert check world x y z - world = args[1]; - try { - x = Integer.parseInt(args[2]); - y = Integer.parseInt(args[3]); - z = Integer.parseInt(args[4]); - } catch (NumberFormatException e) { - sender.sendMessage(ChatColor.RED + "Coordinates must be numbers."); - return true; - } - } else { - sender.sendMessage(ChatColor.RED + "Usage: /griefalert check (optional) "); - return true; - } - boolean ignored = isLocationIgnored(x, y, z, world); - if (ignored) { - sender.sendMessage(ChatColor.YELLOW + "GriefAlert is DISABLED at " + x + ", " + y + ", " + z + " in " + world + "."); - } else { - sender.sendMessage(ChatColor.GREEN + "GriefAlert is ENABLED at " + x + ", " + y + ", " + z + " in " + world + "."); - } - return true; - } - sender.sendMessage(ChatColor.RED + "Unknown subcommand. Use: ignore, unignore, check"); - return false; - } - - @Override - public java.util.List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - if (!command.getName().equalsIgnoreCase("griefalert")) return null; - java.util.List completions = new java.util.ArrayList<>(); - if (args.length == 1) { - java.util.List subs = java.util.Arrays.asList("ignore", "unignore", "check"); - for (String s : subs) { - if (s.startsWith(args[0].toLowerCase())) completions.add(s); - } - return completions; - } - if (args.length == 2 && (args[0].equalsIgnoreCase("ignore") || args[0].equalsIgnoreCase("unignore") || args[0].equalsIgnoreCase("check"))) { - // Suggest world names for the 2nd argument - for (org.bukkit.World world : org.bukkit.Bukkit.getWorlds()) { - completions.add(world.getName()); - } - return completions; - } - // Optionally, you could add number tab completion for coordinates, but it's not necessary - return null; - } - - // Sends the alert (or cancels it) - private void alert(String message, String playerName, String mapLink, String target, int x, int y, int z, String world) { - // Exclude trusted people - Player griefer = Bukkit.getPlayer(playerName); - if (griefer.hasPermission("griefalert.exclude") || griefer.hasPermission("griefalert.exclude." + target)) { - return; - } - // Spam limiter - String realAlertMessage = message; - String[] alert1 = null; - if (lastAlert != null) { - alert1 = lastAlert.split(" "); - } - String[] alert2 = message.split(" "); - if (alert1 != null) { - if (alert1[2].equals(alert2[2]) && alert1[5].equals(alert2[5]) && alert1[1].equals("broke") && alert2[1].equals("broke")) { - identicalAlerts += 1; - } else if (Arrays.equals(alert1, alert2)) { - identicalAlerts += 1; - } else { - identicalAlerts = 1; - } - } - if (identicalAlerts == 4) { - message = ChatColor.GRAY + "Same behavior continues."; - mapLink = null; - } - if (identicalAlerts > 4) { - return; - } - // Use direct location check - if (world != null && isLocationIgnored(x, y, z, world)) { - return; // Do not alert if location is ignored - } - // Send an event for external hooks - GriefAlertEvent griefalert_event; - if (MAP_LINK != null && !MAP_LINK.isEmpty() && mapLink != null) { - griefalert_event = new GriefAlertEvent(message + " (" + mapLink + ")"); - } else { - griefalert_event = new GriefAlertEvent(message); - } - getServer().getPluginManager().callEvent(griefalert_event); - // Notify staff ingame - for (Player player : Bukkit.getOnlinePlayers()) { - if (player.hasPermission("griefalert.notify")) { - player.sendMessage(message); - } - } - lastAlert = realAlertMessage; - } - - //pet alert(dog and cat only) - @EventHandler - public void onPetKill(EntityDeathEvent event) { - if (!(event.getEntity() instanceof Tameable tameable)) return; - if (!tameable.isTamed()) return; - - //checks if wolf or cat or not - if (!(event.getEntity() instanceof Wolf) && !(event.getEntity() instanceof Cat)) return; - - - AnimalTamer Owner = tameable.getOwner(); - if (Owner == null) return; - if (!(event.getEntity().getKiller() instanceof Player killer)) return; - //if owner kills nothing happens - if (killer.getUniqueId().equals(Owner.getUniqueId())) return; - - int x = event.getEntity().getLocation().getBlockX(); - int y = event.getEntity().getLocation().getBlockY(); - int z = event.getEntity().getLocation().getBlockZ(); - String worldName = event.getEntity().getWorld().getName(); - String pet = event.getEntity().getType().name(); - - String message = ChatColor.GRAY + killer.getName() + " killed" + " " + pet + " in " + Owner.getName() + "'s build at " + x + " " + y + " " + z + getHumanWorldName(worldName); - alert(message, killer.getName(), "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", Owner.getName(), x, y, z, worldName); - - } - - //farm animal handler - @EventHandler - public void onFarmAnimalDeath(EntityDeathEvent event) { - if (!(event.getEntity().getKiller() instanceof Player killer)) return; - List alertanimals = getConfig().getStringList("triggered-animals"); - String typeName = event.getEntityType().name(); - - - if (!alertanimals.contains(typeName)) return; - - Block blockBelow = event.getEntity().getLocation().subtract(0, 1, 0).getBlock(); - String animalOwner = inspectBlock(blockBelow, killer); - - if (animalOwner == null) return; - - if (animalOwner.equals(killer.getName())) return; - - - int x = event.getEntity().getLocation().getBlockX(); - int y = event.getEntity().getLocation().getBlockY(); - int z = event.getEntity().getLocation().getBlockZ(); - String worldName = event.getEntity().getWorld().getName(); - - - String message = ChatColor.GRAY + killer.getName() + " killed" + " " + typeName + "in " + animalOwner + "'s build at " + x + " " + y + " " + z + getHumanWorldName(worldName); - - alert(message, killer.getName(), "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", animalOwner, x, y, z, worldName); - - - } - - /*code i hope for copper waxing/unwaxing theres no proper onwax() or onUnWax() - so im kinda gonna try to just check a situation like, if ur holding an axe, left clicking a copper block - and its waxed, ill assume ur unwaxing, and therefor sending an alert - but some of this code was written at 1am so idk how and why im why and howing */ - - @EventHandler - public void onBlockClick(PlayerInteractEvent event) { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); - ItemStack item = event.getItem(); - - if (block == null || item == null) return; - - Material before = block.getType(); - - - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - String world = block.getWorld().getName(); - - - if (isLocationIgnored(x, y, z, world)) { - return; - } - - boolean isCopper = before.name().contains("COPPER"); - //if aint copper it can no copper and means no copper affected - if (!isCopper) return; - //for waxing logic might not even be needed - //boolean isHoneycomb = item.getType() == Material.HONEYCOMB; - - //for unwax logic and also might not be needed - //boolean isAxe = item.getType().toString().endsWith("_AXE"); - - String target = inspectBlock(block, player); - if (Objects.equals(target, player.getName())) return; - if (target == null) return; - - Bukkit.getScheduler().runTaskLater(this, () -> { - String action; - Material after = block.getType(); - - if (before == after) return; - - boolean wasWaxed = before.name().startsWith("WAXED_"); - boolean isWaxed = after.name().startsWith("WAXED_"); - - if (wasWaxed && !isWaxed) { - action = "Unwaxed"; - } else if (!wasWaxed && isWaxed) { - action = "Waxed"; - } else if (item != null && item.getType().name().endsWith("_AXE")) { - action = "undusted"; - - } else { - action = "error 404 check with kleedje30"; - } - - String message = ChatColor.GRAY + player.getName() + action + " Copper " + " at " + x + " " + y + " " + z + getHumanWorldName(world); - alert(message, player.getName(), "[Map Link](" + MAP_LINK + "/?worldname=" + world + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, world); - - }, 1L); - } - - //stripping logs - @EventHandler - public void onLogStrip(PlayerInteractEvent event) { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - - Player player = event.getPlayer(); - Block block = event.getClickedBlock(); - ItemStack item = event.getItem(); - - if (block == null || item == null) return; - - Material before = block.getType(); - - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); - String world = block.getWorld().getName(); - - boolean isWood = before.name().contains("LOG"); - - if (!isWood) return; - - - if (isLocationIgnored(x, y, z, world)) { - return; - } - - String target = inspectBlock(block, player); - if (target == null) return; - - if (target.equals(player.getName())) return; - - Bukkit.getScheduler().runTaskLater(this, () -> { - String action; - Material after = block.getType(); - if (before == after) return; - - if (!before.name().contains("STRIPPED") && after.name().contains("STRIPPED")) { - action = "Stripped"; - } else { - return; - } - - - String message = ChatColor.GRAY + player.getName() + action + " a(n) " + before + " at " + x + " " + y + " " + z + getHumanWorldName(world); - alert(message, player.getName(), "[Map Link](" + MAP_LINK + "/?worldname=" + world + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, world); - - - }, 1L); - } - - private CoreProtectAPI getCoreProtect() { - Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect"); - - if (!(plugin instanceof CoreProtect)) { - return null; - } - - return ((CoreProtect) plugin).getAPI(); - } -} \ No newline at end of file diff --git a/src/net/ardakaz/griefalert/GriefAlertEvent.java b/src/net/ardakaz/griefalert/GriefAlertEvent.java deleted file mode 100644 index a347edf..0000000 --- a/src/net/ardakaz/griefalert/GriefAlertEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -// "API" for other plugins - -package net.ardakaz.griefalert; - -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -public class GriefAlertEvent extends Event { - private static final HandlerList HANDLERS = new HandlerList(); - private String alert = ""; - - public GriefAlertEvent(String alert) { - this.alert = alert; - } - - public static HandlerList getHandlerList() { - return HANDLERS; - } - - @Override - public HandlerList getHandlers() { - return HANDLERS; - } - - public String getAlert() { - return this.alert; - } -} \ No newline at end of file