Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
110fa1c8cf | |||
79408d801b | |||
2f6b42fef4 | |||
0c21d1b645 | |||
4186a1dedf | |||
480e157e1a | |||
a340441fae | |||
c706c8d0f0 | |||
02d9dabda9 | |||
6769c8e57f | |||
11383965a8 |
9
LICENSE
Normal file
9
LICENSE
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 ArdakazMC
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
plugin.yml
27
plugin.yml
@ -1,13 +1,14 @@
|
|||||||
name: GriefAlert
|
name: GriefAlert
|
||||||
main: net.ardakaz.griefalert.GriefAlert
|
main: net.ardakaz.griefalert.GriefAlert
|
||||||
version: 0.3
|
version: 0.3.2
|
||||||
api-version: 1.21
|
api-version: 1.21
|
||||||
depends: [CoreProtect]
|
depends: [CoreProtect]
|
||||||
description: A simple grief alert plugin using the CoreProtect API.
|
softdepend: [DiscordSRV]
|
||||||
authors: [Ardakaz, kleedje30]
|
description: A simple grief alert plugin using the CoreProtect API.
|
||||||
commands:
|
authors: [Ardakaz, kleedje30]
|
||||||
griefalert:
|
commands:
|
||||||
description: GriefAlert staff commands
|
griefalert:
|
||||||
usage: /griefalert <ignore|unignore|check>
|
description: GriefAlert staff commands
|
||||||
permission: griefalert.staff
|
usage: /griefalert <ignore|unignore|check>
|
||||||
permission-message: You do not have permission to use this command.
|
permission: griefalert.staff
|
||||||
|
permission-message: You do not have permission to use this command.
|
@ -1,491 +1,491 @@
|
|||||||
package net.ardakaz.griefalert;
|
package net.ardakaz.griefalert;
|
||||||
|
|
||||||
import net.coreprotect.CoreProtect;
|
import net.coreprotect.CoreProtect;
|
||||||
import net.coreprotect.CoreProtectAPI;
|
import net.coreprotect.CoreProtectAPI;
|
||||||
import net.coreprotect.CoreProtectAPI.ParseResult;
|
import net.coreprotect.CoreProtectAPI.ParseResult;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabCompleter;
|
import org.bukkit.command.TabCompleter;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
import org.bukkit.event.inventory.InventoryAction;
|
import org.bukkit.event.inventory.InventoryAction;
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||||
import org.bukkit.event.inventory.InventoryType;
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class GriefAlert extends JavaPlugin implements Listener, TabCompleter {
|
public class GriefAlert extends JavaPlugin implements Listener, TabCompleter {
|
||||||
|
|
||||||
private static CoreProtectAPI coreProtectAPI;
|
private static CoreProtectAPI coreProtectAPI;
|
||||||
private Integer identicalAlerts = 1;
|
private Integer identicalAlerts = 1;
|
||||||
private String lastAlert;
|
private String lastAlert;
|
||||||
|
|
||||||
private Set<Material> EXCLUDED_BLOCKS;
|
private Set<Material> EXCLUDED_BLOCKS;
|
||||||
private Set<InventoryType> VALID_CONTAINERS;
|
private Set<InventoryType> VALID_CONTAINERS;
|
||||||
private String MAP_LINK;
|
private String MAP_LINK;
|
||||||
private Boolean ALLOW_STEALING;
|
private Boolean ALLOW_STEALING;
|
||||||
|
|
||||||
private Connection connection;
|
private Connection connection;
|
||||||
private final String DB_FILE = "ignored_locations.db";
|
private final String DB_FILE = "ignored_locations.db";
|
||||||
|
|
||||||
// Init GriefAlert
|
// Init GriefAlert
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
|
||||||
coreProtectAPI = getCoreProtect();
|
coreProtectAPI = getCoreProtect();
|
||||||
if (coreProtectAPI == null) {
|
if (coreProtectAPI == null) {
|
||||||
getLogger().severe("CoreProtect not found! Disabling plugin.");
|
getLogger().severe("CoreProtect not found! Disabling plugin.");
|
||||||
getServer().getPluginManager().disablePlugin(this);
|
getServer().getPluginManager().disablePlugin(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getServer().getPluginManager().registerEvents(this, this);
|
getServer().getPluginManager().registerEvents(this, this);
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
saveDefaultConfig();
|
saveDefaultConfig();
|
||||||
List<String> excludedBlocks = getConfig().getStringList("excluded-blocks");
|
List<String> excludedBlocks = getConfig().getStringList("excluded-blocks");
|
||||||
EXCLUDED_BLOCKS = excludedBlocks.stream().map(Material::valueOf).collect(Collectors.toSet());
|
EXCLUDED_BLOCKS = excludedBlocks.stream().map(Material::valueOf).collect(Collectors.toSet());
|
||||||
List<String> validContainers = getConfig().getStringList("valid-containers");
|
List<String> validContainers = getConfig().getStringList("valid-containers");
|
||||||
VALID_CONTAINERS = validContainers.stream().map(InventoryType::valueOf).collect(Collectors.toSet());
|
VALID_CONTAINERS = validContainers.stream().map(InventoryType::valueOf).collect(Collectors.toSet());
|
||||||
MAP_LINK = getConfig().getString("map-link");
|
MAP_LINK = getConfig().getString("map-link");
|
||||||
ALLOW_STEALING = getConfig().getBoolean("allow-stealing");
|
ALLOW_STEALING = getConfig().getBoolean("allow-stealing");
|
||||||
|
|
||||||
setupDatabase();
|
setupDatabase();
|
||||||
|
|
||||||
getCommand("griefalert").setTabCompleter(this);
|
getCommand("griefalert").setTabCompleter(this);
|
||||||
|
|
||||||
getLogger().info("GriefAlert has been enabled.");
|
getLogger().info("GriefAlert has been enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
getLogger().info("GriefAlert has been disabled.");
|
getLogger().info("GriefAlert has been disabled.");
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
try { connection.close(); } catch (SQLException ignored) {}
|
try { connection.close(); } catch (SQLException ignored) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupDatabase() {
|
private void setupDatabase() {
|
||||||
try {
|
try {
|
||||||
connection = DriverManager.getConnection("jdbc:sqlite:" + getDataFolder().getAbsolutePath() + "/" + DB_FILE);
|
connection = DriverManager.getConnection("jdbc:sqlite:" + getDataFolder().getAbsolutePath() + "/" + DB_FILE);
|
||||||
Statement stmt = connection.createStatement();
|
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.executeUpdate("CREATE TABLE IF NOT EXISTS ignored_locations (x INTEGER, y INTEGER, z INTEGER, world TEXT, PRIMARY KEY (x, y, z, world))");
|
||||||
stmt.close();
|
stmt.close();
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
getLogger().severe("Could not set up SQLite database: " + e.getMessage());
|
getLogger().severe("Could not set up SQLite database: " + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isLocationIgnored(int x, int y, int z, String world) {
|
private boolean isLocationIgnored(int x, int y, int z, String world) {
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement("SELECT 1 FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?");
|
PreparedStatement ps = connection.prepareStatement("SELECT 1 FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?");
|
||||||
ps.setInt(1, x);
|
ps.setInt(1, x);
|
||||||
ps.setInt(2, y);
|
ps.setInt(2, y);
|
||||||
ps.setInt(3, z);
|
ps.setInt(3, z);
|
||||||
ps.setString(4, world);
|
ps.setString(4, world);
|
||||||
ResultSet rs = ps.executeQuery();
|
ResultSet rs = ps.executeQuery();
|
||||||
boolean exists = rs.next();
|
boolean exists = rs.next();
|
||||||
rs.close();
|
rs.close();
|
||||||
ps.close();
|
ps.close();
|
||||||
return exists;
|
return exists;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
getLogger().warning("DB error: " + e.getMessage());
|
getLogger().warning("DB error: " + e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean addIgnoredLocation(int x, int y, int z, String world) {
|
private boolean addIgnoredLocation(int x, int y, int z, String world) {
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement("INSERT OR IGNORE INTO ignored_locations (x, y, z, world) VALUES (?, ?, ?, ?)");
|
PreparedStatement ps = connection.prepareStatement("INSERT OR IGNORE INTO ignored_locations (x, y, z, world) VALUES (?, ?, ?, ?)");
|
||||||
ps.setInt(1, x);
|
ps.setInt(1, x);
|
||||||
ps.setInt(2, y);
|
ps.setInt(2, y);
|
||||||
ps.setInt(3, z);
|
ps.setInt(3, z);
|
||||||
ps.setString(4, world);
|
ps.setString(4, world);
|
||||||
int updated = ps.executeUpdate();
|
int updated = ps.executeUpdate();
|
||||||
ps.close();
|
ps.close();
|
||||||
return updated > 0;
|
return updated > 0;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
getLogger().warning("DB error: " + e.getMessage());
|
getLogger().warning("DB error: " + e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean removeIgnoredLocation(int x, int y, int z, String world) {
|
private boolean removeIgnoredLocation(int x, int y, int z, String world) {
|
||||||
try {
|
try {
|
||||||
PreparedStatement ps = connection.prepareStatement("DELETE FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?");
|
PreparedStatement ps = connection.prepareStatement("DELETE FROM ignored_locations WHERE x=? AND y=? AND z=? AND world=?");
|
||||||
ps.setInt(1, x);
|
ps.setInt(1, x);
|
||||||
ps.setInt(2, y);
|
ps.setInt(2, y);
|
||||||
ps.setInt(3, z);
|
ps.setInt(3, z);
|
||||||
ps.setString(4, world);
|
ps.setString(4, world);
|
||||||
int updated = ps.executeUpdate();
|
int updated = ps.executeUpdate();
|
||||||
ps.close();
|
ps.close();
|
||||||
return updated > 0;
|
return updated > 0;
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
getLogger().warning("DB error: " + e.getMessage());
|
getLogger().warning("DB error: " + e.getMessage());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler (ignoreCancelled = true)
|
@EventHandler (ignoreCancelled = true)
|
||||||
// Block break alerts
|
// Block break alerts
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
// Exclusion list
|
// Exclusion list
|
||||||
if (EXCLUDED_BLOCKS.contains(event.getBlock().getType())) {
|
if (EXCLUDED_BLOCKS.contains(event.getBlock().getType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event parser
|
// Event parser
|
||||||
String playerName = event.getPlayer().getName();
|
String playerName = event.getPlayer().getName();
|
||||||
String blockType = event.getBlock().getType().toString();
|
String blockType = event.getBlock().getType().toString();
|
||||||
int x = event.getBlock().getX();
|
int x = event.getBlock().getX();
|
||||||
int y = event.getBlock().getY();
|
int y = event.getBlock().getY();
|
||||||
int z = event.getBlock().getZ();
|
int z = event.getBlock().getZ();
|
||||||
String worldName = event.getBlock().getWorld().getName();
|
String worldName = event.getBlock().getWorld().getName();
|
||||||
|
|
||||||
// Check if grief
|
// Check if grief
|
||||||
String target = inspectBlock(event.getBlock(), event.getPlayer());
|
String target = inspectBlock(event.getBlock(), event.getPlayer());
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
String message = ChatColor.GRAY + playerName + " broke " + blockType + " placed by " + target + " at " + x + " " + y + " " + z + getHumanWorldName(worldName);
|
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);
|
alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stealing alerts
|
// Stealing alerts
|
||||||
@EventHandler (ignoreCancelled = true)
|
@EventHandler (ignoreCancelled = true)
|
||||||
public void onInventoryClick(InventoryClickEvent event) {
|
public void onInventoryClick(InventoryClickEvent event) {
|
||||||
if (ALLOW_STEALING) {
|
if (ALLOW_STEALING) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
boolean stealing;
|
boolean stealing;
|
||||||
|
|
||||||
// Event parser for inv
|
// Event parser for inv
|
||||||
if (!(event.getWhoClicked() instanceof Player)) return;
|
if (!(event.getWhoClicked() instanceof Player)) return;
|
||||||
Player player = (Player) event.getWhoClicked();
|
Player player = (Player) event.getWhoClicked();
|
||||||
Inventory inventory = event.getInventory();
|
Inventory inventory = event.getInventory();
|
||||||
Inventory clickedInventory = event.getClickedInventory();
|
Inventory clickedInventory = event.getClickedInventory();
|
||||||
ItemStack item = event.getCurrentItem();
|
ItemStack item = event.getCurrentItem();
|
||||||
|
|
||||||
if (item == null || inventory.getLocation() == null || item.getType() == Material.AIR) {
|
if (item == null || inventory.getLocation() == null || item.getType() == Material.AIR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclusion list
|
// Exclusion list
|
||||||
if (!VALID_CONTAINERS.contains(inventory.getType())) {
|
if (!VALID_CONTAINERS.contains(inventory.getType())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inv actions (needs fixing)
|
// Inv actions (needs fixing)
|
||||||
InventoryAction action = event.getAction();
|
InventoryAction action = event.getAction();
|
||||||
if ((action == InventoryAction.PICKUP_ALL || action == InventoryAction.PICKUP_HALF ||
|
if ((action == InventoryAction.PICKUP_ALL || action == InventoryAction.PICKUP_HALF ||
|
||||||
action == InventoryAction.PICKUP_ONE || action == InventoryAction.PICKUP_SOME ||
|
action == InventoryAction.PICKUP_ONE || action == InventoryAction.PICKUP_SOME ||
|
||||||
action == InventoryAction.MOVE_TO_OTHER_INVENTORY) && clickedInventory == inventory) {
|
action == InventoryAction.MOVE_TO_OTHER_INVENTORY) && clickedInventory == inventory) {
|
||||||
stealing = true;
|
stealing = true;
|
||||||
} else if (action == InventoryAction.PLACE_ALL || action == InventoryAction.PLACE_SOME ||
|
} else if (action == InventoryAction.PLACE_ALL || action == InventoryAction.PLACE_SOME ||
|
||||||
action == InventoryAction.PLACE_ONE || (action == InventoryAction.MOVE_TO_OTHER_INVENTORY && clickedInventory != inventory)) {
|
action == InventoryAction.PLACE_ONE || (action == InventoryAction.MOVE_TO_OTHER_INVENTORY && clickedInventory != inventory)) {
|
||||||
stealing = false;
|
stealing = false;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event parser for container + check if grief
|
// Event parser for container + check if grief
|
||||||
String target = inspectBlock(inventory.getLocation().getBlock(), player);
|
String target = inspectBlock(inventory.getLocation().getBlock(), player);
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
String playerName = player.getName();
|
String playerName = player.getName();
|
||||||
String itemName = item.getType().toString();
|
String itemName = item.getType().toString();
|
||||||
int amount = item.getAmount();
|
int amount = item.getAmount();
|
||||||
int x = inventory.getLocation().getBlockX();
|
int x = inventory.getLocation().getBlockX();
|
||||||
int y = inventory.getLocation().getBlockY();
|
int y = inventory.getLocation().getBlockY();
|
||||||
int z = inventory.getLocation().getBlockZ();
|
int z = inventory.getLocation().getBlockZ();
|
||||||
String worldName = inventory.getLocation().getWorld().getName();
|
String worldName = inventory.getLocation().getWorld().getName();
|
||||||
if (stealing) {
|
if (stealing) {
|
||||||
String message = ChatColor.GRAY + playerName + " took " + amount + " " + itemName + " from " + target + "'s container at " + x + " " + y + " " + z + getHumanWorldName(worldName);
|
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);
|
alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName);
|
||||||
} else {
|
} else {
|
||||||
String message = ChatColor.GRAY + playerName + " put " + amount + " " + itemName + " into " + target + "'s container at " + x + " " + y + " " + z + getHumanWorldName(worldName);
|
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);
|
alert(message, playerName, "[Map Link](" + MAP_LINK + "/?worldname=" + worldName + "&zoom=7&x=" + x + "&y=" + y + "&z=" + z + ")", target, x, y, z, worldName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||||
if (!command.getName().equalsIgnoreCase("griefalert")) return false;
|
if (!command.getName().equalsIgnoreCase("griefalert")) return false;
|
||||||
if (args.length == 0) return false;
|
if (args.length == 0) return false;
|
||||||
String sub = args[0].toLowerCase();
|
String sub = args[0].toLowerCase();
|
||||||
if (sub.equals("ignore")) {
|
if (sub.equals("ignore")) {
|
||||||
if (!sender.hasPermission("griefalert.staff.ignore")) {
|
if (!sender.hasPermission("griefalert.staff.ignore")) {
|
||||||
sender.sendMessage(ChatColor.RED + "You do not have permission.");
|
sender.sendMessage(ChatColor.RED + "You do not have permission.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String world;
|
String world;
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
if (args.length == 4) {
|
if (args.length == 4) {
|
||||||
// /griefalert ignore x y z (use sender's world)
|
// /griefalert ignore x y z (use sender's world)
|
||||||
if (!(sender instanceof Player)) {
|
if (!(sender instanceof Player)) {
|
||||||
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
world = ((Player)sender).getWorld().getName();
|
world = ((Player)sender).getWorld().getName();
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[1]);
|
x = Integer.parseInt(args[1]);
|
||||||
y = Integer.parseInt(args[2]);
|
y = Integer.parseInt(args[2]);
|
||||||
z = Integer.parseInt(args[3]);
|
z = Integer.parseInt(args[3]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (args.length == 5) {
|
} else if (args.length == 5) {
|
||||||
// /griefalert ignore world x y z
|
// /griefalert ignore world x y z
|
||||||
world = args[1];
|
world = args[1];
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[2]);
|
x = Integer.parseInt(args[2]);
|
||||||
y = Integer.parseInt(args[3]);
|
y = Integer.parseInt(args[3]);
|
||||||
z = Integer.parseInt(args[4]);
|
z = Integer.parseInt(args[4]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.RED + "Usage: /griefalert ignore <world> <x> <y> <z> or /griefalert ignore <x> <y> <z>");
|
sender.sendMessage(ChatColor.RED + "Usage: /griefalert ignore <world> <x> <y> <z> or /griefalert ignore <x> <y> <z>");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean result = addIgnoredLocation(x, y, z, world);
|
boolean result = addIgnoredLocation(x, y, z, world);
|
||||||
if (result) {
|
if (result) {
|
||||||
sender.sendMessage(ChatColor.GREEN + "Location ignored.");
|
sender.sendMessage(ChatColor.GREEN + "Location ignored.");
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.YELLOW + "Location was already ignored.");
|
sender.sendMessage(ChatColor.YELLOW + "Location was already ignored.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (sub.equals("unignore")) {
|
} else if (sub.equals("unignore")) {
|
||||||
if (!sender.hasPermission("griefalert.staff.UnIgnore")) {
|
if (!sender.hasPermission("griefalert.staff.UnIgnore")) {
|
||||||
sender.sendMessage(ChatColor.RED + "You do not have permission.");
|
sender.sendMessage(ChatColor.RED + "You do not have permission.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
String world;
|
String world;
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
if (args.length == 4) {
|
if (args.length == 4) {
|
||||||
// /griefalert unignore x y z (use sender's world)
|
// /griefalert unignore x y z (use sender's world)
|
||||||
if (!(sender instanceof Player)) {
|
if (!(sender instanceof Player)) {
|
||||||
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
world = ((Player)sender).getWorld().getName();
|
world = ((Player)sender).getWorld().getName();
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[1]);
|
x = Integer.parseInt(args[1]);
|
||||||
y = Integer.parseInt(args[2]);
|
y = Integer.parseInt(args[2]);
|
||||||
z = Integer.parseInt(args[3]);
|
z = Integer.parseInt(args[3]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be valid.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be valid.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (args.length == 5) {
|
} else if (args.length == 5) {
|
||||||
// /griefalert unignore world x y z
|
// /griefalert unignore world x y z
|
||||||
world = args[1];
|
world = args[1];
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[2]);
|
x = Integer.parseInt(args[2]);
|
||||||
y = Integer.parseInt(args[3]);
|
y = Integer.parseInt(args[3]);
|
||||||
z = Integer.parseInt(args[4]);
|
z = Integer.parseInt(args[4]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.RED + "Usage: /griefalert unignore <world> <x> <y> <z> or /griefalert unignore <x> <y> <z>");
|
sender.sendMessage(ChatColor.RED + "Usage: /griefalert unignore <world> <x> <y> <z> or /griefalert unignore <x> <y> <z>");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean result = removeIgnoredLocation(x, y, z, world);
|
boolean result = removeIgnoredLocation(x, y, z, world);
|
||||||
if (result) {
|
if (result) {
|
||||||
sender.sendMessage(ChatColor.GREEN + "Location unignored.");
|
sender.sendMessage(ChatColor.GREEN + "Location unignored.");
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.YELLOW + "Location was not ignored.");
|
sender.sendMessage(ChatColor.YELLOW + "Location was not ignored.");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (sub.equals("check")) {
|
} else if (sub.equals("check")) {
|
||||||
// /griefalert check <world> <x> <y> <z> or /griefalert check <x> <y> <z>
|
// /griefalert check <world> <x> <y> <z> or /griefalert check <x> <y> <z>
|
||||||
String world;
|
String world;
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
if (args.length == 4) {
|
if (args.length == 4) {
|
||||||
// /griefalert check x y z (use sender's world)
|
// /griefalert check x y z (use sender's world)
|
||||||
if (!(sender instanceof Player)) {
|
if (!(sender instanceof Player)) {
|
||||||
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
sender.sendMessage(ChatColor.RED + "Only players can use this command without specifying a world.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
world = ((Player)sender).getWorld().getName();
|
world = ((Player)sender).getWorld().getName();
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[1]);
|
x = Integer.parseInt(args[1]);
|
||||||
y = Integer.parseInt(args[2]);
|
y = Integer.parseInt(args[2]);
|
||||||
z = Integer.parseInt(args[3]);
|
z = Integer.parseInt(args[3]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (args.length == 5) {
|
} else if (args.length == 5) {
|
||||||
// /griefalert check world x y z
|
// /griefalert check world x y z
|
||||||
world = args[1];
|
world = args[1];
|
||||||
try {
|
try {
|
||||||
x = Integer.parseInt(args[2]);
|
x = Integer.parseInt(args[2]);
|
||||||
y = Integer.parseInt(args[3]);
|
y = Integer.parseInt(args[3]);
|
||||||
z = Integer.parseInt(args[4]);
|
z = Integer.parseInt(args[4]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
sender.sendMessage(ChatColor.RED + "Coordinates must be numbers.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.RED + "Usage: /griefalert check <world>(optional) <x> <y> <z> ");
|
sender.sendMessage(ChatColor.RED + "Usage: /griefalert check <world>(optional) <x> <y> <z> ");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean ignored = isLocationIgnored(x, y, z, world);
|
boolean ignored = isLocationIgnored(x, y, z, world);
|
||||||
if (ignored) {
|
if (ignored) {
|
||||||
sender.sendMessage(ChatColor.YELLOW + "GriefAlert is DISABLED at " + x + ", " + y + ", " + z + " in " + world + ".");
|
sender.sendMessage(ChatColor.YELLOW + "GriefAlert is DISABLED at " + x + ", " + y + ", " + z + " in " + world + ".");
|
||||||
} else {
|
} else {
|
||||||
sender.sendMessage(ChatColor.GREEN + "GriefAlert is ENABLED at " + x + ", " + y + ", " + z + " in " + world + ".");
|
sender.sendMessage(ChatColor.GREEN + "GriefAlert is ENABLED at " + x + ", " + y + ", " + z + " in " + world + ".");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
sender.sendMessage(ChatColor.RED + "Unknown subcommand. Use: ignore, unignore, check");
|
sender.sendMessage(ChatColor.RED + "Unknown subcommand. Use: ignore, unignore, check");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public java.util.List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
public java.util.List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||||
if (!command.getName().equalsIgnoreCase("griefalert")) return null;
|
if (!command.getName().equalsIgnoreCase("griefalert")) return null;
|
||||||
java.util.List<String> completions = new java.util.ArrayList<>();
|
java.util.List<String> completions = new java.util.ArrayList<>();
|
||||||
if (args.length == 1) {
|
if (args.length == 1) {
|
||||||
java.util.List<String> subs = java.util.Arrays.asList("ignore", "unignore", "check");
|
java.util.List<String> subs = java.util.Arrays.asList("ignore", "unignore", "check");
|
||||||
for (String s : subs) {
|
for (String s : subs) {
|
||||||
if (s.startsWith(args[0].toLowerCase())) completions.add(s);
|
if (s.startsWith(args[0].toLowerCase())) completions.add(s);
|
||||||
}
|
}
|
||||||
return completions;
|
return completions;
|
||||||
}
|
}
|
||||||
if (args.length == 2 && (args[0].equalsIgnoreCase("ignore") || args[0].equalsIgnoreCase("unignore") || args[0].equalsIgnoreCase("check"))) {
|
if (args.length == 2 && (args[0].equalsIgnoreCase("ignore") || args[0].equalsIgnoreCase("unignore") || args[0].equalsIgnoreCase("check"))) {
|
||||||
// Suggest world names for the 2nd argument
|
// Suggest world names for the 2nd argument
|
||||||
for (org.bukkit.World world : org.bukkit.Bukkit.getWorlds()) {
|
for (org.bukkit.World world : org.bukkit.Bukkit.getWorlds()) {
|
||||||
completions.add(world.getName());
|
completions.add(world.getName());
|
||||||
}
|
}
|
||||||
return completions;
|
return completions;
|
||||||
}
|
}
|
||||||
// Optionally, you could add number tab completion for coordinates, but it's not necessary
|
// Optionally, you could add number tab completion for coordinates, but it's not necessary
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the alert (or cancels it)
|
// 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) {
|
private void alert(String message, String playerName, String mapLink, String target, int x, int y, int z, String world) {
|
||||||
// Exclude trusted people
|
// Exclude trusted people
|
||||||
Player griefer = Bukkit.getPlayer(playerName);
|
Player griefer = Bukkit.getPlayer(playerName);
|
||||||
if (griefer.hasPermission("griefalert.exclude") || griefer.hasPermission("griefalert.exclude." + target)) {
|
if (griefer.hasPermission("griefalert.exclude") || griefer.hasPermission("griefalert.exclude." + target)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Spam limiter
|
// Spam limiter
|
||||||
String realAlertMessage = message;
|
String realAlertMessage = message;
|
||||||
String[] alert1 = null;
|
String[] alert1 = null;
|
||||||
if (lastAlert != null) {
|
if (lastAlert != null) {
|
||||||
alert1 = lastAlert.split(" ");
|
alert1 = lastAlert.split(" ");
|
||||||
}
|
}
|
||||||
String[] alert2 = message.split(" ");
|
String[] alert2 = message.split(" ");
|
||||||
if (alert1 != null) {
|
if (alert1 != null) {
|
||||||
if (alert1[2].equals(alert2[2]) && alert1[5].equals(alert2[5]) && alert1[1].equals("broke") && alert2[1].equals("broke")) {
|
if (alert1[2].equals(alert2[2]) && alert1[5].equals(alert2[5]) && alert1[1].equals("broke") && alert2[1].equals("broke")) {
|
||||||
identicalAlerts += 1;
|
identicalAlerts += 1;
|
||||||
} else if (Arrays.equals(alert1, alert2)) {
|
} else if (Arrays.equals(alert1, alert2)) {
|
||||||
identicalAlerts += 1;
|
identicalAlerts += 1;
|
||||||
} else {
|
} else {
|
||||||
identicalAlerts = 1;
|
identicalAlerts = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (identicalAlerts == 4) {
|
if (identicalAlerts == 4) {
|
||||||
message = ChatColor.GRAY + "Same behavior continues.";
|
message = ChatColor.GRAY + "Same behavior continues.";
|
||||||
mapLink = null;
|
mapLink = null;
|
||||||
}
|
}
|
||||||
if (identicalAlerts > 4) {
|
if (identicalAlerts > 4) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Use direct location check
|
// Use direct location check
|
||||||
if (world != null && isLocationIgnored(x, y, z, world)) {
|
if (world != null && isLocationIgnored(x, y, z, world)) {
|
||||||
return; // Do not alert if location is ignored
|
return; // Do not alert if location is ignored
|
||||||
}
|
}
|
||||||
// Send an event for external hooks
|
// Send an event for external hooks
|
||||||
GriefAlertEvent griefalert_event;
|
GriefAlertEvent griefalert_event;
|
||||||
if (mapLink != null && !mapLink.isEmpty()) {
|
if (MAP_LINK != null && !MAP_LINK.isEmpty()) {
|
||||||
griefalert_event = new GriefAlertEvent(message + " (" + mapLink + ")");
|
griefalert_event = new GriefAlertEvent(message + " (" + mapLink + ")");
|
||||||
} else {
|
} else {
|
||||||
griefalert_event = new GriefAlertEvent(message);
|
griefalert_event = new GriefAlertEvent(message);
|
||||||
}
|
}
|
||||||
getServer().getPluginManager().callEvent(griefalert_event);
|
getServer().getPluginManager().callEvent(griefalert_event);
|
||||||
// Notify staff ingame
|
// Notify staff ingame
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
if (player.hasPermission("griefalert.notify")) {
|
if (player.hasPermission("griefalert.notify")) {
|
||||||
player.sendMessage(message);
|
player.sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastAlert = realAlertMessage;
|
lastAlert = realAlertMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block inspector: only the most recent placement counts for ownership.
|
// Block inspector: only the most recent placement counts for ownership.
|
||||||
private static String inspectBlock(Block block, Player player) {
|
private static String inspectBlock(Block block, Player player) {
|
||||||
List<String[]> lookup = coreProtectAPI.blockLookup(block, 50000000);
|
List<String[]> lookup = coreProtectAPI.blockLookup(block, 50000000);
|
||||||
if (lookup == null || lookup.size() == 0) {
|
if (lookup == null || lookup.size() == 0) {
|
||||||
// Natural block
|
// Natural block
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Find the most recent placement event only
|
// Find the most recent placement event only
|
||||||
for (String[] result : lookup) {
|
for (String[] result : lookup) {
|
||||||
ParseResult parseResult = coreProtectAPI.parseResult(result);
|
ParseResult parseResult = coreProtectAPI.parseResult(result);
|
||||||
if (parseResult == null) continue;
|
if (parseResult == null) continue;
|
||||||
if (parseResult.getActionId() == 1 && !parseResult.isRolledBack() && !parseResult.getPlayer().startsWith("#")) {
|
if (parseResult.getActionId() == 1 && !parseResult.isRolledBack() && !parseResult.getPlayer().startsWith("#")) {
|
||||||
// If the current player placed it, it's theirs (no alert)
|
// If the current player placed it, it's theirs (no alert)
|
||||||
if (parseResult.getPlayer().equals(player.getName())) {
|
if (parseResult.getPlayer().equals(player.getName())) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return parseResult.getPlayer();
|
return parseResult.getPlayer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If we see a break before a placement, stop (block is gone)
|
// If we see a break before a placement, stop (block is gone)
|
||||||
if (parseResult.getActionId() == 0) {
|
if (parseResult.getActionId() == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// No valid placement found
|
// No valid placement found
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getHumanWorldName(String worldName) {
|
private static String getHumanWorldName(String worldName) {
|
||||||
String world = "";
|
String world = "";
|
||||||
|
|
||||||
if (worldName.endsWith("_nether")) {
|
if (worldName.endsWith("_nether")) {
|
||||||
world = " in the Nether";
|
world = " in the Nether";
|
||||||
}
|
}
|
||||||
else if (worldName.endsWith("_the_end")) {
|
else if (worldName.endsWith("_the_end")) {
|
||||||
world = " in the End";
|
world = " in the End";
|
||||||
}
|
}
|
||||||
|
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
private CoreProtectAPI getCoreProtect() {
|
private CoreProtectAPI getCoreProtect() {
|
||||||
Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect");
|
Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect");
|
||||||
|
|
||||||
if (plugin == null || !(plugin instanceof CoreProtect)) {
|
if (plugin == null || !(plugin instanceof CoreProtect)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ((CoreProtect) plugin).getAPI();
|
return ((CoreProtect) plugin).getAPI();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,28 +1,34 @@
|
|||||||
// "API" for other plugins
|
// "API" for other plugins
|
||||||
|
|
||||||
package net.ardakaz.griefalert;
|
package net.ardakaz.griefalert;
|
||||||
|
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
public class GriefAlertEvent extends Event {
|
|
||||||
private static final HandlerList HANDLERS = new HandlerList();
|
public class GriefAlertEvent extends Event {
|
||||||
private String alert = "";
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
private String alert = "";
|
||||||
public GriefAlertEvent(String alert) {
|
|
||||||
this.alert = alert;
|
public GriefAlertEvent(String alert) {
|
||||||
}
|
this.alert = alert;
|
||||||
|
|
||||||
public static HandlerList getHandlerList() {
|
// Discord hook for 1.21.5
|
||||||
return HANDLERS;
|
if (Bukkit.getServer().getPluginManager().getPlugin("DiscordSRV") != null) {
|
||||||
}
|
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "discord broadcast #grief-alerts " + this.getAlert());
|
||||||
|
}
|
||||||
@Override
|
}
|
||||||
public HandlerList getHandlers() {
|
|
||||||
return HANDLERS;
|
public static HandlerList getHandlerList() {
|
||||||
}
|
return HANDLERS;
|
||||||
|
}
|
||||||
public String getAlert() {
|
|
||||||
return this.alert;
|
@Override
|
||||||
}
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAlert() {
|
||||||
|
return this.alert;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user