summaryrefslogtreecommitdiff
path: root/src/main/java/dev/deeve/containeraudit
diff options
context:
space:
mode:
authorFlarp <flurpdadurp@gmail.com>2023-12-28 16:54:23 -0500
committerFlarp <flurpdadurp@gmail.com>2023-12-28 16:54:23 -0500
commitecfecaf19410e91437764cf42e9a61276ae6a09b (patch)
treee928a3d8b8d1f0e63907e69df6544dec6dbbcdfc /src/main/java/dev/deeve/containeraudit
downloadcontainer-audit-ecfecaf19410e91437764cf42e9a61276ae6a09b.tar.gz
First commit
Diffstat (limited to 'src/main/java/dev/deeve/containeraudit')
-rw-r--r--src/main/java/dev/deeve/containeraudit/ChestEvent.java14
-rw-r--r--src/main/java/dev/deeve/containeraudit/ChestListener.java95
-rw-r--r--src/main/java/dev/deeve/containeraudit/Database.java125
-rw-r--r--src/main/java/dev/deeve/containeraudit/Plugin.java44
4 files changed, 278 insertions, 0 deletions
diff --git a/src/main/java/dev/deeve/containeraudit/ChestEvent.java b/src/main/java/dev/deeve/containeraudit/ChestEvent.java
new file mode 100644
index 0000000..a59e0ea
--- /dev/null
+++ b/src/main/java/dev/deeve/containeraudit/ChestEvent.java
@@ -0,0 +1,14 @@
+package dev.deeve.containeraudit;
+
+import java.time.LocalDateTime;
+
+public class ChestEvent {
+ private int count;
+ private String block;
+ private int x;
+ private int y;
+ private int z;
+ private String player;
+ private String type;
+ private LocalDateTime timestamp;
+}
diff --git a/src/main/java/dev/deeve/containeraudit/ChestListener.java b/src/main/java/dev/deeve/containeraudit/ChestListener.java
new file mode 100644
index 0000000..bc93b9c
--- /dev/null
+++ b/src/main/java/dev/deeve/containeraudit/ChestListener.java
@@ -0,0 +1,95 @@
+package dev.deeve.containeraudit;
+
+import java.util.List;
+
+import org.bukkit.Bukkit;
+import org.bukkit.Location;
+import org.bukkit.Material;
+import org.bukkit.block.Block;
+import org.bukkit.entity.HumanEntity;
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import org.bukkit.event.block.BlockBreakEvent;
+import org.bukkit.event.block.BlockPlaceEvent;
+import org.bukkit.event.inventory.InventoryAction;
+import org.bukkit.event.inventory.InventoryClickEvent;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.ItemStack;
+
+
+public class ChestListener implements Listener {
+
+ public static List<String> ignore;
+
+ public ChestListener(List<String> ignore) {
+ ChestListener.ignore = ignore;
+ }
+
+ @EventHandler
+ public final void onInventoryClick(InventoryClickEvent event) {
+ String playerName = event.getWhoClicked().getName();
+ Inventory inventory = event.getClickedInventory();
+
+ if (inventory == null || ignore.contains(playerName)) return;
+
+
+
+ Location loc = inventory.getLocation();
+
+ InventoryAction action = event.getAction();
+
+ if (inventory.getType() == InventoryType.CHEST && (action == InventoryAction.COLLECT_TO_CURSOR ||
+ action == InventoryAction.PICKUP_ALL ||
+ action == InventoryAction.PICKUP_HALF ||
+ action == InventoryAction.PICKUP_ONE ||
+ action == InventoryAction.PICKUP_SOME ||
+ action == InventoryAction.MOVE_TO_OTHER_INVENTORY)) {
+
+ // we are taking from the chest
+ Database.logInventoryEvent(playerName, true, loc, event.getCurrentItem());
+
+ } else if (inventory.getType() == InventoryType.CHEST && (action == InventoryAction.PLACE_ALL ||
+ action == InventoryAction.PLACE_ONE ||
+ action == InventoryAction.PLACE_SOME ||
+ action == InventoryAction.HOTBAR_MOVE_AND_READD ||
+ action == InventoryAction.HOTBAR_SWAP)) {
+
+ // we are placing into the chest
+ Database.logInventoryEvent(playerName, false, loc, event.getCursor());
+
+ } else if (inventory.getType() == InventoryType.CHEST && (action == InventoryAction.SWAP_WITH_CURSOR)) {
+
+ // we are swapping what is in our cursor with what is in the given slot, reverse
+ Database.logInventoryEvent(playerName, true, loc, event.getCursor());
+ Database.logInventoryEvent(playerName, false, loc, event.getCurrentItem());
+
+ }
+
+
+ }
+
+ @EventHandler
+ public final void onBlockPlace(BlockPlaceEvent event) {
+ Block placedBlock = event.getBlock();
+ String playerName = event.getPlayer().getName();
+
+ if (ignore.contains(playerName)) return;
+
+ if (placedBlock.getType() == Material.CHEST)
+ Database.logBlockEvent(playerName, "PLACE", placedBlock.getLocation());
+
+ }
+
+ @EventHandler
+ public final void onBlockBreak(BlockBreakEvent event) {
+ Block placedBlock = event.getBlock();
+ String playerName = event.getPlayer().getName();
+
+ if (ignore.contains(playerName)) return;
+
+ if (placedBlock.getType() == Material.CHEST)
+ Database.logBlockEvent(playerName, "BREAK", placedBlock.getLocation());
+
+ }
+}
diff --git a/src/main/java/dev/deeve/containeraudit/Database.java b/src/main/java/dev/deeve/containeraudit/Database.java
new file mode 100644
index 0000000..ad409f4
--- /dev/null
+++ b/src/main/java/dev/deeve/containeraudit/Database.java
@@ -0,0 +1,125 @@
+package dev.deeve.containeraudit;
+
+import org.bukkit.entity.Player;
+import org.bukkit.plugin.java.JavaPlugin;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.Location;
+import org.bukkit.Bukkit;
+
+import java.sql.PreparedStatement;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+public class Database {
+ static Connection connection;
+ static Logger logger;
+
+ public static void connect(String path, Logger logger) throws SQLException {
+ connection = DriverManager.getConnection("jdbc:sqlite:" + path);
+ Database.logger = logger;
+ }
+
+ static String playerID(Player player) {
+ return player.getUniqueId().toString().replaceAll("-", "");
+ }
+
+ public static void createTables() throws SQLException {
+ PreparedStatement chestEventCreate = connection.prepareStatement(
+ "CREATE TABLE IF NOT EXISTS chest_events (" +
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "player TEXT NOT NULL, " +
+ "x REAL NOT NULL, " +
+ "y REAL NOT NULL, " +
+ "z REAL NOT NULL, " +
+ "block TEXT NOT NULL," +
+ "count INTEGER NOT NULL," +
+ "event_type TEXT NOT NULL," +
+ "timestamp INTEGER NOT NULL" +
+ ")"
+ );
+ chestEventCreate.executeUpdate();
+
+ PreparedStatement chestCreate = connection.prepareStatement(
+ "CREATE TABLE IF NOT EXISTS chests (" +
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "actor TEXT NOT NULL, " +
+ "action TEXT NOT NULL," +
+ "x REAL NOT NULL, " +
+ "y REAL NOT NULL, " +
+ "z REAL NOT NULL," +
+ "timestamp INTEGER NOT NULL" +
+ ")"
+ );
+
+ chestCreate.executeUpdate();
+
+ PreparedStatement viewCreate = connection.prepareStatement(
+ "CREATE VIEW IF NOT EXISTS chest_block_events AS " +
+ "SELECT * FROM chests AS placed_chest FULL OUTER JOIN chests AS broke_chest ON " +
+ "broke_chest.action = \"BREAK\" AND placed_chest.action = \"PLACE\" AND " +
+ " placed_chest.x = broke_chest.x AND placed_chest.y = broke_chest.y AND placed_chest.z = broke_chest.z AND "
+ + "broke_chest.timestamp = (SELECT MIN(timestamp) FROM chests WHERE timestamp > placed_chest.timestamp) WHERE " +
+ " placed_chest.action = \"PLACE\" OR broke_chest.action = \"BREAK\";"
+ );
+
+ viewCreate.executeUpdate();
+
+ // software engineering is dead
+ PreparedStatement shmiewShmeate = connection.prepareStatement("CREATE VIEW IF NOT EXISTS chest_event_owned AS SELECT chest_events.id, chest_events.player, chest_events.x, chest_events.y, chest_events.z, chest_events.timestamp AS event_timestamp, action, block, `count`, chests.timestamp AS chest_placed_timestamp, chests.actor AS chest_owner FROM chest_events LEFT JOIN chests ON chests.timestamp = (SELECT MAX(timestamp) FROM chests WHERE chest_events.x = x AND chest_events.y = y AND chest_events.z = z AND chests.action = \"PLACE\" AND chest_events.timestamp > timestamp)");
+ shmiewShmeate.executeUpdate();
+
+
+ }
+
+ public static void logInventoryEvent(String player, boolean pickup, Location loc, ItemStack stack) {
+ try {
+ PreparedStatement statement = connection.prepareStatement(
+ "INSERT INTO chest_events (player, x, y, z, block, count, event_type, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
+
+ statement.setString(1, player);
+ statement.setInt(2, loc.getBlockX());
+ statement.setInt(3, loc.getBlockY());
+ statement.setInt(4, loc.getBlockZ());
+ statement.setString(5, stack.getType().getKey().toString());
+ statement.setInt(6, stack.getAmount());
+ statement.setString(7, pickup ? "PICKUP" : "PLACE");
+ statement.setLong(8, Instant.now().getEpochSecond());
+
+ statement.executeUpdate();
+
+ } catch (SQLException ex) {
+ logger.log(Level.SEVERE, "Error occured when inserting into chest_events");
+ ex.printStackTrace();
+ }
+
+ }
+
+ public static void logBlockEvent(String player, String type, Location loc) {
+ try {
+ PreparedStatement statement = connection.prepareStatement(
+ "INSERT INTO chests (actor, action, x, y, z, timestamp) VALUES (?, ?, ?, ?, ?, ?)");
+
+ statement.setString(1, player);
+ statement.setString(2, type);
+ statement.setInt(3, loc.getBlockX());
+ statement.setInt(4, loc.getBlockY());
+ statement.setInt(5, loc.getBlockZ());
+ statement.setLong(6, Instant.now().getEpochSecond());
+
+ statement.executeUpdate();
+
+ } catch (SQLException ex) {
+ logger.log(Level.SEVERE, "Error occured when inserting into chests");
+ ex.printStackTrace();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/dev/deeve/containeraudit/Plugin.java b/src/main/java/dev/deeve/containeraudit/Plugin.java
new file mode 100644
index 0000000..a92d6c0
--- /dev/null
+++ b/src/main/java/dev/deeve/containeraudit/Plugin.java
@@ -0,0 +1,44 @@
+package dev.deeve.containeraudit;
+
+
+import org.bukkit.plugin.java.JavaPlugin;
+
+import java.util.logging.Logger;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Level;
+import java.sql.SQLException;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class Plugin extends JavaPlugin {
+ public static Logger logger;
+
+
+ public void onEnable() {
+ logger = getLogger();
+ getDataFolder().mkdirs();
+
+ try {
+ Database.connect(new File(getDataFolder(), "database.db").getPath(), logger);
+ List<String> ignores = new ArrayList();
+ Path okay = Paths.get(getDataFolder().getPath(), "okay.txt");
+
+ if (Files.exists(okay)) {
+ ignores = Files.readAllLines(okay);
+ }
+
+ getServer().getPluginManager().registerEvents(new ChestListener(ignores), this);
+ Database.createTables();
+ }
+ catch (SQLException | IOException ex) {
+ logger.log(Level.SEVERE, "Database error: (not enabling plugin)");
+ ex.printStackTrace();
+ return;
+ }
+
+ }
+}