add-gradle project #1

Merged
Ardakaz merged 7 commits from add-gradle into main 2026-06-27 09:33:29 +00:00
4 changed files with 0 additions and 934 deletions
Showing only changes of commit 43c49c06ee - Show all commits

View File

@@ -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: ""

View File

@@ -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 <ignore|unignore|check>
permission: griefalert.staff
permission-message: You do not have permission to use this command.

View File

@@ -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<Material> EXCLUDED_BLOCKS;
private Set<InventoryType> 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<String[]> 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<String> excludedBlocks = getConfig().getStringList("excluded-blocks");
EXCLUDED_BLOCKS = excludedBlocks.stream().map(Material::valueOf).collect(Collectors.toSet());
List<String> 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 <world> <x> <y> <z> or /griefalert ignore <x> <y> <z>");
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 <world> <x> <y> <z> or /griefalert unignore <x> <y> <z>");
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 <world> <x> <y> <z> or /griefalert check <x> <y> <z>
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 <world>(optional) <x> <y> <z> ");
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<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
if (!command.getName().equalsIgnoreCase("griefalert")) return null;
java.util.List<String> completions = new java.util.ArrayList<>();
if (args.length == 1) {
java.util.List<String> 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<String> 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();
}
}

View File

@@ -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;
}
}