diff --git a/docs/api/version/v11.md b/docs/api/version/v11.md new file mode 100644 index 0000000..8541c13 --- /dev/null +++ b/docs/api/version/v11.md @@ -0,0 +1,530 @@ +# API Version 11 + +The CoreProtect API enables you to log your own block changes, perform lookups, rollbacks, restores, and more. + +| API Details | | +| --- | --- | +| **API Version:** | 11 | +| **Plugin Version:** | v24.0+ | +| **Maven:** | [maven.playpro.com](https://maven.playpro.com) | + +--- + +## Upgrading from API v10 + +The changes from the previous API version are as follows: + +- The following event was extended to include Location (mutable): +```java +CoreProtectPreLogEvent(String user, Location location) +``` +- The old constructor remains for backward compatibility and is deprecated: +```java +@Deprecated +CoreProtectPreLogEvent(String user) +``` + +--- + +## Getting Started + +Ensure you're using CoreProtect 24.0 or higher. Add it as an external jar to your plugin in your IDE. +Alternatively, if using Maven, you can add it via the repository https://maven.playpro.com (net.coreprotect, 24.0). + +The first thing you need to do is get access to CoreProtect. You can do this by using code similar to the following: + +```java +import net.coreprotect.CoreProtect; +import net.coreprotect.CoreProtectAPI; + +private CoreProtectAPI getCoreProtect() { + Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect"); + + // Check that CoreProtect is loaded + if (plugin == null || !(plugin instanceof CoreProtect)) { + return null; + } + + // Check that the API is enabled + CoreProtectAPI CoreProtect = ((CoreProtect) plugin).getAPI(); + if (CoreProtect.isEnabled() == false) { + return null; + } + + // Check that a compatible version of the API is loaded + if (CoreProtect.APIVersion() < 11) { + return null; + } + + return CoreProtect; +} +``` + +With this code, you can then access the API with a call like the following: + +```java +CoreProtectAPI api = getCoreProtect(); +if (api != null){ // Ensure we have access to the API + api.testAPI(); // Will print out "[CoreProtect] API test successful." in the console. +} +``` + +Yay, you're now using the CoreProtect API! + +--- + +## API Overview + +### Available Methods + +```java +boolean isEnabled() + +void testAPI() + +List performLookup(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location) + +List performRollback(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location) + +List performRestore(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location) + +List blockLookup(Block block, int time) + +List sessionLookup(String user, int time) + +List queueLookup(Block block) + +ParseResult parseResult(String[] result) + +boolean logChat(Player player, String message) + +boolean logCommand(Player player, String command) + +boolean logPlacement(String user, BlockState blockState) + +boolean logPlacement(String user, Location location, Material type, BlockData blockData) + +boolean logRemoval(String user, BlockState blockState) + +boolean logRemoval(String user, Location location, Material type, BlockData blockData) + +boolean logContainerTransaction(String user, Location location) + +boolean logInteraction(String user, Location location) + +boolean hasPlaced(String user, Block block, int time, int offset) + +boolean hasRemoved(String user, Block block, int time, int offset) + +void performPurge(int time) +``` + +--- + +### Available Events + +The following events are emitted by CoreProtect. + +#### CoreProtectPreLogEvent + +Fired when a CoreProtect logger is about to log an action. Cancellable. + +| Property | Description | Mutable | +| --- | --- | --- | +| User | The name of the user under which this action will be logged. | Yes | +| Location | The location where the action will be logged. | Yes | +| Cancelled | If cancelled, the action won't be logged to the database. | Yes | + +--- + +### Method Usage + +*Detailed method information is listed below.* + +#### `isEnabled()` + +Calling this will return true if the server has the CoreProtect API enabled, and false if it does not. + +--- + +#### `testAPI()` + +Running this will print out "[CoreProtect] API Test Successful." in the server console. + +--- + +#### `performLookup(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)` + +This will perform a lookup. + +* **time:** Specify the amount of time to search back. "5" would return results from the last 5 seconds. +* **restrict_users:** Specify any usernames to perform the lookup on. Can be set to "null" if both a radius and a location are specified. +* **exclude_users:** Specify any usernames to exclude from the lookup. Can be set to "null". +* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the search to. Can be set to "null". +* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the search. Can be set to "null". +* **action_list:** Specify a list of action types to restrict the search to. Can be set to "null" +* **radius:** Specify a radius to restrict the search to. A location must be specified if using this. Set to "0" to disable. +* **radius_location:** Specify a location to search around. Can be set to "null" if no radius is specified, and a user is specified. + +--- + +#### `performRollback(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)` + +This will perform a rollback. Method must be called async. + +* **time:** Specify the amount of time to rollback. "5" would return results from the last 5 seconds. +* **restrict_users:** Specify any usernames to perform the rollback on. Can be set to "null" if both a radius and a location are specified. +* **exclude_users:** Specify any usernames to exclude from the rollback. Can be set to "null". +* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the rollback to. Can be set to "null". +* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the rollback. Can be set to "null". +* **action_list:** Specify a list of action types to restrict the rollback to. Can be set to "null" +* **radius:** Specify a radius to restrict the rollback to. A location must be specified if using this. Set to "0" to disable. +* **radius_location:** Specify a location to rollback around. Can be set to "null" if no radius is specified, and a user is specified. + +--- + +#### `performRestore(int time, List restrict_users, List exclude_users, List restrict_blocks, List exclude_blocks, List action_list, int radius, Location radius_location)` + +This will perform a restore. + +* **time:** Specify the amount of time to restore. "5" would return results from the last 5 seconds. +* **restrict_users:** Specify any usernames to perform the restore on. Can be set to "null" if both a radius and a location are specified. +* **exclude_users:** Specify any usernames to exclude from the restore. Can be set to "null". +* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the restore to. Can be set to "null". +* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the restore. Can be set to "null". +* **action_list:** Specify a list of action types to restrict the restore to. Can be set to "null" +* **radius:** Specify a radius to restrict the restore to. A location must be specified if using this. Set to "0" to disable. +* **radius_location:** Specify a location to restore around. Can be set to "null" if no radius is specified, and a user is specified. + +--- + +#### `blockLookup(Block block, int time)` + +This will perform a full lookup on a single block. + +* **block:** The block to perform the lookup on. +* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds. + +--- + +#### `queueLookup(Block block)` + +This will search the consumer queue for changes on a block not yet saved in the database. + +* **block:** The block to perform the lookup on. + +--- + +#### `sessionLookup(String user, int time)` + +This will perform a session lookup on a single player. + +* **user:** The username to perform the lookup on. +* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds. + +--- + +#### `ParseResult parseResult(String[] result)` + +This will parse results from a lookup. You'll then be able to view the following: + +* **getX():** Get the X coordinate of the block. +* **getY():** Get the Y coordinate of the block. +* **getZ():** Get the Z coordinate of the block. +* **getType():** Get the Material of the block. +* **getBlockData():** Get the BlockData of the block. +* **getPlayer():** Get the username as a string. +* **getTimestamp():** Get the time of the action. +* **getActionId():** Get the action ID. (0=removed, 1=placed, 2=interaction) +* **getActionString():** Get the action as a string. (Removal, Placement, Interaction) +* **isRolledBack():** If the block is currently rolled back or not. +* **worldName():** The name of the world the block is located in. + +--- + +#### `logPlacement(String user, BlockState blockState)` + +This will log a block as being placed. *(Thread safe)* + +* **user:** Specify the username to log as having placed the block. +* **blockState:** Specify the BlockState of the block you're logging. + +--- + +#### `logPlacement(String user, Location location, Material type, BlockData blockData)` + +This will log a block as being placed. + +* **user:** Specify the username to log as having placed the block. +* **location:** Specify the location of the block you're logging. +* **type:** Specify the Material of the block you're logging. +* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null". + +--- + +#### `logRemoval(String user, BlockState blockState)` + +This will log a block as being removed/broken. *(Thread safe)* + +* **user:** Specify the username to log as having removed the block. +* **blockState:** Specify the BlockState of the block you're logging. + +--- + +#### `logRemoval(String user, Location location, Material type, BlockData blockData)` + +This will log a block as being removed/broken, and will log the block's inventory (if applicable). + +* **user:** Specify the username to log as having removed the block. +* **location:** Specify the location of the block you're logging. +* **type:** Specify the Material of the block you're logging. +* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null". + +--- + +#### `logContainerTransaction(String user, Location location)` + +This will log any transactions made to a block's inventory immediately after calling the method. + +* **user:** Specify the username to log as having added/removed the items. +* **location:** Specify the location of the block inventory you're logging. + +--- + +#### `logInteraction(String user, Location location)` + +This will log a block as having been interacted with. + +* **user:** Specify the username to log as having caused the interaction. +* **location:** Specify the location of the interaction you're logging. + +--- + +#### `hasPlaced(String user, Block block, int time, int offset)` + +This will return true if a user has already placed a block at the location within the specified time limit. + +* **user:** The username you're checking to see if they've placed a block already. +* **block:** The block you're checking. +* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks. +* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0 = no offset) + +--- + +#### `hasRemoved(String user, Block block, int time, int offset)` + +This will return true if a user has already removed a block at the location within the specified time limit. + +* **user:** The username you're checking to see if they've removed a block already. +* **block:** The block you're checking. +* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks. +* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0 = no offset) + +--- + +#### `performPurge(int time)` + +This will perform a purge on the CoreProtect database. + +* **time:** Purge any data earlier than this. "120" would purge any data older than 120 seconds (2 minutes). + +--- + + +### Examples + +- Get the last 60 seconds of block data for the user "Notch". +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + List lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, null, null, 0, null); + if (lookup != null){ + for (String[] result : lookup){ + ParseResult parseResult = CoreProtect.parseResult(result); + int x = parseResult.getX(); + int y = parseResult.getY(); + int z = parseResult.getZ(); + // ... + } + } +} +``` + +--- + +- Get the last 60 seconds of block data for the user "Notch", excluding dirt and grass blocks. +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + List exclude = Arrays.asList(Material.DIRT, Material.GRASS); + List lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, exclude, null, 0, null); + if (lookup != null){ + for (String[] value : lookup){ + ParseResult result = CoreProtect.parseResult(value); + int x = result.getX(); + int y = result.getY(); + int z = result.getZ(); + // ... + } + } +} +``` + +--- + +- Get the last 60 seconds of block data within 5 blocks of a location. +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + List lookup = CoreProtect.performLookup(60, null, null, null, null, null, 5, location); + if (lookup != null){ + for (String[] value : lookup){ + ParseResult result = CoreProtect.parseResult(value); + int x = result.getX(); + int y = result.getY(); + int z = result.getZ(); + // ... + } + } +} +``` + +--- + +- Rollbacks / restores use the same code structure as the above examples. For example: +```java +class BasicThread implements Runnable { +@Override +public void run() { + try { + CoreProtectAPI CoreProtect = getCoreProtect(); + if (CoreProtect != null){ // Ensure we have access to the API + List lookup = CoreProtect.performRollback(60, Arrays.asList("Notch"), null, null, null, null, 0, null); + if (lookup != null){ + for (String[] value : lookup){ + ParseResult result = CoreProtect.parseResult(value); + int x = result.getX(); + int y = result.getY(); + int z = result.getZ(); + // ... + } + } + } + } + catch (Exception e){ + e.printStackTrace(); + } +} +} +Runnable runnable = new BasicThread(); +Thread thread = new Thread(runnable); +thread.start(); +``` + +--- + +- Check if the user "Notch" has already placed a block at a location within the last 60 seconds. +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + boolean hasPlaced = CoreProtect.hasPlaced("Notch", block, 60, 0); + + // Search queue for pending changes + if (!hasPlaced){ + List lookup = CoreProtect.queueLookup(block); + for (String[] result : lookup){ + ParseResult parseResult = CoreProtect.parseResult(result); + if (parseResult.getActionId()==1 && parseResult.getPlayer().equals("Notch")){ + hasPlaced = true; + break; + } + } + } +} +``` + +--- + +- Get the last 60 seconds of block data for a specific block. +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + List lookup = CoreProtect.blockLookup(block, 60); + if (lookup != null){ + for (String[] result : lookup){ + ParseResult parseResult = CoreProtect.parseResult(result); + int x = parseResult.getX(); + int y = parseResult.getY(); + int z = parseResult.getZ(); + // ... + } + } +} +``` + +--- + +- Get the last 1 day of session data for the user "Notch". +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + List lookup = CoreProtect.sessionLookup("Notch", (24 * 60 * 60)); + if (lookup != null){ + for (String[] result : lookup){ + ParseResult parseResult = CoreProtect.parseResult(result); + int x = parseResult.getX(); + int y = parseResult.getY(); + int z = parseResult.getZ(); + int action = parseResult.getActionId(); // 0 = logout, 1 = login + // ... + } + } +} +``` + +--- + +- Log the placement of a block at a location by the user "Notch". +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + boolean success = CoreProtect.logPlacement("Notch", block.getLocation(), block.getType(), block.getData()); +} +``` + +--- + +- Log adding/remove items in a chest (or some other block inventory). +```java +CoreProtectAPI CoreProtect = getCoreProtect(); +if (CoreProtect != null){ // Ensure we have access to the API + boolean success = CoreProtect.logContainerTransaction("Notch", inventory.getLocation()); + // modify your container contents immediately after (e.g. [i]inventory.addItem(itemStack);[/i]) +} +``` + +--- + +- Perform a multi-threaded placement check to see if the user "Notch" has already placed a block at a location within the last 60 seconds. This ignores the most recent 1 second of logged data, to account for the fact that that new block data may have already been logged, depending on your code. +```java +final Block block = null; //Should be an actual block +class BasicThread implements Runnable { + @Override + public void run() { + try { + CoreProtectAPI CoreProtect = getCoreProtect(); + if (CoreProtect != null){ // Ensure we have access to the API + boolean hasPlaced = CoreProtect.hasPlaced("Notch", block, 60, 1); + } + } + catch (Exception e){ + e.printStackTrace(); + } + } +} +Runnable runnable = new BasicThread(); +Thread thread = new Thread(runnable); +thread.start(); +``` + +--- \ No newline at end of file diff --git a/docs/database-migration.md b/docs/database-migration.md index 71d45fb..a9259db 100644 --- a/docs/database-migration.md +++ b/docs/database-migration.md @@ -19,8 +19,9 @@ The `/co migrate-db` command allows you to seamlessly transfer all your CoreProt | `/co migrate-db` | `` | Migrate to the specified database type | **Examples:** -- `/co migrate-db mysql` - Migrate from SQLite to MySQL -- `/co migrate-db sqlite` - Migrate from MySQL to SQLite + +* `/co migrate-db mysql` - Migrate from SQLite to MySQL +* `/co migrate-db sqlite` - Migrate from MySQL to SQLite > **Console Only:** This command can only be executed from the server console, not from in-game. diff --git a/src/main/java/net/coreprotect/CoreProtectAPI.java b/src/main/java/net/coreprotect/CoreProtectAPI.java index de866f6..757427b 100755 --- a/src/main/java/net/coreprotect/CoreProtectAPI.java +++ b/src/main/java/net/coreprotect/CoreProtectAPI.java @@ -41,7 +41,7 @@ public class CoreProtectAPI extends Queue { /** * Current version of the API */ - private static final int API_VERSION = 10; + private static final int API_VERSION = 11; public static class ParseResult extends net.coreprotect.api.result.ParseResult { diff --git a/src/main/java/net/coreprotect/database/logger/BlockBreakLogger.java b/src/main/java/net/coreprotect/database/logger/BlockBreakLogger.java index dccecc7..cfe0618 100644 --- a/src/main/java/net/coreprotect/database/logger/BlockBreakLogger.java +++ b/src/main/java/net/coreprotect/database/logger/BlockBreakLogger.java @@ -54,17 +54,18 @@ public class BlockBreakLogger { blockData = overrideData; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(location.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); CacheHandler.breakCache.put("" + x + "." + y + "." + z + "." + wid + "", new Object[] { time, event.getUser(), type }); if (event.isCancelled()) { diff --git a/src/main/java/net/coreprotect/database/logger/BlockPlaceLogger.java b/src/main/java/net/coreprotect/database/logger/BlockPlaceLogger.java index 32487a7..59db0dd 100644 --- a/src/main/java/net/coreprotect/database/logger/BlockPlaceLogger.java +++ b/src/main/java/net/coreprotect/database/logger/BlockPlaceLogger.java @@ -6,6 +6,7 @@ import java.util.Locale; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.Location; import org.bukkit.block.BlockState; import net.coreprotect.CoreProtect; @@ -85,15 +86,21 @@ public class BlockPlaceLogger { } } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation()); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(block.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); + // Use event location for subsequent logging + x = eventLocation.getBlockX(); + y = eventLocation.getBlockY(); + z = eventLocation.getBlockZ(); + if (event.getUser().length() > 0) { CacheHandler.lookupCache.put("" + x + "." + y + "." + z + "." + wid + "", new Object[] { time, event.getUser(), type }); } diff --git a/src/main/java/net/coreprotect/database/logger/CommandLogger.java b/src/main/java/net/coreprotect/database/logger/CommandLogger.java index 5647184..d85faec 100644 --- a/src/main/java/net/coreprotect/database/logger/CommandLogger.java +++ b/src/main/java/net/coreprotect/database/logger/CommandLogger.java @@ -29,7 +29,7 @@ public class CommandLogger { return; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -39,10 +39,11 @@ public class CommandLogger { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(location.getWorld().getName()); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); CommandStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, message); } catch (Exception e) { diff --git a/src/main/java/net/coreprotect/database/logger/ContainerLogger.java b/src/main/java/net/coreprotect/database/logger/ContainerLogger.java index a2e3f83..d0aa141 100644 --- a/src/main/java/net/coreprotect/database/logger/ContainerLogger.java +++ b/src/main/java/net/coreprotect/database/logger/ContainerLogger.java @@ -223,7 +223,7 @@ public class ContainerLogger extends Queue { metadata = null; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -233,11 +233,12 @@ public class ContainerLogger extends Queue { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(location.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); int typeId = MaterialUtils.getBlockId(item.getType().name(), true); int data = 0; int amount = item.getAmount(); diff --git a/src/main/java/net/coreprotect/database/logger/EntityKillLogger.java b/src/main/java/net/coreprotect/database/logger/EntityKillLogger.java index f8ddcdb..f929bf8 100644 --- a/src/main/java/net/coreprotect/database/logger/EntityKillLogger.java +++ b/src/main/java/net/coreprotect/database/logger/EntityKillLogger.java @@ -6,6 +6,7 @@ import java.util.List; import java.util.Locale; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.block.BlockState; import net.coreprotect.CoreProtect; @@ -30,7 +31,8 @@ public class EntityKillLogger { return; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + Location initialLocation = new Location(block.getWorld(), block.getX(), block.getY(), block.getZ()); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -40,11 +42,12 @@ public class EntityKillLogger { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(block.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); int entity_key = 0; ResultSet resultSet = EntityStatement.insert(preparedStmt2, time, data); diff --git a/src/main/java/net/coreprotect/database/logger/ItemLogger.java b/src/main/java/net/coreprotect/database/logger/ItemLogger.java index c7c38e9..2092822 100644 --- a/src/main/java/net/coreprotect/database/logger/ItemLogger.java +++ b/src/main/java/net/coreprotect/database/logger/ItemLogger.java @@ -129,7 +129,7 @@ public class ItemLogger { data = null; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -139,11 +139,12 @@ public class ItemLogger { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(location.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L) - offset; - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); int typeId = MaterialUtils.getBlockId(item.getType().name(), true); int amount = item.getAmount(); ItemStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, typeId, data, amount, action); diff --git a/src/main/java/net/coreprotect/database/logger/PlayerInteractLogger.java b/src/main/java/net/coreprotect/database/logger/PlayerInteractLogger.java index 3a5e502..c4a7c46 100644 --- a/src/main/java/net/coreprotect/database/logger/PlayerInteractLogger.java +++ b/src/main/java/net/coreprotect/database/logger/PlayerInteractLogger.java @@ -5,6 +5,7 @@ import java.util.Locale; import org.bukkit.Bukkit; import org.bukkit.Material; +import org.bukkit.Location; import org.bukkit.block.BlockState; import net.coreprotect.CoreProtect; @@ -29,7 +30,7 @@ public class PlayerInteractLogger { return; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation()); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -39,11 +40,12 @@ public class PlayerInteractLogger { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(block.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); int data = 0; BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, null, null, 2, 0); } diff --git a/src/main/java/net/coreprotect/database/logger/PlayerKillLogger.java b/src/main/java/net/coreprotect/database/logger/PlayerKillLogger.java index d476055..a11d21c 100644 --- a/src/main/java/net/coreprotect/database/logger/PlayerKillLogger.java +++ b/src/main/java/net/coreprotect/database/logger/PlayerKillLogger.java @@ -4,6 +4,7 @@ import java.sql.PreparedStatement; import java.util.Locale; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.block.BlockState; import net.coreprotect.CoreProtect; @@ -30,7 +31,8 @@ public class PlayerKillLogger { UserStatement.loadId(preparedStmt.getConnection(), player, null); } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + Location initialLocation = new Location(block.getWorld(), block.getX(), block.getY(), block.getZ()); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -41,11 +43,12 @@ public class PlayerKillLogger { int userId = UserStatement.getId(preparedStmt, event.getUser(), true); int playerId = ConfigHandler.playerIdCache.get(player.toLowerCase(Locale.ROOT)); - int wid = WorldUtils.getWorldId(block.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L); - int x = block.getX(); - int y = block.getY(); - int z = block.getZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, 0, playerId, null, null, 3, 0); } catch (Exception e) { diff --git a/src/main/java/net/coreprotect/database/logger/SignTextLogger.java b/src/main/java/net/coreprotect/database/logger/SignTextLogger.java index 1da6038..42d3ca8 100644 --- a/src/main/java/net/coreprotect/database/logger/SignTextLogger.java +++ b/src/main/java/net/coreprotect/database/logger/SignTextLogger.java @@ -26,7 +26,7 @@ public class SignTextLogger { return; } - CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user); + CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location); if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) { CoreProtect.getInstance().getServer().getPluginManager().callEvent(event); } @@ -36,11 +36,12 @@ public class SignTextLogger { } int userId = UserStatement.getId(preparedStmt, event.getUser(), true); - int wid = WorldUtils.getWorldId(location.getWorld().getName()); + Location eventLocation = event.getLocation(); + int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName()); int time = (int) (System.currentTimeMillis() / 1000L) - timeOffset; - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); + int x = eventLocation.getBlockX(); + int y = eventLocation.getBlockY(); + int z = eventLocation.getBlockZ(); if (line1.isEmpty() && line2.isEmpty() && line3.isEmpty() && line4.isEmpty()) { line1 = null; diff --git a/src/main/java/net/coreprotect/event/CoreProtectPreLogEvent.java b/src/main/java/net/coreprotect/event/CoreProtectPreLogEvent.java index a9fbd00..ad15110 100644 --- a/src/main/java/net/coreprotect/event/CoreProtectPreLogEvent.java +++ b/src/main/java/net/coreprotect/event/CoreProtectPreLogEvent.java @@ -1,5 +1,6 @@ package net.coreprotect.event; +import org.bukkit.Location; import org.bukkit.event.Cancellable; import org.bukkit.event.Event; import org.bukkit.event.HandlerList; @@ -9,16 +10,33 @@ public class CoreProtectPreLogEvent extends Event implements Cancellable { private static final HandlerList handlers = new HandlerList(); private boolean cancelled = false; private String user; + private Location location; + public CoreProtectPreLogEvent(String user, Location location) { + super(true); // async + this.user = user; + this.location = location; + } + + /** + * Backwards-compatible constructor for API v10 and earlier. + * Defaults location to null; listeners expecting v10 signature can still subscribe. + */ + @Deprecated public CoreProtectPreLogEvent(String user) { super(true); // async this.user = user; + this.location = null; } public String getUser() { return user; } + public Location getLocation() { + return location; + } + @Override public boolean isCancelled() { return cancelled; @@ -37,6 +55,14 @@ public class CoreProtectPreLogEvent extends Event implements Cancellable { this.user = newUser; } + public void setLocation(Location newLocation) { + if (newLocation == null) { + throw new IllegalArgumentException("Invalid location"); + } + + this.location = newLocation; + } + @Override public HandlerList getHandlers() { return handlers;