Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32fd97f768 | ||
|
|
d45ac1b275 | ||
|
|
cd7a71648b | ||
|
|
dc87d4fbf4 | ||
|
|
f8a8e3f657 | ||
|
|
52c5b28b79 | ||
|
|
90a2981603 | ||
|
|
fbc68766f6 | ||
|
|
667061a9fe | ||
|
|
2e2e5a9857 | ||
|
|
79e0ca7b13 | ||
|
|
a3a6d398de | ||
|
|
7c7dce0048 | ||
|
|
acfb6fce7a | ||
|
|
152c37e85a |
No files matched your search
@@ -41,7 +41,7 @@ Maven
|
||||
<dependency>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>coreprotect</artifactId>
|
||||
<version>22.3</version>
|
||||
<version>22.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
+7
-9
@@ -2,16 +2,16 @@ import org.apache.tools.ant.filters.ReplaceTokens
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'com.github.johnrengelman.shadow' version '7.1.2'
|
||||
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||
id 'com.palantir.git-version' version '0.13.0'
|
||||
}
|
||||
|
||||
group = 'net.coreprotect'
|
||||
String projectVersion = '22.3'
|
||||
String projectVersion = '22.4'
|
||||
String projectBranch = ''
|
||||
version = projectVersion // `version` might be modified, we don't always want that (e.g. plugin.yml)
|
||||
description = 'Provides block protection for your server.'
|
||||
sourceCompatibility = '17'
|
||||
sourceCompatibility = '21'
|
||||
|
||||
if (System.getenv("BUILD_NUMBER") != null) {
|
||||
// Being built in Jenkins, append Build ID
|
||||
@@ -23,17 +23,15 @@ if (System.getenv("BUILD_NUMBER") != null) {
|
||||
logger.info("Building version $version")
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url = 'https://hub.spigotmc.org/nexus/content/groups/public/' }
|
||||
maven { url = 'https://papermc.io/repo/repository/maven-public/' }
|
||||
maven { url = 'https://repo.papermc.io/repository/maven-public/' }
|
||||
maven { url = 'https://repo.codemc.org/repository/maven-public/' }
|
||||
maven { url = 'https://maven.enginehub.org/repo/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly('com.sk89q.worldedit:worldedit-bukkit:7.0.0-SNAPSHOT') {
|
||||
exclude group: 'org.bukkit'
|
||||
}
|
||||
implementation(platform("com.intellectualsites.bom:bom-newest:1.44")) // Ref: https://github.com/IntellectualSites/bom
|
||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core")
|
||||
compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Bukkit")
|
||||
compileOnly 'io.papermc.paper:paper-api:1.20.4-R0.1-SNAPSHOT'
|
||||
implementation 'org.bstats:bstats-bukkit-lite:1.8'
|
||||
implementation 'com.zaxxer:HikariCP:5.0.1'
|
||||
|
||||
+3
-3
@@ -4,8 +4,8 @@ The CoreProtect API enables you to log your own block changes, perform lookups,
|
||||
|
||||
| API Details | |
|
||||
| --- | --- |
|
||||
| **API Version:** | 9 |
|
||||
| **Plugin Version:** | v21.0+ |
|
||||
| **API Version:** | 10 |
|
||||
| **Plugin Version:** | v22.4+ |
|
||||
| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
|
||||
|
||||
*Documentation for the API version 9 can be found [here](/api/version/v9/).*
|
||||
*Documentation for the API version 10 can be found [here](/api/version/v10/).*
|
||||
@@ -0,0 +1,526 @@
|
||||
# API Version 10
|
||||
|
||||
The CoreProtect API enables you to log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
|
||||
| API Details | |
|
||||
| --- | --- |
|
||||
| **API Version:** | 10 |
|
||||
| **Plugin Version:** | v22.4+ |
|
||||
| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
|
||||
|
||||
---
|
||||
|
||||
## Upgrading from API v9
|
||||
|
||||
The changes from the previous API version are as follows:
|
||||
|
||||
- The following methods have been added:
|
||||
```java
|
||||
logPlacement(String user, BlockState blockState)
|
||||
|
||||
logRemoval(String user, BlockState blockState)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ensure you're using CoreProtect 22.4 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](https://maven.playpro.com) (net.coreprotect, 22.4).
|
||||
|
||||
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() < 10) {
|
||||
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<String[]> performLookup(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> performRollback(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> performRestore(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> blockLookup(Block block, int time)
|
||||
|
||||
List<String[]> sessionLookup(String user, int time)
|
||||
|
||||
List<String[]> 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 |
|
||||
| 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<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> 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<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> 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<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> 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<String[]> 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<Object> exclude = Arrays.asList(Material.DIRT, Material.GRASS);
|
||||
List<String[]> 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<String[]> 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<String[]> 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<String[]> 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<String[]> 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<String[]> 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();
|
||||
```
|
||||
|
||||
---
|
||||
+6
-3
@@ -18,15 +18,18 @@ Secondary configuration files override the value specified in config.yml. If you
|
||||
|
||||
## Disabling Logging
|
||||
|
||||
To disable logging for specific users or commands, simply do the following:
|
||||
To disable logging for specific users, blocks or commands, simply do the following:
|
||||
|
||||
1. In the CoreProtect plugin directory, create a file named `blacklist.txt`.
|
||||
2. Enter the names of the users (or commands) you'd like to disable logging for (each username on a new line).
|
||||
3. Either restart your server, or type "/co reload" in-game.
|
||||
|
||||
This can be used to disable logging for non-player users, such as "#tnt". For example, if you'd like to disable logging for the user "Notch", TNT explosions, and the "/help" command, the blacklist.txt file would look like this:
|
||||
This can be used to disable logging for non-player users, such as "#creeper". For example, if you'd like to disable logging for the user "Notch", TNT explosions, stone blocks, and the "/help" command, the blacklist.txt file would look like this:
|
||||
```text
|
||||
Notch
|
||||
#tnt
|
||||
/help
|
||||
```
|
||||
minecraft:stone
|
||||
```
|
||||
|
||||
*Please note that to disable logging for blocks, CoreProtect v23+ is required, and you must include the namespace. For example, to disable logging for dirt, you must add it as "minecraft:dirt".*
|
||||
+3
-3
@@ -22,7 +22,7 @@ Log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
A list of plugins and tools that are compatible with CoreProtect.
|
||||
|
||||
[**Per-World Configuration Files**](/config/#per-world-configuration)
|
||||
Log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
Modify the logging settings for a specific world on your server.
|
||||
|
||||
[**Disable Logging for Specific Users or Commands**](/config/#disabling-logging)
|
||||
Log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
[**Disable Logging With a Blacklist**](/config/#disabling-logging)
|
||||
Disable logging for specific users, blocks or commands.
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>CoreProtect</artifactId>
|
||||
<version>22.3</version>
|
||||
<version>22.4</version>
|
||||
<properties>
|
||||
<project.branch></project.branch>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -88,11 +88,18 @@
|
||||
<id>codemc-repo</id>
|
||||
<url>https://repo.codemc.org/repository/maven-public/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>enginehub-repo</id>
|
||||
<url>https://maven.enginehub.org/repo/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.intellectualsites.bom</groupId>
|
||||
<artifactId>bom-newest</artifactId> <!-- Ref: https://github.com/IntellectualSites/bom -->
|
||||
<version>1.44</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<dependencies>
|
||||
<!--
|
||||
paper-api: io.papermc.paper
|
||||
@@ -113,14 +120,18 @@
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.sk89q.worldedit</groupId>
|
||||
<artifactId>worldedit-bukkit</artifactId>
|
||||
<version>7.0.0-SNAPSHOT</version>
|
||||
<groupId>com.fastasyncworldedit</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastasyncworldedit</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Bukkit</artifactId>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bukkit</groupId>
|
||||
<artifactId>bukkit</artifactId>
|
||||
<artifactId>FastAsyncWorldEdit-Core</artifactId>
|
||||
<groupId>*</groupId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
@@ -25,7 +25,7 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.Lookup;
|
||||
import net.coreprotect.database.Rollback;
|
||||
import net.coreprotect.database.rollback.Rollback;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.listener.player.InventoryChangeListener;
|
||||
import net.coreprotect.utility.Chat;
|
||||
@@ -168,7 +168,7 @@ public class CoreProtectAPI extends Queue {
|
||||
}
|
||||
|
||||
public int APIVersion() {
|
||||
return 9;
|
||||
return 10;
|
||||
}
|
||||
|
||||
public List<String[]> blockLookup(Block block, int time) {
|
||||
@@ -282,6 +282,19 @@ public class CoreProtectAPI extends Queue {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean logPlacement(String user, BlockState blockState) {
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blockState == null || user == null || user.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Queue.queueBlockPlace(user, blockState, blockState.getType(), null, blockState.getType(), -1, 0, blockState.getBlockData().getAsString());
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean logPlacement(String user, Location location, Material type, BlockData blockData) {
|
||||
if (Config.getGlobal().API_ENABLED) {
|
||||
if (user != null && location != null) {
|
||||
@@ -316,6 +329,19 @@ public class CoreProtectAPI extends Queue {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean logRemoval(String user, BlockState blockState) {
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (blockState == null || user == null || user.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Queue.queueBlockBreak(user, blockState, blockState.getType(), blockState.getBlockData().getAsString(), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean logRemoval(String user, Location location, Material type, BlockData blockData) {
|
||||
if (Config.getGlobal().API_ENABLED) {
|
||||
if (user != null && location != null) {
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.coreprotect.model.BlockGroup;
|
||||
public class Bukkit_v1_20 extends Bukkit_v1_19 implements BukkitInterface {
|
||||
|
||||
private Boolean hasClickedPosition = null;
|
||||
private Boolean hasBasePotionType = null;
|
||||
|
||||
public Bukkit_v1_20() {
|
||||
BlockGroup.CONTAINERS = new HashSet<>(Arrays.asList(Material.JUKEBOX, Material.DISPENSER, Material.CHEST, Material.FURNACE, Material.BREWING_STAND, Material.TRAPPED_CHEST, Material.HOPPER, Material.DROPPER, Material.ARMOR_STAND, Material.ITEM_FRAME, Material.SHULKER_BOX, Material.BLACK_SHULKER_BOX, Material.BLUE_SHULKER_BOX, Material.BROWN_SHULKER_BOX, Material.CYAN_SHULKER_BOX, Material.GRAY_SHULKER_BOX, Material.GREEN_SHULKER_BOX, Material.LIGHT_BLUE_SHULKER_BOX, Material.LIME_SHULKER_BOX, Material.MAGENTA_SHULKER_BOX, Material.ORANGE_SHULKER_BOX, Material.PINK_SHULKER_BOX, Material.PURPLE_SHULKER_BOX, Material.RED_SHULKER_BOX, Material.LIGHT_GRAY_SHULKER_BOX, Material.WHITE_SHULKER_BOX, Material.YELLOW_SHULKER_BOX, Material.BARREL, Material.BLAST_FURNACE, Material.SMOKER, Material.LECTERN, Material.CHISELED_BOOKSHELF));
|
||||
@@ -255,20 +256,34 @@ public class Bukkit_v1_20 extends Bukkit_v1_19 implements BukkitInterface {
|
||||
|
||||
@Override
|
||||
public ItemStack getArrowMeta(Arrow arrow, ItemStack itemStack) {
|
||||
PotionType potionType = arrow.getBasePotionType();
|
||||
Color color = arrow.getColor();
|
||||
if (potionType != null || color != null) {
|
||||
itemStack = new ItemStack(Material.TIPPED_ARROW);
|
||||
PotionMeta meta = (PotionMeta) itemStack.getItemMeta();
|
||||
meta.setBasePotionType(potionType);
|
||||
meta.setColor(color);
|
||||
for (PotionEffect effect : arrow.getCustomEffects()) {
|
||||
meta.addCustomEffect(effect, false);
|
||||
try {
|
||||
if (hasBasePotionType == null) {
|
||||
hasBasePotionType = true;
|
||||
Arrow.class.getMethod("getBasePotionType"); // Bukkit 1.20.2+
|
||||
}
|
||||
else if (Boolean.FALSE.equals(hasBasePotionType)) {
|
||||
return super.getArrowMeta(arrow, itemStack);
|
||||
}
|
||||
itemStack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return itemStack;
|
||||
PotionType potionType = arrow.getBasePotionType();
|
||||
Color color = arrow.getColor();
|
||||
if (potionType != null || color != null) {
|
||||
itemStack = new ItemStack(Material.TIPPED_ARROW);
|
||||
PotionMeta meta = (PotionMeta) itemStack.getItemMeta();
|
||||
meta.setBasePotionType(potionType);
|
||||
meta.setColor(color);
|
||||
for (PotionEffect effect : arrow.getCustomEffects()) {
|
||||
meta.addCustomEffect(effect, false);
|
||||
}
|
||||
itemStack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return itemStack;
|
||||
}
|
||||
catch (Exception e) {
|
||||
hasBasePotionType = false;
|
||||
return super.getArrowMeta(arrow, itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.ContainerRollback;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.Rollback;
|
||||
import net.coreprotect.database.lookup.PlayerLookup;
|
||||
import net.coreprotect.database.rollback.Rollback;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
|
||||
@@ -41,7 +41,6 @@ public class Config extends Language {
|
||||
public String MYSQL_USERNAME;
|
||||
public String MYSQL_PASSWORD;
|
||||
public String LANGUAGE;
|
||||
public boolean ENABLE_AWE;
|
||||
public boolean ENABLE_SSL;
|
||||
public boolean DISABLE_WAL;
|
||||
public boolean HOVER_EVENTS;
|
||||
@@ -189,7 +188,6 @@ public class Config extends Language {
|
||||
}
|
||||
|
||||
private void readValues() {
|
||||
this.ENABLE_AWE = this.getBoolean("enable-awe", false);
|
||||
this.ENABLE_SSL = this.getBoolean("enable-ssl", false);
|
||||
this.DISABLE_WAL = this.getBoolean("disable-wal", false);
|
||||
this.HOVER_EVENTS = this.getBoolean("hover-events", true);
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package net.coreprotect.consumer.process;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -46,8 +48,9 @@ class ContainerTransactionProcess {
|
||||
}
|
||||
}
|
||||
else if (loggingChestId.startsWith("#hopper")) {
|
||||
if (force_size == 0 && ConfigHandler.oldContainer.get(loggingChestId).size() == 1 && ConfigHandler.transactingChest.get(transactingChestId).isEmpty()) {
|
||||
int loopCount = ConfigHandler.loggingChest.get(loggingChestId);
|
||||
List<Object> transactingChest = ConfigHandler.transactingChest.get(transactingChestId);
|
||||
if (force_size == 0 && ConfigHandler.oldContainer.getOrDefault(loggingChestId, Collections.synchronizedList(new ArrayList<>())).size() == 1 && transactingChest != null && transactingChest.isEmpty()) {
|
||||
int loopCount = ConfigHandler.loggingChest.getOrDefault(loggingChestId, 0);
|
||||
int maxInventorySize = (99 * 54);
|
||||
try {
|
||||
Inventory checkInventory = (Inventory) inventory;
|
||||
|
||||
@@ -83,6 +83,14 @@ public class Process {
|
||||
int consumerDataSize = consumerData.size();
|
||||
currentConsumerSize = consumerDataSize;
|
||||
|
||||
if (currentConsumerSize == 0) { // No data, skip processing
|
||||
updateLockTable(statement, (lastRun ? 0 : 1));
|
||||
statement.close();
|
||||
Consumer.consumer_id.put(processId, new Integer[] { 0, 0 });
|
||||
Consumer.isPaused = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Database.beginTransaction(statement);
|
||||
// Scan through usernames, ensure everything is loaded in memory.
|
||||
for (Entry<Integer, String[]> entry : users.entrySet()) {
|
||||
@@ -225,6 +233,7 @@ public class Process {
|
||||
consumerData.remove(index);
|
||||
}
|
||||
currentConsumerSize = 0;
|
||||
Consumer.consumer_id.put(processId, new Integer[] { 0, 0 });
|
||||
Consumer.isPaused = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,15 @@ import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.database.rollback.Rollback;
|
||||
import net.coreprotect.database.rollback.RollbackComplete;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Util;
|
||||
|
||||
public class ContainerRollback extends Queue {
|
||||
public class ContainerRollback extends Rollback {
|
||||
|
||||
public static void performContainerRollbackRestore(Statement statement, CommandSender user, List<String> checkUuids, List<String> checkUsers, String timeString, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, final Location location, Integer[] radius, long startTime, long endTime, boolean restrictWorld, boolean lookup, boolean verbose, final int rollbackType) {
|
||||
try {
|
||||
@@ -176,7 +178,7 @@ public class ContainerRollback extends Queue {
|
||||
int itemCount = 0;
|
||||
int entityCount = 0;
|
||||
|
||||
Rollback.finishRollbackRestore(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, file, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, 0);
|
||||
RollbackComplete.output(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, file, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, 0);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
||||
@@ -372,7 +372,7 @@ public class Database extends Queue {
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "session(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int (3), z int, action tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(time)";
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "sign(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int, user int, wid int, x int, y int, z int, action tinyint, color int, color_secondary int, data tinyint, waxed tinyint, face tinyint, line_1 varchar(100), line_2 varchar(100), line_3 varchar(100), line_4 varchar(100), line_5 varchar(100), line_6 varchar(100), line_7 varchar(100), line_8 varchar(100)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, owner varchar(64)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, owner varchar(255)) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
index = ", INDEX(user), INDEX(uuid)";
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "user(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),time int,user varchar(100),uuid varchar(64)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
index = ", INDEX(uuid,user)";
|
||||
|
||||
@@ -29,7 +29,7 @@ import net.coreprotect.utility.Util;
|
||||
|
||||
public class Lookup extends Queue {
|
||||
|
||||
static List<String[]> convertRawLookup(Statement statement, List<Object[]> list) {
|
||||
protected static List<String[]> convertRawLookup(Statement statement, List<Object[]> list) {
|
||||
List<String[]> newList = new ArrayList<>();
|
||||
|
||||
if (list == null) {
|
||||
@@ -122,7 +122,7 @@ public class Lookup extends Queue {
|
||||
return newList;
|
||||
}
|
||||
|
||||
static List<Object[]> performLookupRaw(Statement statement, CommandSender user, List<String> checkUuids, List<String> checkUsers, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, Location location, Integer[] radius, Long[] rowData, long startTime, long endTime, int limitOffset, int limitCount, boolean restrictWorld, boolean lookup) {
|
||||
protected static List<Object[]> performLookupRaw(Statement statement, CommandSender user, List<String> checkUuids, List<String> checkUsers, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, Location location, Integer[] radius, Long[] rowData, long startTime, long endTime, int limitOffset, int limitCount, boolean restrictWorld, boolean lookup) {
|
||||
List<Object[]> list = new ArrayList<>();
|
||||
List<Integer> invalidRollbackActions = new ArrayList<>();
|
||||
invalidRollbackActions.add(2);
|
||||
|
||||
+4
-753
@@ -1,10 +1,7 @@
|
||||
package net.coreprotect.database;
|
||||
package net.coreprotect.database.rollback;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.sql.Statement;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -20,14 +17,9 @@ import java.util.UUID;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.FireworkEffect.Builder;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.Banner;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
@@ -35,7 +27,6 @@ import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.CommandBlock;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.block.Jukebox;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.Bisected.Half;
|
||||
@@ -65,18 +56,6 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BannerMeta;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.CrossbowMeta;
|
||||
import org.bukkit.inventory.meta.FireworkEffectMeta;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.inventory.meta.SuspiciousStewMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.io.BukkitObjectInputStream;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
@@ -85,6 +64,7 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.database.Lookup;
|
||||
import net.coreprotect.database.logger.ItemLogger;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.language.Phrase;
|
||||
@@ -100,7 +80,7 @@ import net.coreprotect.utility.Teleport;
|
||||
import net.coreprotect.utility.Util;
|
||||
import net.coreprotect.utility.entity.HangingUtil;
|
||||
|
||||
public class Rollback extends Queue {
|
||||
public class Rollback extends RollbackUtil {
|
||||
|
||||
public static List<String[]> performRollbackRestore(Statement statement, CommandSender user, List<String> checkUuids, List<String> checkUsers, String timeString, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, Location location, Integer[] radius, long startTime, long endTime, boolean restrictWorld, boolean lookup, boolean verbose, final int rollbackType, final int preview) {
|
||||
List<String[]> list = new ArrayList<>();
|
||||
@@ -1337,7 +1317,7 @@ public class Rollback extends Queue {
|
||||
double totalSeconds = (timeFinish - timeStart) / 1000.0;
|
||||
|
||||
if (user != null) {
|
||||
finishRollbackRestore(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, chunkCount, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, preview);
|
||||
RollbackComplete.output(user, location, checkUsers, restrictList, excludeList, excludeUserList, actionList, timeString, chunkCount, totalSeconds, itemCount, blockCount, entityCount, rollbackType, radius, verbose, restrictWorld, preview);
|
||||
}
|
||||
|
||||
list = Lookup.convertRawLookup(statement, lookupList);
|
||||
@@ -1350,733 +1330,4 @@ public class Rollback extends Queue {
|
||||
return null;
|
||||
}
|
||||
|
||||
static void finishRollbackRestore(CommandSender user, Location location, List<String> checkUsers, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, String timeString, Integer chunkCount, Double seconds, Integer itemCount, Integer blockCount, Integer entityCount, int rollbackType, Integer[] radius, boolean verbose, boolean restrictWorld, int preview) {
|
||||
try {
|
||||
if (preview == 2) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_CANCELLED));
|
||||
return;
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, "-----");
|
||||
|
||||
StringBuilder usersBuilder = new StringBuilder();
|
||||
for (String value : checkUsers) {
|
||||
if (usersBuilder.length() == 0) {
|
||||
usersBuilder = usersBuilder.append("" + value + "");
|
||||
}
|
||||
else {
|
||||
usersBuilder.append(", ").append(value);
|
||||
}
|
||||
}
|
||||
String users = usersBuilder.toString();
|
||||
|
||||
if (users.equals("#global") && restrictWorld) {
|
||||
users = "#" + location.getWorld().getName();
|
||||
}
|
||||
|
||||
if (preview > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.THIRD)); // preview
|
||||
}
|
||||
else if (rollbackType == 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.FIRST)); // rollback
|
||||
}
|
||||
else if (rollbackType == 1) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.SECOND)); // restore
|
||||
}
|
||||
|
||||
if (preview == 1 || rollbackType == 0 || rollbackType == 1) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_TIME, timeString));
|
||||
}
|
||||
|
||||
if (radius != null) {
|
||||
int worldedit = radius[7];
|
||||
if (worldedit == 0) {
|
||||
Integer rollbackRadius = radius[0];
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_RADIUS, rollbackRadius.toString(), (rollbackRadius == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_SELECTION, "#worldedit"));
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictWorld && radius == null) {
|
||||
if (location != null) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, location.getWorld().getName(), Selector.FIRST));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+inventory", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-inventory", Selector.SECOND));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "inventory", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
else if (actionList.contains(4)) {
|
||||
if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-container", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+container", Selector.SECOND));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "container", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
else if (actionList.contains(0) && actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(3)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "kill", Selector.SECOND));
|
||||
}
|
||||
|
||||
if (restrictList.size() > 0) {
|
||||
StringBuilder restrictTargets = new StringBuilder();
|
||||
boolean material = false;
|
||||
boolean item = false;
|
||||
boolean entity = false;
|
||||
|
||||
int targetCount = 0;
|
||||
for (Object restrictTarget : restrictList) {
|
||||
String targetName = "";
|
||||
|
||||
if (restrictTarget instanceof Material) {
|
||||
targetName = ((Material) restrictTarget).name().toLowerCase(Locale.ROOT);
|
||||
item = (!item ? !(((Material) restrictTarget).isBlock()) : item);
|
||||
material = true;
|
||||
}
|
||||
else if (restrictTarget instanceof EntityType) {
|
||||
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
|
||||
entity = true;
|
||||
}
|
||||
|
||||
if (targetCount == 0) {
|
||||
restrictTargets = restrictTargets.append("" + targetName + "");
|
||||
}
|
||||
else {
|
||||
restrictTargets.append(", ").append(targetName);
|
||||
}
|
||||
|
||||
targetCount++;
|
||||
}
|
||||
|
||||
String targetType = Selector.THIRD;
|
||||
if (material && !item && !entity) {
|
||||
targetType = Selector.FIRST;
|
||||
}
|
||||
else if (material && item && !entity) {
|
||||
targetType = Selector.THIRD;
|
||||
}
|
||||
else if (entity && !material) {
|
||||
targetType = Selector.SECOND;
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, restrictTargets.toString(), Selector.FIRST, targetType, (targetCount == 1 ? Selector.FIRST : Selector.SECOND))); // include
|
||||
}
|
||||
|
||||
if (excludeList.size() > 0) {
|
||||
StringBuilder excludeTargets = new StringBuilder();
|
||||
boolean material = false;
|
||||
boolean item = false;
|
||||
boolean entity = false;
|
||||
|
||||
int excludeCount = 0;
|
||||
for (Map.Entry<Object, Boolean> entry : excludeList.entrySet()) {
|
||||
Object excludeTarget = entry.getKey();
|
||||
Boolean excludeTargetInternal = entry.getValue();
|
||||
|
||||
// don't display default block excludes
|
||||
if (Boolean.TRUE.equals(excludeTargetInternal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't display that excluded water/fire/farmland in inventory rollbacks
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (excludeTarget.equals(Material.FIRE) || excludeTarget.equals(Material.WATER) || excludeTarget.equals(Material.FARMLAND)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String targetName = "";
|
||||
if (excludeTarget instanceof Material) {
|
||||
targetName = ((Material) excludeTarget).name().toLowerCase(Locale.ROOT);
|
||||
item = (!item ? !(((Material) excludeTarget).isBlock()) : item);
|
||||
material = true;
|
||||
}
|
||||
else if (excludeTarget instanceof EntityType) {
|
||||
targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT);
|
||||
entity = true;
|
||||
}
|
||||
|
||||
if (excludeCount == 0) {
|
||||
excludeTargets = excludeTargets.append("" + targetName + "");
|
||||
}
|
||||
else {
|
||||
excludeTargets.append(", ").append(targetName);
|
||||
}
|
||||
|
||||
excludeCount++;
|
||||
}
|
||||
|
||||
String targetType = Selector.THIRD;
|
||||
if (material && !item && !entity) {
|
||||
targetType = Selector.FIRST;
|
||||
}
|
||||
else if (material && item && !entity) {
|
||||
targetType = Selector.THIRD;
|
||||
}
|
||||
else if (entity && !material) {
|
||||
targetType = Selector.SECOND;
|
||||
}
|
||||
|
||||
if (excludeCount > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, excludeTargets.toString(), Selector.SECOND, targetType, (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); // exclude
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeUserList.size() > 0) {
|
||||
StringBuilder excludeUsers = new StringBuilder();
|
||||
|
||||
int excludeCount = 0;
|
||||
for (String excludeUser : excludeUserList) {
|
||||
// don't display that excluded #hopper in inventory rollbacks
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (excludeUser.equals("#hopper")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeCount == 0) {
|
||||
excludeUsers = excludeUsers.append("" + excludeUser + "");
|
||||
}
|
||||
else {
|
||||
excludeUsers.append(", ").append(excludeUser);
|
||||
}
|
||||
|
||||
excludeCount++;
|
||||
}
|
||||
|
||||
if (excludeCount > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder modifiedData = new StringBuilder();
|
||||
Integer modifyCount = 0;
|
||||
if (actionList.contains(5)) {
|
||||
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
else {
|
||||
if (itemCount > 0 || actionList.contains(4)) {
|
||||
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(itemCount), (itemCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
|
||||
if (entityCount > 0) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_ENTITY, NumberFormat.getInstance().format(entityCount), (entityCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
|
||||
if (blockCount > 0 || !actionList.contains(4) || preview > 0) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder modifiedDataVerbose = new StringBuilder();
|
||||
if (verbose && preview == 0 && !actionList.contains(11)) {
|
||||
if (chunkCount > -1 && modifyCount < 3) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
else if (chunkCount > 1) {
|
||||
modifiedDataVerbose.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedData.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND)));
|
||||
if (modifiedDataVerbose.length() > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedDataVerbose.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
|
||||
if (preview == 0) {
|
||||
BigDecimal decimalSeconds = new BigDecimal(seconds).setScale(1, RoundingMode.HALF_EVEN);
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_LENGTH, decimalSeconds.stripTrailingZeros().toPlainString(), (decimalSeconds.doubleValue() == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, "-----");
|
||||
if (preview > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PLEASE_SELECT, "/co apply", "/co cancel"));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
static int modifyContainerItems(Material type, Object container, int slot, ItemStack itemstack, int action) {
|
||||
int modifiedArmor = -1;
|
||||
try {
|
||||
ItemStack[] contents = null;
|
||||
|
||||
if (type != null && type.equals(Material.ARMOR_STAND)) {
|
||||
EntityEquipment equipment = (EntityEquipment) container;
|
||||
if (equipment != null) {
|
||||
if (action == 1) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
if (slot < 4) {
|
||||
contents = equipment.getArmorContents();
|
||||
if (slot >= 0) {
|
||||
contents[slot] = itemstack;
|
||||
}
|
||||
equipment.setArmorContents(contents);
|
||||
}
|
||||
else {
|
||||
ArmorStand armorStand = (ArmorStand) equipment.getHolder();
|
||||
armorStand.setArms(true);
|
||||
switch (slot) {
|
||||
case 4:
|
||||
equipment.setItemInMainHand(itemstack);
|
||||
break;
|
||||
case 5:
|
||||
equipment.setItemInOffHand(itemstack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type != null && type.equals(Material.ITEM_FRAME)) {
|
||||
ItemFrame frame = (ItemFrame) container;
|
||||
if (frame != null) {
|
||||
if (action == 1) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
frame.setItem(itemstack);
|
||||
}
|
||||
}
|
||||
else if (type != null && type.equals(Material.JUKEBOX)) {
|
||||
Jukebox jukebox = (Jukebox) container;
|
||||
if (jukebox != null) {
|
||||
if (action == 1 && Tag.ITEMS_MUSIC_DISCS.isTagged(itemstack.getType())) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
jukebox.setRecord(itemstack);
|
||||
jukebox.update();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Inventory inventory = (Inventory) container;
|
||||
if (inventory != null) {
|
||||
boolean isPlayerInventory = (inventory instanceof PlayerInventory);
|
||||
if (action == 1) {
|
||||
int count = 0;
|
||||
int amount = itemstack.getAmount();
|
||||
itemstack.setAmount(1);
|
||||
|
||||
while (count < amount) {
|
||||
boolean addedItem = false;
|
||||
if (isPlayerInventory) {
|
||||
int setArmor = Util.setPlayerArmor((PlayerInventory) inventory, itemstack);
|
||||
addedItem = (setArmor > -1);
|
||||
modifiedArmor = addedItem ? setArmor : modifiedArmor;
|
||||
}
|
||||
if (!addedItem) {
|
||||
if (BukkitAdapter.ADAPTER.isChiseledBookshelf(type)) {
|
||||
ItemStack[] inventoryContents = inventory.getStorageContents();
|
||||
int i = 0;
|
||||
for (ItemStack stack : inventoryContents) {
|
||||
if (stack == null) {
|
||||
inventoryContents[i] = itemstack;
|
||||
addedItem = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (addedItem) {
|
||||
inventory.setStorageContents(inventoryContents);
|
||||
}
|
||||
else {
|
||||
addedItem = (inventory.addItem(itemstack).size() == 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addedItem = (inventory.addItem(itemstack).size() == 0);
|
||||
}
|
||||
}
|
||||
if (!addedItem && isPlayerInventory) {
|
||||
PlayerInventory playerInventory = (PlayerInventory) inventory;
|
||||
ItemStack offhand = playerInventory.getItemInOffHand();
|
||||
if (offhand == null || offhand.getType() == Material.AIR || (itemstack.isSimilar(offhand) && offhand.getAmount() < offhand.getMaxStackSize())) {
|
||||
ItemStack setOffhand = itemstack.clone();
|
||||
if (itemstack.isSimilar(offhand)) {
|
||||
setOffhand.setAmount(offhand.getAmount() + 1);
|
||||
}
|
||||
|
||||
playerInventory.setItemInOffHand(setOffhand);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int removeAmount = itemstack.getAmount();
|
||||
ItemStack removeMatch = itemstack.clone();
|
||||
removeMatch.setAmount(1);
|
||||
|
||||
ItemStack[] inventoryContents = (isPlayerInventory ? inventory.getContents() : inventory.getStorageContents()).clone();
|
||||
for (int i = inventoryContents.length - 1; i >= 0; i--) {
|
||||
if (inventoryContents[i] != null) {
|
||||
ItemStack itemStack = inventoryContents[i].clone();
|
||||
int maxAmount = itemStack.getAmount();
|
||||
int currentAmount = maxAmount;
|
||||
itemStack.setAmount(1);
|
||||
|
||||
if (itemStack.toString().equals(removeMatch.toString())) {
|
||||
for (int scan = 0; scan < maxAmount; scan++) {
|
||||
if (removeAmount > 0) {
|
||||
currentAmount--;
|
||||
itemStack.setAmount(currentAmount);
|
||||
removeAmount--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
itemStack.setAmount(maxAmount);
|
||||
}
|
||||
|
||||
if (itemStack.getAmount() == 0) {
|
||||
inventoryContents[i] = null;
|
||||
}
|
||||
else {
|
||||
inventoryContents[i] = itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeAmount == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPlayerInventory) {
|
||||
inventory.setContents(inventoryContents);
|
||||
}
|
||||
else {
|
||||
inventory.setStorageContents(inventoryContents);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while (count < removeAmount) {
|
||||
inventory.removeItem(removeMatch);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return modifiedArmor;
|
||||
}
|
||||
|
||||
public static void sortContainerItems(PlayerInventory inventory, List<Integer> modifiedArmorSlots) {
|
||||
try {
|
||||
ItemStack[] armorContents = inventory.getArmorContents();
|
||||
ItemStack[] storageContents = inventory.getStorageContents();
|
||||
|
||||
for (int armor = 0; armor < armorContents.length; armor++) {
|
||||
ItemStack armorItem = armorContents[armor];
|
||||
if (armorItem == null || !modifiedArmorSlots.contains(armor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int storage = 0; storage < storageContents.length; storage++) {
|
||||
ItemStack storageItem = storageContents[storage];
|
||||
if (storageItem == null) {
|
||||
storageContents[storage] = armorItem;
|
||||
armorContents[armor] = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inventory.setArmorContents(armorContents);
|
||||
inventory.setStorageContents(storageContents);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildFireworkEffect(Builder effectBuilder, Material rowType, ItemStack itemstack) {
|
||||
try {
|
||||
FireworkEffect effect = effectBuilder.build();
|
||||
if ((rowType == Material.FIREWORK_ROCKET)) {
|
||||
FireworkMeta meta = (FireworkMeta) itemstack.getItemMeta();
|
||||
meta.addEffect(effect);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if ((rowType == Material.FIREWORK_STAR)) {
|
||||
FireworkEffectMeta meta = (FireworkEffectMeta) itemstack.getItemMeta();
|
||||
meta.setEffect(effect);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object[] populateItemStack(ItemStack itemstack, Object list) {
|
||||
int slot = 0;
|
||||
String faceData = "";
|
||||
|
||||
try {
|
||||
/*
|
||||
if (list instanceof Object[]) {
|
||||
slot = (int) ((Object[]) list)[0];
|
||||
ItemMeta itemMeta = (ItemMeta) ((Object[]) list)[1];
|
||||
itemstack.setItemMeta(itemMeta);
|
||||
return new Object[] { slot, itemstack };
|
||||
}
|
||||
*/
|
||||
|
||||
Material rowType = itemstack.getType();
|
||||
List<Object> metaList = (List<Object>) list;
|
||||
if (metaList.size() > 0 && !(metaList.get(0) instanceof List<?>)) {
|
||||
if (rowType.name().endsWith("_BANNER")) {
|
||||
BannerMeta meta = (BannerMeta) itemstack.getItemMeta();
|
||||
for (Object value : metaList) {
|
||||
if (value instanceof Map) {
|
||||
Pattern pattern = new Pattern((Map<String, Object>) value);
|
||||
meta.addPattern(pattern);
|
||||
}
|
||||
}
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if (BlockGroup.SHULKER_BOXES.contains(rowType)) {
|
||||
BlockStateMeta meta = (BlockStateMeta) itemstack.getItemMeta();
|
||||
ShulkerBox shulkerBox = (ShulkerBox) meta.getBlockState();
|
||||
for (Object value : metaList) {
|
||||
ItemStack item = Util.unserializeItemStackLegacy(value);
|
||||
if (item != null) {
|
||||
shulkerBox.getInventory().addItem(item);
|
||||
}
|
||||
}
|
||||
meta.setBlockState(shulkerBox);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return new Object[] { slot, faceData, itemstack };
|
||||
}
|
||||
|
||||
int itemCount = 0;
|
||||
Builder effectBuilder = FireworkEffect.builder();
|
||||
for (List<Map<String, Object>> map : (List<List<Map<String, Object>>>) list) {
|
||||
if (map.size() == 0) {
|
||||
if (itemCount == 3 && (rowType == Material.FIREWORK_ROCKET || rowType == Material.FIREWORK_STAR)) {
|
||||
buildFireworkEffect(effectBuilder, rowType, itemstack);
|
||||
itemCount = 0;
|
||||
}
|
||||
|
||||
itemCount++;
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> mapData = map.get(0);
|
||||
|
||||
if (mapData.get("slot") != null) {
|
||||
slot = (Integer) mapData.get("slot");
|
||||
}
|
||||
else if (mapData.get("facing") != null) {
|
||||
faceData = (String) mapData.get("facing");
|
||||
}
|
||||
else if (mapData.get("modifiers") != null) {
|
||||
ItemMeta itemMeta = itemstack.getItemMeta();
|
||||
if (itemMeta.hasAttributeModifiers()) {
|
||||
for (Map.Entry<Attribute, AttributeModifier> entry : itemMeta.getAttributeModifiers().entries()) {
|
||||
itemMeta.removeAttributeModifier(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
List<Object> modifiers = (List<Object>) mapData.get("modifiers");
|
||||
|
||||
for (Object item : modifiers) {
|
||||
Map<Attribute, Map<String, Object>> modifiersMap = (Map<Attribute, Map<String, Object>>) item;
|
||||
for (Map.Entry<Attribute, Map<String, Object>> entry : modifiersMap.entrySet()) {
|
||||
try {
|
||||
Attribute attribute = entry.getKey();
|
||||
AttributeModifier modifier = AttributeModifier.deserialize(entry.getValue());
|
||||
itemMeta.addAttributeModifier(attribute, modifier);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// AttributeModifier already exists
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemstack.setItemMeta(itemMeta);
|
||||
}
|
||||
else if (itemCount == 0) {
|
||||
ItemMeta meta = Util.deserializeItemMeta(itemstack.getItemMeta().getClass(), map.get(0));
|
||||
itemstack.setItemMeta(meta);
|
||||
|
||||
if (map.size() > 1 && (rowType == Material.POTION)) {
|
||||
PotionMeta subMeta = (PotionMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(map.get(1));
|
||||
subMeta.setColor(color);
|
||||
itemstack.setItemMeta(subMeta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((rowType == Material.LEATHER_HORSE_ARMOR) || (rowType == Material.LEATHER_HELMET) || (rowType == Material.LEATHER_CHESTPLATE) || (rowType == Material.LEATHER_LEGGINGS) || (rowType == Material.LEATHER_BOOTS)) { // leather armor
|
||||
for (Map<String, Object> colorData : map) {
|
||||
LeatherArmorMeta meta = (LeatherArmorMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
meta.setColor(color);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.POTION)) { // potion
|
||||
for (Map<String, Object> potionData : map) {
|
||||
PotionMeta meta = (PotionMeta) itemstack.getItemMeta();
|
||||
PotionEffect effect = new PotionEffect(potionData);
|
||||
meta.addCustomEffect(effect, true);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if (rowType.name().endsWith("_BANNER")) {
|
||||
for (Map<String, Object> patternData : map) {
|
||||
BannerMeta meta = (BannerMeta) itemstack.getItemMeta();
|
||||
Pattern pattern = new Pattern(patternData);
|
||||
meta.addPattern(pattern);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.CROSSBOW)) {
|
||||
CrossbowMeta meta = (CrossbowMeta) itemstack.getItemMeta();
|
||||
for (Map<String, Object> itemData : map) {
|
||||
ItemStack crossbowItem = Util.unserializeItemStack(itemData);
|
||||
if (crossbowItem != null) {
|
||||
meta.addChargedProjectile(crossbowItem);
|
||||
}
|
||||
}
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if (rowType == Material.MAP || rowType == Material.FILLED_MAP) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
MapMeta meta = (MapMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
meta.setColor(color);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.FIREWORK_ROCKET) || (rowType == Material.FIREWORK_STAR)) {
|
||||
if (itemCount == 1) {
|
||||
effectBuilder = FireworkEffect.builder();
|
||||
for (Map<String, Object> fireworkData : map) {
|
||||
org.bukkit.FireworkEffect.Type type = (org.bukkit.FireworkEffect.Type) fireworkData.getOrDefault("type", org.bukkit.FireworkEffect.Type.BALL);
|
||||
boolean hasFlicker = (Boolean) fireworkData.get("flicker");
|
||||
boolean hasTrail = (Boolean) fireworkData.get("trail");
|
||||
effectBuilder.with(type);
|
||||
effectBuilder.flicker(hasFlicker);
|
||||
effectBuilder.trail(hasTrail);
|
||||
}
|
||||
}
|
||||
else if (itemCount == 2) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
effectBuilder.withColor(color);
|
||||
}
|
||||
}
|
||||
else if (itemCount == 3) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
effectBuilder.withFade(color);
|
||||
}
|
||||
buildFireworkEffect(effectBuilder, rowType, itemstack);
|
||||
itemCount = 0;
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.SUSPICIOUS_STEW)) {
|
||||
for (Map<String, Object> suspiciousStewData : map) {
|
||||
SuspiciousStewMeta meta = (SuspiciousStewMeta) itemstack.getItemMeta();
|
||||
PotionEffect effect = new PotionEffect(suspiciousStewData);
|
||||
meta.addCustomEffect(effect, true);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BukkitAdapter.ADAPTER.setItemMeta(rowType, itemstack, map);
|
||||
}
|
||||
}
|
||||
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new Object[] { slot, faceData, itemstack };
|
||||
}
|
||||
|
||||
public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) {
|
||||
if (metadata != null) {
|
||||
try {
|
||||
ByteArrayInputStream metaByteStream = new ByteArrayInputStream(metadata);
|
||||
BukkitObjectInputStream metaObjectStream = new BukkitObjectInputStream(metaByteStream);
|
||||
Object metaList = metaObjectStream.readObject();
|
||||
metaObjectStream.close();
|
||||
metaByteStream.close();
|
||||
|
||||
return populateItemStack(itemstack, metaList);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return new Object[] { 0, "", itemstack };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,306 @@
|
||||
package net.coreprotect.database.rollback;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
|
||||
public class RollbackComplete {
|
||||
|
||||
public static void output(CommandSender user, Location location, List<String> checkUsers, List<Object> restrictList, Map<Object, Boolean> excludeList, List<String> excludeUserList, List<Integer> actionList, String timeString, Integer chunkCount, Double seconds, Integer itemCount, Integer blockCount, Integer entityCount, int rollbackType, Integer[] radius, boolean verbose, boolean restrictWorld, int preview) {
|
||||
try {
|
||||
if (preview == 2) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_CANCELLED));
|
||||
return;
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, "-----");
|
||||
|
||||
StringBuilder usersBuilder = new StringBuilder();
|
||||
for (String value : checkUsers) {
|
||||
if (usersBuilder.length() == 0) {
|
||||
usersBuilder = usersBuilder.append("" + value + "");
|
||||
}
|
||||
else {
|
||||
usersBuilder.append(", ").append(value);
|
||||
}
|
||||
}
|
||||
String users = usersBuilder.toString();
|
||||
|
||||
if (users.equals("#global") && restrictWorld) {
|
||||
users = "#" + location.getWorld().getName();
|
||||
}
|
||||
|
||||
if (preview > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.THIRD)); // preview
|
||||
}
|
||||
else if (rollbackType == 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.FIRST)); // rollback
|
||||
}
|
||||
else if (rollbackType == 1) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_COMPLETED, users, Selector.SECOND)); // restore
|
||||
}
|
||||
|
||||
if (preview == 1 || rollbackType == 0 || rollbackType == 1) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_TIME, timeString));
|
||||
}
|
||||
|
||||
if (radius != null) {
|
||||
int worldedit = radius[7];
|
||||
if (worldedit == 0) {
|
||||
Integer rollbackRadius = radius[0];
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_RADIUS, rollbackRadius.toString(), (rollbackRadius == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_SELECTION, "#worldedit"));
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictWorld && radius == null) {
|
||||
if (location != null) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, location.getWorld().getName(), Selector.FIRST));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+inventory", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-inventory", Selector.SECOND));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "inventory", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
else if (actionList.contains(4)) {
|
||||
if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-container", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+container", Selector.SECOND));
|
||||
}
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "container", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
else if (actionList.contains(0) && actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(0)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "-block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(1)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "+block", Selector.SECOND));
|
||||
}
|
||||
else if (actionList.contains(3)) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_WORLD_ACTION, "kill", Selector.SECOND));
|
||||
}
|
||||
|
||||
if (restrictList.size() > 0) {
|
||||
StringBuilder restrictTargets = new StringBuilder();
|
||||
boolean material = false;
|
||||
boolean item = false;
|
||||
boolean entity = false;
|
||||
|
||||
int targetCount = 0;
|
||||
for (Object restrictTarget : restrictList) {
|
||||
String targetName = "";
|
||||
|
||||
if (restrictTarget instanceof Material) {
|
||||
targetName = ((Material) restrictTarget).name().toLowerCase(Locale.ROOT);
|
||||
item = (!item ? !(((Material) restrictTarget).isBlock()) : item);
|
||||
material = true;
|
||||
}
|
||||
else if (restrictTarget instanceof EntityType) {
|
||||
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
|
||||
entity = true;
|
||||
}
|
||||
|
||||
if (targetCount == 0) {
|
||||
restrictTargets = restrictTargets.append("" + targetName + "");
|
||||
}
|
||||
else {
|
||||
restrictTargets.append(", ").append(targetName);
|
||||
}
|
||||
|
||||
targetCount++;
|
||||
}
|
||||
|
||||
String targetType = Selector.THIRD;
|
||||
if (material && !item && !entity) {
|
||||
targetType = Selector.FIRST;
|
||||
}
|
||||
else if (material && item && !entity) {
|
||||
targetType = Selector.THIRD;
|
||||
}
|
||||
else if (entity && !material) {
|
||||
targetType = Selector.SECOND;
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, restrictTargets.toString(), Selector.FIRST, targetType, (targetCount == 1 ? Selector.FIRST : Selector.SECOND))); // include
|
||||
}
|
||||
|
||||
if (excludeList.size() > 0) {
|
||||
StringBuilder excludeTargets = new StringBuilder();
|
||||
boolean material = false;
|
||||
boolean item = false;
|
||||
boolean entity = false;
|
||||
|
||||
int excludeCount = 0;
|
||||
for (Map.Entry<Object, Boolean> entry : excludeList.entrySet()) {
|
||||
Object excludeTarget = entry.getKey();
|
||||
Boolean excludeTargetInternal = entry.getValue();
|
||||
|
||||
// don't display default block excludes
|
||||
if (Boolean.TRUE.equals(excludeTargetInternal)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// don't display that excluded water/fire/farmland in inventory rollbacks
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (excludeTarget.equals(Material.FIRE) || excludeTarget.equals(Material.WATER) || excludeTarget.equals(Material.FARMLAND)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
String targetName = "";
|
||||
if (excludeTarget instanceof Material) {
|
||||
targetName = ((Material) excludeTarget).name().toLowerCase(Locale.ROOT);
|
||||
item = (!item ? !(((Material) excludeTarget).isBlock()) : item);
|
||||
material = true;
|
||||
}
|
||||
else if (excludeTarget instanceof EntityType) {
|
||||
targetName = ((EntityType) excludeTarget).name().toLowerCase(Locale.ROOT);
|
||||
entity = true;
|
||||
}
|
||||
|
||||
if (excludeCount == 0) {
|
||||
excludeTargets = excludeTargets.append("" + targetName + "");
|
||||
}
|
||||
else {
|
||||
excludeTargets.append(", ").append(targetName);
|
||||
}
|
||||
|
||||
excludeCount++;
|
||||
}
|
||||
|
||||
String targetType = Selector.THIRD;
|
||||
if (material && !item && !entity) {
|
||||
targetType = Selector.FIRST;
|
||||
}
|
||||
else if (material && item && !entity) {
|
||||
targetType = Selector.THIRD;
|
||||
}
|
||||
else if (entity && !material) {
|
||||
targetType = Selector.SECOND;
|
||||
}
|
||||
|
||||
if (excludeCount > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_INCLUDE, excludeTargets.toString(), Selector.SECOND, targetType, (excludeCount == 1 ? Selector.FIRST : Selector.SECOND))); // exclude
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeUserList.size() > 0) {
|
||||
StringBuilder excludeUsers = new StringBuilder();
|
||||
|
||||
int excludeCount = 0;
|
||||
for (String excludeUser : excludeUserList) {
|
||||
// don't display that excluded #hopper in inventory rollbacks
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (excludeUser.equals("#hopper")) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (excludeCount == 0) {
|
||||
excludeUsers = excludeUsers.append("" + excludeUser + "");
|
||||
}
|
||||
else {
|
||||
excludeUsers.append(", ").append(excludeUser);
|
||||
}
|
||||
|
||||
excludeCount++;
|
||||
}
|
||||
|
||||
if (excludeCount > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_EXCLUDED_USERS, excludeUsers.toString(), (excludeCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder modifiedData = new StringBuilder();
|
||||
Integer modifyCount = 0;
|
||||
if (actionList.contains(5)) {
|
||||
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
else {
|
||||
if (itemCount > 0 || actionList.contains(4)) {
|
||||
modifiedData = modifiedData.append(Phrase.build(Phrase.AMOUNT_ITEM, NumberFormat.getInstance().format(itemCount), (itemCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
|
||||
if (entityCount > 0) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_ENTITY, NumberFormat.getInstance().format(entityCount), (entityCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
|
||||
if (blockCount > 0 || !actionList.contains(4) || preview > 0) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_BLOCK, NumberFormat.getInstance().format(blockCount), (blockCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder modifiedDataVerbose = new StringBuilder();
|
||||
if (verbose && preview == 0 && !actionList.contains(11)) {
|
||||
if (chunkCount > -1 && modifyCount < 3) {
|
||||
if (modifyCount > 0) {
|
||||
modifiedData.append(", ");
|
||||
}
|
||||
modifiedData.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
modifyCount++;
|
||||
}
|
||||
else if (chunkCount > 1) {
|
||||
modifiedDataVerbose.append(Phrase.build(Phrase.AMOUNT_CHUNK, NumberFormat.getInstance().format(chunkCount), (chunkCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedData.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND)));
|
||||
if (modifiedDataVerbose.length() > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_MODIFIED, modifiedDataVerbose.toString(), (preview == 0 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
|
||||
if (preview == 0) {
|
||||
BigDecimal decimalSeconds = new BigDecimal(seconds).setScale(1, RoundingMode.HALF_EVEN);
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ROLLBACK_LENGTH, decimalSeconds.stripTrailingZeros().toPlainString(), (decimalSeconds.doubleValue() == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
|
||||
Chat.sendMessage(user, "-----");
|
||||
if (preview > 0) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PLEASE_SELECT, "/co apply", "/co cancel"));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,487 @@
|
||||
package net.coreprotect.database.rollback;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.FireworkEffect;
|
||||
import org.bukkit.FireworkEffect.Builder;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.block.Jukebox;
|
||||
import org.bukkit.block.ShulkerBox;
|
||||
import org.bukkit.block.banner.Pattern;
|
||||
import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.inventory.meta.BannerMeta;
|
||||
import org.bukkit.inventory.meta.BlockStateMeta;
|
||||
import org.bukkit.inventory.meta.CrossbowMeta;
|
||||
import org.bukkit.inventory.meta.FireworkEffectMeta;
|
||||
import org.bukkit.inventory.meta.FireworkMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.inventory.meta.SuspiciousStewMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.util.io.BukkitObjectInputStream;
|
||||
|
||||
import net.coreprotect.bukkit.BukkitAdapter;
|
||||
import net.coreprotect.database.Lookup;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.utility.Util;
|
||||
|
||||
public class RollbackUtil extends Lookup {
|
||||
|
||||
protected static int modifyContainerItems(Material type, Object container, int slot, ItemStack itemstack, int action) {
|
||||
int modifiedArmor = -1;
|
||||
try {
|
||||
ItemStack[] contents = null;
|
||||
|
||||
if (type != null && type.equals(Material.ARMOR_STAND)) {
|
||||
EntityEquipment equipment = (EntityEquipment) container;
|
||||
if (equipment != null) {
|
||||
if (action == 1) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
if (slot < 4) {
|
||||
contents = equipment.getArmorContents();
|
||||
if (slot >= 0) {
|
||||
contents[slot] = itemstack;
|
||||
}
|
||||
equipment.setArmorContents(contents);
|
||||
}
|
||||
else {
|
||||
ArmorStand armorStand = (ArmorStand) equipment.getHolder();
|
||||
armorStand.setArms(true);
|
||||
switch (slot) {
|
||||
case 4:
|
||||
equipment.setItemInMainHand(itemstack);
|
||||
break;
|
||||
case 5:
|
||||
equipment.setItemInOffHand(itemstack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type != null && type.equals(Material.ITEM_FRAME)) {
|
||||
ItemFrame frame = (ItemFrame) container;
|
||||
if (frame != null) {
|
||||
if (action == 1) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
frame.setItem(itemstack);
|
||||
}
|
||||
}
|
||||
else if (type != null && type.equals(Material.JUKEBOX)) {
|
||||
Jukebox jukebox = (Jukebox) container;
|
||||
if (jukebox != null) {
|
||||
if (action == 1 && Tag.ITEMS_MUSIC_DISCS.isTagged(itemstack.getType())) {
|
||||
itemstack.setAmount(1);
|
||||
}
|
||||
else {
|
||||
itemstack.setType(Material.AIR);
|
||||
itemstack.setAmount(0);
|
||||
}
|
||||
|
||||
jukebox.setRecord(itemstack);
|
||||
jukebox.update();
|
||||
}
|
||||
}
|
||||
else {
|
||||
Inventory inventory = (Inventory) container;
|
||||
if (inventory != null) {
|
||||
boolean isPlayerInventory = (inventory instanceof PlayerInventory);
|
||||
if (action == 1) {
|
||||
int count = 0;
|
||||
int amount = itemstack.getAmount();
|
||||
itemstack.setAmount(1);
|
||||
|
||||
while (count < amount) {
|
||||
boolean addedItem = false;
|
||||
if (isPlayerInventory) {
|
||||
int setArmor = Util.setPlayerArmor((PlayerInventory) inventory, itemstack);
|
||||
addedItem = (setArmor > -1);
|
||||
modifiedArmor = addedItem ? setArmor : modifiedArmor;
|
||||
}
|
||||
if (!addedItem) {
|
||||
if (BukkitAdapter.ADAPTER.isChiseledBookshelf(type)) {
|
||||
ItemStack[] inventoryContents = inventory.getStorageContents();
|
||||
int i = 0;
|
||||
for (ItemStack stack : inventoryContents) {
|
||||
if (stack == null) {
|
||||
inventoryContents[i] = itemstack;
|
||||
addedItem = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (addedItem) {
|
||||
inventory.setStorageContents(inventoryContents);
|
||||
}
|
||||
else {
|
||||
addedItem = (inventory.addItem(itemstack).size() == 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
addedItem = (inventory.addItem(itemstack).size() == 0);
|
||||
}
|
||||
}
|
||||
if (!addedItem && isPlayerInventory) {
|
||||
PlayerInventory playerInventory = (PlayerInventory) inventory;
|
||||
ItemStack offhand = playerInventory.getItemInOffHand();
|
||||
if (offhand == null || offhand.getType() == Material.AIR || (itemstack.isSimilar(offhand) && offhand.getAmount() < offhand.getMaxStackSize())) {
|
||||
ItemStack setOffhand = itemstack.clone();
|
||||
if (itemstack.isSimilar(offhand)) {
|
||||
setOffhand.setAmount(offhand.getAmount() + 1);
|
||||
}
|
||||
|
||||
playerInventory.setItemInOffHand(setOffhand);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int removeAmount = itemstack.getAmount();
|
||||
ItemStack removeMatch = itemstack.clone();
|
||||
removeMatch.setAmount(1);
|
||||
|
||||
ItemStack[] inventoryContents = (isPlayerInventory ? inventory.getContents() : inventory.getStorageContents()).clone();
|
||||
for (int i = inventoryContents.length - 1; i >= 0; i--) {
|
||||
if (inventoryContents[i] != null) {
|
||||
ItemStack itemStack = inventoryContents[i].clone();
|
||||
int maxAmount = itemStack.getAmount();
|
||||
int currentAmount = maxAmount;
|
||||
itemStack.setAmount(1);
|
||||
|
||||
if (itemStack.toString().equals(removeMatch.toString())) {
|
||||
for (int scan = 0; scan < maxAmount; scan++) {
|
||||
if (removeAmount > 0) {
|
||||
currentAmount--;
|
||||
itemStack.setAmount(currentAmount);
|
||||
removeAmount--;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
itemStack.setAmount(maxAmount);
|
||||
}
|
||||
|
||||
if (itemStack.getAmount() == 0) {
|
||||
inventoryContents[i] = null;
|
||||
}
|
||||
else {
|
||||
inventoryContents[i] = itemStack;
|
||||
}
|
||||
}
|
||||
|
||||
if (removeAmount == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPlayerInventory) {
|
||||
inventory.setContents(inventoryContents);
|
||||
}
|
||||
else {
|
||||
inventory.setStorageContents(inventoryContents);
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
while (count < removeAmount) {
|
||||
inventory.removeItem(removeMatch);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return modifiedArmor;
|
||||
}
|
||||
|
||||
public static void sortContainerItems(PlayerInventory inventory, List<Integer> modifiedArmorSlots) {
|
||||
try {
|
||||
ItemStack[] armorContents = inventory.getArmorContents();
|
||||
ItemStack[] storageContents = inventory.getStorageContents();
|
||||
|
||||
for (int armor = 0; armor < armorContents.length; armor++) {
|
||||
ItemStack armorItem = armorContents[armor];
|
||||
if (armorItem == null || !modifiedArmorSlots.contains(armor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int storage = 0; storage < storageContents.length; storage++) {
|
||||
ItemStack storageItem = storageContents[storage];
|
||||
if (storageItem == null) {
|
||||
storageContents[storage] = armorItem;
|
||||
armorContents[armor] = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inventory.setArmorContents(armorContents);
|
||||
inventory.setStorageContents(storageContents);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void buildFireworkEffect(Builder effectBuilder, Material rowType, ItemStack itemstack) {
|
||||
try {
|
||||
FireworkEffect effect = effectBuilder.build();
|
||||
if ((rowType == Material.FIREWORK_ROCKET)) {
|
||||
FireworkMeta meta = (FireworkMeta) itemstack.getItemMeta();
|
||||
meta.addEffect(effect);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if ((rowType == Material.FIREWORK_STAR)) {
|
||||
FireworkEffectMeta meta = (FireworkEffectMeta) itemstack.getItemMeta();
|
||||
meta.setEffect(effect);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Object[] populateItemStack(ItemStack itemstack, Object list) {
|
||||
int slot = 0;
|
||||
String faceData = "";
|
||||
|
||||
try {
|
||||
/*
|
||||
if (list instanceof Object[]) {
|
||||
slot = (int) ((Object[]) list)[0];
|
||||
ItemMeta itemMeta = (ItemMeta) ((Object[]) list)[1];
|
||||
itemstack.setItemMeta(itemMeta);
|
||||
return new Object[] { slot, itemstack };
|
||||
}
|
||||
*/
|
||||
|
||||
Material rowType = itemstack.getType();
|
||||
List<Object> metaList = (List<Object>) list;
|
||||
if (metaList.size() > 0 && !(metaList.get(0) instanceof List<?>)) {
|
||||
if (rowType.name().endsWith("_BANNER")) {
|
||||
BannerMeta meta = (BannerMeta) itemstack.getItemMeta();
|
||||
for (Object value : metaList) {
|
||||
if (value instanceof Map) {
|
||||
Pattern pattern = new Pattern((Map<String, Object>) value);
|
||||
meta.addPattern(pattern);
|
||||
}
|
||||
}
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if (BlockGroup.SHULKER_BOXES.contains(rowType)) {
|
||||
BlockStateMeta meta = (BlockStateMeta) itemstack.getItemMeta();
|
||||
ShulkerBox shulkerBox = (ShulkerBox) meta.getBlockState();
|
||||
for (Object value : metaList) {
|
||||
ItemStack item = Util.unserializeItemStackLegacy(value);
|
||||
if (item != null) {
|
||||
shulkerBox.getInventory().addItem(item);
|
||||
}
|
||||
}
|
||||
meta.setBlockState(shulkerBox);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return new Object[] { slot, faceData, itemstack };
|
||||
}
|
||||
|
||||
int itemCount = 0;
|
||||
Builder effectBuilder = FireworkEffect.builder();
|
||||
for (List<Map<String, Object>> map : (List<List<Map<String, Object>>>) list) {
|
||||
if (map.size() == 0) {
|
||||
if (itemCount == 3 && (rowType == Material.FIREWORK_ROCKET || rowType == Material.FIREWORK_STAR)) {
|
||||
buildFireworkEffect(effectBuilder, rowType, itemstack);
|
||||
itemCount = 0;
|
||||
}
|
||||
|
||||
itemCount++;
|
||||
continue;
|
||||
}
|
||||
Map<String, Object> mapData = map.get(0);
|
||||
|
||||
if (mapData.get("slot") != null) {
|
||||
slot = (Integer) mapData.get("slot");
|
||||
}
|
||||
else if (mapData.get("facing") != null) {
|
||||
faceData = (String) mapData.get("facing");
|
||||
}
|
||||
else if (mapData.get("modifiers") != null) {
|
||||
ItemMeta itemMeta = itemstack.getItemMeta();
|
||||
if (itemMeta.hasAttributeModifiers()) {
|
||||
for (Map.Entry<Attribute, AttributeModifier> entry : itemMeta.getAttributeModifiers().entries()) {
|
||||
itemMeta.removeAttributeModifier(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
List<Object> modifiers = (List<Object>) mapData.get("modifiers");
|
||||
|
||||
for (Object item : modifiers) {
|
||||
Map<Attribute, Map<String, Object>> modifiersMap = (Map<Attribute, Map<String, Object>>) item;
|
||||
for (Map.Entry<Attribute, Map<String, Object>> entry : modifiersMap.entrySet()) {
|
||||
try {
|
||||
Attribute attribute = entry.getKey();
|
||||
AttributeModifier modifier = AttributeModifier.deserialize(entry.getValue());
|
||||
itemMeta.addAttributeModifier(attribute, modifier);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// AttributeModifier already exists
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemstack.setItemMeta(itemMeta);
|
||||
}
|
||||
else if (itemCount == 0) {
|
||||
ItemMeta meta = Util.deserializeItemMeta(itemstack.getItemMeta().getClass(), map.get(0));
|
||||
itemstack.setItemMeta(meta);
|
||||
|
||||
if (map.size() > 1 && (rowType == Material.POTION)) {
|
||||
PotionMeta subMeta = (PotionMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(map.get(1));
|
||||
subMeta.setColor(color);
|
||||
itemstack.setItemMeta(subMeta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ((rowType == Material.LEATHER_HORSE_ARMOR) || (rowType == Material.LEATHER_HELMET) || (rowType == Material.LEATHER_CHESTPLATE) || (rowType == Material.LEATHER_LEGGINGS) || (rowType == Material.LEATHER_BOOTS)) { // leather armor
|
||||
for (Map<String, Object> colorData : map) {
|
||||
LeatherArmorMeta meta = (LeatherArmorMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
meta.setColor(color);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.POTION)) { // potion
|
||||
for (Map<String, Object> potionData : map) {
|
||||
PotionMeta meta = (PotionMeta) itemstack.getItemMeta();
|
||||
PotionEffect effect = new PotionEffect(potionData);
|
||||
meta.addCustomEffect(effect, true);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if (rowType.name().endsWith("_BANNER")) {
|
||||
for (Map<String, Object> patternData : map) {
|
||||
BannerMeta meta = (BannerMeta) itemstack.getItemMeta();
|
||||
Pattern pattern = new Pattern(patternData);
|
||||
meta.addPattern(pattern);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.CROSSBOW)) {
|
||||
CrossbowMeta meta = (CrossbowMeta) itemstack.getItemMeta();
|
||||
for (Map<String, Object> itemData : map) {
|
||||
ItemStack crossbowItem = Util.unserializeItemStack(itemData);
|
||||
if (crossbowItem != null) {
|
||||
meta.addChargedProjectile(crossbowItem);
|
||||
}
|
||||
}
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
else if (rowType == Material.MAP || rowType == Material.FILLED_MAP) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
MapMeta meta = (MapMeta) itemstack.getItemMeta();
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
meta.setColor(color);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.FIREWORK_ROCKET) || (rowType == Material.FIREWORK_STAR)) {
|
||||
if (itemCount == 1) {
|
||||
effectBuilder = FireworkEffect.builder();
|
||||
for (Map<String, Object> fireworkData : map) {
|
||||
org.bukkit.FireworkEffect.Type type = (org.bukkit.FireworkEffect.Type) fireworkData.getOrDefault("type", org.bukkit.FireworkEffect.Type.BALL);
|
||||
boolean hasFlicker = (Boolean) fireworkData.get("flicker");
|
||||
boolean hasTrail = (Boolean) fireworkData.get("trail");
|
||||
effectBuilder.with(type);
|
||||
effectBuilder.flicker(hasFlicker);
|
||||
effectBuilder.trail(hasTrail);
|
||||
}
|
||||
}
|
||||
else if (itemCount == 2) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
effectBuilder.withColor(color);
|
||||
}
|
||||
}
|
||||
else if (itemCount == 3) {
|
||||
for (Map<String, Object> colorData : map) {
|
||||
org.bukkit.Color color = org.bukkit.Color.deserialize(colorData);
|
||||
effectBuilder.withFade(color);
|
||||
}
|
||||
buildFireworkEffect(effectBuilder, rowType, itemstack);
|
||||
itemCount = 0;
|
||||
}
|
||||
}
|
||||
else if ((rowType == Material.SUSPICIOUS_STEW)) {
|
||||
for (Map<String, Object> suspiciousStewData : map) {
|
||||
SuspiciousStewMeta meta = (SuspiciousStewMeta) itemstack.getItemMeta();
|
||||
PotionEffect effect = new PotionEffect(suspiciousStewData);
|
||||
meta.addCustomEffect(effect, true);
|
||||
itemstack.setItemMeta(meta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
BukkitAdapter.ADAPTER.setItemMeta(rowType, itemstack, map);
|
||||
}
|
||||
}
|
||||
|
||||
itemCount++;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return new Object[] { slot, faceData, itemstack };
|
||||
}
|
||||
|
||||
public static Object[] populateItemStack(ItemStack itemstack, byte[] metadata) {
|
||||
if (metadata != null) {
|
||||
try {
|
||||
ByteArrayInputStream metaByteStream = new ByteArrayInputStream(metadata);
|
||||
BukkitObjectInputStream metaObjectStream = new BukkitObjectInputStream(metaByteStream);
|
||||
Object metaList = metaObjectStream.readObject();
|
||||
metaObjectStream.close();
|
||||
metaByteStream.close();
|
||||
|
||||
return populateItemStack(itemstack, metaList);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
return new Object[] { 0, "", itemstack };
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.Skull;
|
||||
import org.bukkit.block.sign.Side;
|
||||
|
||||
import net.coreprotect.config.Config;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
|
||||
public class Paper_v1_20 extends Paper_v1_17 implements PaperInterface {
|
||||
@@ -22,7 +23,17 @@ public class Paper_v1_20 extends Paper_v1_17 implements PaperInterface {
|
||||
|
||||
@Override
|
||||
public String getSkullOwner(Skull skull) {
|
||||
return skull.getPlayerProfile().getName();
|
||||
String owner = skull.getPlayerProfile().getName();
|
||||
if (Config.getGlobal().MYSQL) {
|
||||
if (owner.length() > 255 && skull.getPlayerProfile().getId() != null) {
|
||||
return skull.getPlayerProfile().getId().toString();
|
||||
}
|
||||
else if (owner.length() > 255) {
|
||||
return owner.substring(0, 255);
|
||||
}
|
||||
}
|
||||
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.coreprotect.patch.script;
|
||||
|
||||
import java.sql.Statement;
|
||||
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
|
||||
public class __2_23_0 {
|
||||
|
||||
protected static boolean patch(Statement statement) {
|
||||
try {
|
||||
if (Config.getGlobal().MYSQL) {
|
||||
try {
|
||||
statement.executeUpdate("ALTER TABLE " + ConfigHandler.prefix + "skull MODIFY owner VARCHAR(255);");
|
||||
}
|
||||
catch (Exception e) {
|
||||
Chat.console(Phrase.build(Phrase.PATCH_SKIP_UPDATE, ConfigHandler.prefix + "skull", Selector.FIRST, Selector.FIRST));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package net.coreprotect.spigot;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.HoverEvent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.chat.hover.content.Text;
|
||||
@@ -18,8 +19,46 @@ public class Spigot_v1_16 extends SpigotHandler implements SpigotInterface {
|
||||
public void addHoverComponent(Object message, String[] data) {
|
||||
try {
|
||||
if (Config.getGlobal().HOVER_EVENTS) {
|
||||
String tooltipText = data[1]; // text displayed inside tooltip
|
||||
TextComponent component = new TextComponent(TextComponent.fromLegacyText(data[2]));
|
||||
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(TextComponent.fromLegacyText(processComponent(data[1])))));
|
||||
// BaseComponent[] displayComponent = TextComponent.fromLegacyText(processComponent(tooltipText));
|
||||
|
||||
if (tooltipText.contains(Color.MAGIC)) {
|
||||
tooltipText = tooltipText.replace(Color.MAGIC, "");
|
||||
|
||||
// to-do
|
||||
/*
|
||||
ComponentBuilder formattedComponent = new ComponentBuilder();
|
||||
StringBuilder messageTest = new StringBuilder();
|
||||
String colorChar = String.valueOf(ChatColor.COLOR_CHAR);
|
||||
boolean isObfuscated = false;
|
||||
|
||||
String[] tooltip = tooltipText.split(colorChar);
|
||||
for (String splitText : tooltip) {
|
||||
boolean setObfuscated = splitText.startsWith("k");
|
||||
splitText = setObfuscated ? splitText.substring(1) : (splitText.length() > 0 ? colorChar : "") + splitText;
|
||||
if ((setObfuscated && !isObfuscated) || (!setObfuscated && isObfuscated)) {
|
||||
formattedComponent.append(TextComponent.fromLegacyText(processComponent(messageTest.toString())));
|
||||
formattedComponent.obfuscated(false); // setObfuscated
|
||||
formattedComponent.append(TextComponent.fromLegacyText(processComponent(splitText)));
|
||||
messageTest.setLength(0);
|
||||
isObfuscated = !isObfuscated;
|
||||
}
|
||||
else {
|
||||
messageTest.append(splitText);
|
||||
}
|
||||
}
|
||||
|
||||
if (messageTest.length() > 0) {
|
||||
formattedComponent.append(TextComponent.fromLegacyText(processComponent(messageTest.toString())));
|
||||
}
|
||||
|
||||
displayComponent = formattedComponent.create();
|
||||
*/
|
||||
}
|
||||
|
||||
BaseComponent[] displayComponent = TextComponent.fromLegacyText(processComponent(tooltipText));
|
||||
component.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(displayComponent)));
|
||||
((TextComponent) message).addExtra(component);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -56,7 +56,7 @@ import net.coreprotect.bukkit.BukkitAdapter;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.Rollback;
|
||||
import net.coreprotect.database.rollback.Rollback;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
|
||||
@@ -57,7 +57,7 @@ import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.bukkit.BukkitAdapter;
|
||||
import net.coreprotect.database.Rollback;
|
||||
import net.coreprotect.database.rollback.Rollback;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.utility.Util;
|
||||
|
||||
@@ -5,12 +5,9 @@ import org.bukkit.Bukkit;
|
||||
import com.sk89q.worldedit.EditSession.Stage;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.event.extent.EditSessionEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
@@ -18,7 +15,6 @@ import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.utility.Chat;
|
||||
|
||||
public class CoreProtectEditSessionEvent {
|
||||
|
||||
private static boolean initialized = false;
|
||||
private static boolean isFAWE = false;
|
||||
private static CoreProtectEditSessionEvent event = new CoreProtectEditSessionEvent();
|
||||
@@ -37,12 +33,17 @@ public class CoreProtectEditSessionEvent {
|
||||
}
|
||||
|
||||
try {
|
||||
if (Bukkit.getServer().getPluginManager().getPlugin("AsyncWorldEdit") == null || Config.getGlobal().ENABLE_AWE) {
|
||||
WorldEdit.getInstance().getEventBus().register(event);
|
||||
initialized = true;
|
||||
ConfigHandler.worldeditEnabled = true;
|
||||
isFAWE = (Bukkit.getServer().getPluginManager().getPlugin("FastAsyncWorldEdit") != null);
|
||||
}
|
||||
WorldEdit.getInstance().getEventBus().register(new Object() {
|
||||
@Subscribe
|
||||
public void onEditSessionEvent(EditSessionEvent event) {
|
||||
if (event.getActor() != null && event.getStage() == Stage.BEFORE_CHANGE) {
|
||||
event.setExtent(new CoreProtectLogger(event.getActor(), event.getWorld(), event.getExtent()));
|
||||
}
|
||||
}
|
||||
});
|
||||
initialized = true;
|
||||
ConfigHandler.worldeditEnabled = true;
|
||||
isFAWE = (Bukkit.getServer().getPluginManager().getPlugin("FastAsyncWorldEdit") != null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
// Failed to initialize WorldEdit logging
|
||||
@@ -51,10 +52,10 @@ public class CoreProtectEditSessionEvent {
|
||||
Scheduler.runTask(CoreProtect.getInstance(), () -> {
|
||||
try {
|
||||
if (isInitialized()) {
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_SUCCESS, "WorldEdit", Selector.FIRST));
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_SUCCESS, isFAWE() ? "FastAsyncWorldEdit" : "WorldEdit", Selector.FIRST));
|
||||
}
|
||||
else {
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_ERROR, "WorldEdit", Selector.FIRST));
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_ERROR, isFAWE() ? "FastAsyncWorldEdit" : "WorldEdit", Selector.FIRST));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -72,19 +73,10 @@ public class CoreProtectEditSessionEvent {
|
||||
WorldEdit.getInstance().getEventBus().unregister(event);
|
||||
initialized = false;
|
||||
ConfigHandler.worldeditEnabled = false;
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_SUCCESS, "WorldEdit", Selector.SECOND));
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_SUCCESS, isFAWE() ? "FastAsyncWorldEdit" : "WorldEdit", Selector.SECOND));
|
||||
}
|
||||
catch (Exception e) {
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_ERROR, "WorldEdit", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void wrapForLogging(EditSessionEvent event) {
|
||||
Actor actor = event.getActor();
|
||||
World world = event.getWorld();
|
||||
if (actor != null && event.getStage() == (isFAWE ? Stage.BEFORE_HISTORY : Stage.BEFORE_CHANGE)) {
|
||||
event.setExtent(new CoreProtectLogger(actor, world, event.getExtent()));
|
||||
Chat.console(Phrase.build(Phrase.INTEGRATION_ERROR, isFAWE() ? "FastAsyncWorldEdit" : "WorldEdit", Selector.SECOND));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,16 @@ import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.bukkit.BukkitAdapter;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import com.sk89q.worldedit.world.block.BlockState;
|
||||
@@ -19,7 +23,6 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.utility.Util;
|
||||
|
||||
public class CoreProtectLogger extends AbstractDelegateExtent {
|
||||
|
||||
private final Actor eventActor;
|
||||
private final World eventWorld;
|
||||
private final Extent eventExtent;
|
||||
@@ -35,7 +38,12 @@ public class CoreProtectLogger extends AbstractDelegateExtent {
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(BlockVector3 position, T block) throws WorldEditException {
|
||||
org.bukkit.World world = BukkitAdapter.adapt(eventWorld);
|
||||
if (!Config.getConfig(world).WORLDEDIT) {
|
||||
return eventExtent.setBlock(position, block);
|
||||
if (CoreProtectEditSessionEvent.isFAWE()) {
|
||||
return eventExtent.setBlock(position.getX(), position.getY(), position.getZ(), block);
|
||||
}
|
||||
else {
|
||||
return eventExtent.setBlock(position, block);
|
||||
}
|
||||
}
|
||||
|
||||
BlockState oldBlock = eventExtent.getBlock(position);
|
||||
@@ -48,16 +56,59 @@ public class CoreProtectLogger extends AbstractDelegateExtent {
|
||||
// e.g. BaseBlock block = eventWorld.getBlock(position);
|
||||
ItemStack[] containerData = CoreProtectEditSessionEvent.isFAWE() ? null : Util.getContainerContents(oldType, null, location);
|
||||
|
||||
if (eventExtent.setBlock(position, block)) {
|
||||
WorldEditLogger.postProcess(eventExtent, eventActor, position, location, block, baseBlock, oldType, oldBlock, containerData);
|
||||
return true;
|
||||
if (CoreProtectEditSessionEvent.isFAWE()) {
|
||||
if (eventExtent.setBlock(position.getX(), position.getY(), position.getZ(), block)) {
|
||||
WorldEditLogger.postProcess(eventExtent, eventActor, position, location, block, baseBlock, oldType, oldBlock, containerData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (eventExtent.setBlock(position, block)) {
|
||||
WorldEditLogger.postProcess(eventExtent, eventActor, position, location, block, baseBlock, oldType, oldBlock, containerData);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
|
||||
return setBlock(BlockVector3.at(x,y,z), block);
|
||||
return this.setBlock(BlockVector3.at(x, y, z), block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int replaceBlocks(final Region region, final Mask mask, final Pattern pattern) throws MaxChangedBlocksException {
|
||||
org.bukkit.World world = BukkitAdapter.adapt(eventWorld);
|
||||
if (!Config.getConfig(world).WORLDEDIT) {
|
||||
return eventExtent.replaceBlocks(region, mask, pattern);
|
||||
}
|
||||
processPatternToBlocks(world, region, pattern);
|
||||
return eventExtent.replaceBlocks(region, mask, pattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int setBlocks(Region region, Pattern pattern) throws MaxChangedBlocksException {
|
||||
org.bukkit.World world = BukkitAdapter.adapt(eventWorld);
|
||||
if (!Config.getConfig(world).WORLDEDIT) {
|
||||
return eventExtent.setBlocks(region, pattern);
|
||||
}
|
||||
processPatternToBlocks(world, region, pattern);
|
||||
return eventExtent.setBlocks(region, pattern);
|
||||
}
|
||||
|
||||
private void processPatternToBlocks(org.bukkit.World world, Region region, Pattern pattern) {
|
||||
for (BlockVector3 position : region.clone()) {
|
||||
BlockState oldBlock = eventExtent.getBlock(position);
|
||||
Material oldType = BukkitAdapter.adapt(oldBlock.getBlockType());
|
||||
Location location = new Location(world, position.getBlockX(), position.getBlockY(), position.getBlockZ());
|
||||
BaseBlock baseBlock = WorldEditLogger.getBaseBlock(eventExtent, position, location, oldType, oldBlock);
|
||||
|
||||
// No clear way to get container content data from within the WorldEdit API
|
||||
// Data may be available by converting oldBlock.toBaseBlock().getNbtData()
|
||||
// e.g. BaseBlock block = eventWorld.getBlock(position);
|
||||
ItemStack[] containerData = CoreProtectEditSessionEvent.isFAWE() ? null : Util.getContainerContents(oldType, null, location);
|
||||
WorldEditLogger.postProcess(eventExtent, eventActor, position, location, pattern.applyBlock(position), baseBlock, oldType, oldBlock, containerData);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user