mirror of
https://github.com/PlayPro/CoreProtect.git
synced 2026-11-04 16:40:13 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0af209a0a0 | ||
|
|
4b0c3dad99 | ||
|
|
b0923ea344 | ||
|
|
1a4330c504 | ||
|
|
a145d207d9 | ||
|
|
0d46e27515 | ||
|
|
cea935f124 | ||
|
|
b5f534fd2c | ||
|
|
4ecab0b101 | ||
|
|
2f196fb385 | ||
|
|
32e074666d | ||
|
|
6f86e08849 | ||
|
|
3a95881ea4 | ||
|
|
04575029c9 | ||
|
|
9d04c025be | ||
|
|
a0ae242dac | ||
|
|
4c2c304329 | ||
|
|
943d471269 | ||
|
|
948ba32e77 | ||
|
|
7d47684afb | ||
|
|
3da2bc554d | ||
|
|
ec699a5a34 | ||
|
|
9a37a0d33a | ||
|
|
5ed0863a87 | ||
|
|
2f4eeeffca | ||
|
|
b3f5959af4 | ||
|
|
eee8d1c39b | ||
|
|
15aaaf8051 | ||
|
|
2429967b79 | ||
|
|
68d3f19d93 | ||
|
|
e2f8da9070 | ||
|
|
b7a662d137 | ||
|
|
cddbc398a6 | ||
|
|
1893eac47a | ||
|
|
305e6de3ac | ||
|
|
5a8b0f93d3 | ||
|
|
1a9b542517 | ||
|
|
8d5b0a20b6 | ||
|
|
39e82953b4 | ||
|
|
bdfd6b1576 | ||
|
|
2291e0d9c7 | ||
|
|
a8aeeca62c | ||
|
|
e7197123aa | ||
|
|
6e6f8d203b | ||
|
|
cb09ddeb0b | ||
|
|
b7a452bf03 | ||
|
|
7f7de03f54 | ||
|
|
ec96019bc2 | ||
|
|
5b2e8883ea | ||
|
|
6571e91c56 | ||
|
|
434d42b547 | ||
|
|
ba96dd1d19 | ||
|
|
7a730a76fc | ||
|
|
6994ec2ac4 | ||
|
|
3914e5e989 | ||
|
|
ab939cfa6f | ||
|
|
39005ee978 | ||
|
|
acadd24c70 | ||
|
|
ab4c405dd2 | ||
|
|
fe0274b069 | ||
|
|
1bd0a0f8b6 | ||
|
|
b6acf109d4 | ||
|
|
6d1ddb8580 | ||
|
|
6d60951cb9 | ||
|
|
3f7c892153 | ||
|
|
962ab485ee | ||
|
|
559ee73edf | ||
|
|
5c561c866d | ||
|
|
78d8301751 | ||
|
|
688b4b930d | ||
|
|
cf04a42d3e | ||
|
|
bd5c1f33b7 | ||
|
|
a658c32ce4 | ||
|
|
592a4f25e4 | ||
|
|
29256b47e6 | ||
|
|
9924a9376e | ||
|
|
cebcc8655a | ||
|
|
3be769ed96 | ||
|
|
3ffece26a3 | ||
|
|
7eaa88eb7f | ||
|
|
c4d3dda0ad | ||
|
|
8b0e735313 | ||
|
|
34ada262c2 | ||
|
|
d7aa696c28 | ||
|
|
67033ac08d | ||
|
|
2c30ba626a | ||
|
|
4ae0affe4b | ||
|
|
0d47338038 | ||
|
|
afbbbd5aab | ||
|
|
cce8c9eb51 | ||
|
|
eaae2afaf8 | ||
|
|
a1458a38be | ||
|
|
7ccb3eff34 | ||
|
|
def5a99096 | ||
|
|
a92a050d2f | ||
|
|
14b0a712de | ||
|
|
cdc8082c3e | ||
|
|
829bcc530d | ||
|
|
aa2a3b9e8e | ||
|
|
eee96fb5f9 | ||
|
|
fc91bc558c | ||
|
|
127170d7b6 | ||
|
|
7caa617a34 | ||
|
|
7c7013f49f | ||
|
|
4d311f5248 | ||
|
|
f5ac148b57 | ||
|
|
e852d75264 | ||
|
|
383caedff5 | ||
|
|
bd449d1b89 | ||
|
|
c706cf5b18 | ||
|
|
d69fffbce0 | ||
|
|
ff36b6e0e6 | ||
|
|
a90b0ea18a | ||
|
|
7dbd928edc | ||
|
|
99130fdcdb | ||
|
|
42a2965cd1 | ||
|
|
971ff57496 | ||
|
|
6c04867eb8 | ||
|
|
b83b39feae | ||
|
|
80a0f24e10 | ||
|
|
9cadca9acb | ||
|
|
0c389e92f3 | ||
|
|
db94ad70eb | ||
|
|
eff43b7d6f | ||
|
|
f0aad273f1 | ||
|
|
bf0e9cf661 | ||
|
|
71b673756f | ||
|
|
2f794d6398 | ||
|
|
f3a1d95b77 | ||
|
|
8c79b3a867 | ||
|
|
d87ecaee42 | ||
|
|
dc4e9f8d60 | ||
|
|
c145fca68c | ||
|
|
b0856b51a5 | ||
|
|
7386f4bd50 | ||
|
|
0f0ceccb7b | ||
|
|
893ce9af46 | ||
|
|
609990e344 | ||
|
|
38166fd381 |
No files matched your search
@@ -13,16 +13,11 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
- name: Set up JDK 21
|
||||
- name: Set up JDK 25
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '21'
|
||||
java-version: '25'
|
||||
distribution: 'temurin'
|
||||
- name: Cache Maven packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.m2
|
||||
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: ${{ runner.os }}-m2
|
||||
cache: 'maven'
|
||||
- name: Build
|
||||
run: mvn -B verify
|
||||
+12
@@ -173,6 +173,9 @@ Desktop.ini
|
||||
## Misc.
|
||||
#############
|
||||
|
||||
.claude
|
||||
AGENTS.md
|
||||
CLAUDE.md
|
||||
.cursorrules
|
||||
.windsurfrules
|
||||
.clinerules
|
||||
@@ -213,8 +216,17 @@ hs_err_pid*
|
||||
# Documentation dev folder
|
||||
docs/dev/
|
||||
|
||||
# symlinks
|
||||
CoreProtect-TestAPI
|
||||
CoreProtect-Fabric
|
||||
CoreProtect-Hytale
|
||||
publish/
|
||||
|
||||
# Extensions
|
||||
/src/main/java/net/coreprotect/utility/extensions
|
||||
!/src/main/java/net/coreprotect/utility/extensions/Extensions.java
|
||||
/.apt_generated/
|
||||
/.apt_generated_tests/
|
||||
|
||||
# Server side files
|
||||
server/*
|
||||
@@ -1,55 +1,206 @@
|
||||

|
||||
|
||||
[](LICENSE)
|
||||
[](https://github.com/PlayPro/CoreProtect/blob/master/LICENSE)
|
||||
[](https://github.com/PlayPro/CoreProtect/actions)
|
||||
[](https://app.netlify.com/sites/coreprotect/deploys)
|
||||
[](https://www.codefactor.io/repository/github/playpro/coreprotect)
|
||||
[](https://discord.gg/b4DZ4jy)
|
||||
|
||||
CoreProtect
|
||||
===========
|
||||
# CoreProtect
|
||||
|
||||
CoreProtect is a blazing fast data logging and anti-griefing tool for Minecraft servers.
|
||||
CoreProtect is a fast, efficient data logging and anti-griefing tool. Inspect, lookup, rollback, and restore any amount of damage without impacting your server performance.
|
||||
|
||||
For a detailed description of the plugin, please visit [coreprotect.net](https://coreprotect.net).
|
||||
CoreProtect is the [#1 anti-griefing plugin](https://bstats.org/plugin/bukkit/CoreProtect), and has been actively developed since early 2012.
|
||||
|
||||
| Quick Links | |
|
||||
| --- | --- |
|
||||
| CoreProtect Discord: | [discord.gg/b4DZ4jy](https://discord.gg/b4DZ4jy) |
|
||||
| CoreProtect Patreon: | [patreon.com/coreprotect](https://www.patreon.com/coreprotect) |
|
||||
| CoreProtect Documentation: | [docs.coreprotect.net](https://docs.coreprotect.net) |
|
||||
| Downloads for MC 1.14 - 1.21: | [coreprotect.net/latest](https://coreprotect.net/latest/) |
|
||||
| Downloads for MC 1.14 - 26.2: | [coreprotect.net/latest](https://coreprotect.net/latest/) |
|
||||
| Downloads for MC 1.8 - 1.12: | [coreprotect.net/legacy](https://coreprotect.net/legacy/) |
|
||||
| Downloads for Fabric: | [coreprotect.net/fabric](https://coreprotect.net/fabric) |
|
||||
| Downloads for Hytale: | [coreprotect.net/hytale](https://coreprotect.net/hytale) |
|
||||
|
||||
bStats
|
||||
------
|
||||
[](https://bstats.org/plugin/bukkit/CoreProtect)
|
||||
## API
|
||||
|
||||
API
|
||||
------
|
||||
### [API Documentation](https://docs.coreprotect.net/api/)
|
||||
|
||||
### Dependency Information
|
||||
Maven
|
||||
|
||||
Maven:
|
||||
|
||||
```xml
|
||||
<repository>
|
||||
<id>playpro-repo</id>
|
||||
<url>https://maven.playpro.com</url>
|
||||
</repository>
|
||||
```
|
||||
|
||||
```xml
|
||||
<dependency>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>coreprotect</artifactId>
|
||||
<version>23.1</version>
|
||||
<version>24.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
Contributing
|
||||
------
|
||||
## Donation Keys
|
||||
|
||||
To support the project and obtain a donation key, visit [coreprotect.net/donate](https://coreprotect.net/donate/).
|
||||
|
||||
## Other Plugins
|
||||
|
||||
* DarkerNights: [spigotmc.org/resources/darkernights.87814](https://www.spigotmc.org/resources/darkernights.87814/)
|
||||
* TransitTubes: [patreon.com/posts/75731668](https://www.patreon.com/posts/75731668)
|
||||
|
||||
## Video Tutorial
|
||||
|
||||
[](https://youtu.be/JwijCiueZ3Y)
|
||||
|
||||
## Core Features
|
||||
|
||||
* Fast, efficient data logging.
|
||||
* Rollbacks and restores with lag-free processing.
|
||||
* Multi-threaded to ensure server performance is never impacted.
|
||||
* No configuration required. Install the plugin, and you're good to go.
|
||||
* SQLite storage by default, with optional MySQL support.
|
||||
* Supports Bukkit, Spigot, Paper, Folia, MultiPaper, and more.
|
||||
* Permission system support and advanced lookup permissions.
|
||||
* Easy-to-use commands and inspector.
|
||||
* Advanced lookup filters and operation limits by radius, world, or WorldEdit selection.
|
||||
* Paginated results with clickable pagination.
|
||||
* Preview rollbacks and restores, and undo rollbacks by restoring the same data.
|
||||
* Rollback or restore specific users, multiple users, or global activity.
|
||||
* Inventory rollback support.
|
||||
* Purge old data by time, world, and block type.
|
||||
* Multi-world support.
|
||||
* Configurable global and per-world logging settings.
|
||||
* Safe default parameters.
|
||||
* Include or exclude specific blocks, items, entities, or users, plus logging blacklists.
|
||||
* WorldEdit and supported FAWE logging.
|
||||
* Enhanced item lookup tooltips.
|
||||
* Localization and translation support.
|
||||
* Automatic update checking and error reporting.
|
||||
* Developer and networking API support.
|
||||
* *...and much more!*
|
||||
|
||||
## What does it log?
|
||||
|
||||
### Blocks and World Changes
|
||||
|
||||
* Blocks placed or broken by players.
|
||||
* Natural block breakage, such as attached blocks breaking when their support is removed.
|
||||
* Block movement, including falling sand, gravel, and piston movement.
|
||||
* Water and lava placement, removal, and flow.
|
||||
* Liquid tracking, associating flowing liquids with the player who placed the source.
|
||||
* Fire ignition from flint and steel or fire charges, block burning, and fire fade.
|
||||
* Optional natural fire extinguishing.
|
||||
* TNT, Creeper, Ghast, and other explosions, plus primed TNT removal.
|
||||
* Entities changing blocks, including Endermen, Ender Dragons, and zombies breaking doors.
|
||||
* Leaf decay.
|
||||
* Tree growth linked back to the player who planted the sapling.
|
||||
* Mushroom, vine, amethyst, chorus, and bamboo growth.
|
||||
* Sculk spread from sculk catalysts.
|
||||
* Nether portal and other natural portal generation.
|
||||
* Crops trampled by players and turtle eggs trampled by players or entities.
|
||||
* Snow generated by snow golems.
|
||||
* Liquid-formed blocks such as obsidian, cobblestone, and concrete.
|
||||
* Flowers placed in flower pots.
|
||||
* Dragon egg teleportation.
|
||||
* Suspicious sand and gravel brushing or destruction.
|
||||
* Custom blocks, such as CraftEngine blocks.
|
||||
|
||||
### Containers, Inventories, and Items
|
||||
|
||||
* Items taken from or placed into vanilla or supported third-party containers.
|
||||
* Hopper, dropper, and dispenser transactions, including container transfers.
|
||||
* Player inventory transactions, including items dropped, thrown, shot, or picked up.
|
||||
* Items broken, created, destroyed, deposited, or withdrawn by players.
|
||||
* Items placed on campfires and lectern book transactions.
|
||||
* Chiseled bookshelf, decorated pot, and shelf inventory transactions.
|
||||
* Copper Golem chest and jukebox transactions, plus crafter slot changes.
|
||||
* Bundle actions through the `#bundle` tag.
|
||||
* Items crafted or traded with villagers.
|
||||
* Allay item exchanges.
|
||||
* Paintings and item frames.
|
||||
|
||||
### Entities and Player Activity
|
||||
|
||||
* Entity deaths and detailed death reasons.
|
||||
* Player-caused entity kills, including animals and monsters.
|
||||
* Armor stands and End Crystals.
|
||||
* Villagers killed by lightning, gossip data, and job-site memories.
|
||||
* Thrown eggs, snowballs, potions, ender pearls, tridents, and wind charges.
|
||||
* Player interactions with doors, buttons, levers, containers, bookshelves, and jukeboxes.
|
||||
* Sign text, color, glow, wax, and modern double-sided signs.
|
||||
* Player chat messages and commands.
|
||||
* Player sessions including logins and logouts, player deaths, and username changes.
|
||||
* Skull skin texture data on Paper servers and custom skull textures.
|
||||
* WorldEdit changes and supported FAWE clipboard pastes.
|
||||
* *...and more!*
|
||||
|
||||
## How to use the inspector
|
||||
|
||||
Once you have the inspector enabled with `/core inspect` or `/co i`, you can do the following:
|
||||
|
||||
* Left-click a block to see who placed that block.
|
||||
* Right-click a block to see what adjacent block was removed.
|
||||
* Right-click while placing a block in a location to see what block was removed at that location.
|
||||
* Right-click while placing a block in another block to see who placed it. For example, place dirt in water to see who placed the water.
|
||||
* Right-click a door, button, lever, container, or similar block to see who last used it.
|
||||
|
||||
## A Few Reviews
|
||||
|
||||
* *"It's easy to use and lightning fast when it comes to rollbacks."*
|
||||
* *"I've been running a MC server since before Bukkit, so I've used just about every block logger out there. CoreProtect is the best and the fastest."*
|
||||
* *"Go with CoreProtect. It's fast, updated frequently, and logs WorldEdit."*
|
||||
* *"Overall it felt more natural, simpler, and much faster to use CoreProtect than Prism, which just doesn't compare."*
|
||||
* *"CoreProtect brings complex logging and rollbacks, whilst at the same time keeping a low profile."*
|
||||
* *Featured on [Linus Tech Tips](https://www.userfolio.com/uploads/coreprotect-linus.png).*
|
||||
|
||||
## Useful Links
|
||||
|
||||
**Documentation**
|
||||
https://docs.coreprotect.net
|
||||
|
||||
**Commands**
|
||||
https://docs.coreprotect.net/commands/
|
||||
|
||||
**Permissions**
|
||||
https://docs.coreprotect.net/permissions/
|
||||
|
||||
**API Documentation**
|
||||
https://docs.coreprotect.net/api/
|
||||
|
||||
**Feedback & Support**
|
||||
https://github.com/PlayPro/CoreProtect/issues
|
||||
|
||||
**Discord**
|
||||
Join us on Discord: https://discord.gg/b4DZ4jy
|
||||
|
||||
**Donate**
|
||||
Enjoy using CoreProtect and want to show your support? [Join our Patreon!](https://www.patreon.com/coreprotect)
|
||||
|
||||
**Sponsors**
|
||||
Thanks to [HostHorde](https://www.hosthorde.com) for sponsoring CoreProtect!
|
||||
|
||||
## Bug Reports
|
||||
|
||||
For any bug reports, please submit a ticket here:
|
||||
https://github.com/PlayPro/CoreProtect/issues
|
||||
|
||||
Thanks for your support!
|
||||
|
||||
## bStats
|
||||
|
||||
[](https://bstats.org/plugin/bukkit/CoreProtect)
|
||||
|
||||
## Contributing
|
||||
|
||||
CoreProtect is an open source project, and gladly accepts community contributions.
|
||||
|
||||
If you'd like to contribute, please read our contributing guidelines here: [CONTRIBUTING.md](CONTRIBUTING.md)
|
||||
|
||||
[](CONTRIBUTING.md#code-of-conduct)
|
||||
[](CONTRIBUTING.md#code-of-conduct)
|
||||
+3
-3
@@ -4,8 +4,8 @@ The CoreProtect API enables you to log your own block changes, perform lookups,
|
||||
|
||||
| API Details | |
|
||||
| --- | --- |
|
||||
| **API Version:** | 10 |
|
||||
| **Plugin Version:** | v22.4+ |
|
||||
| **API Version:** | 12 |
|
||||
| **Plugin Version:** | v24.0+ |
|
||||
| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
|
||||
|
||||
*Documentation for the API version 10 can be found [here](/api/version/v10/).*
|
||||
*Documentation for the API version 12 can be found [here](/api/version/v12/).*
|
||||
@@ -5,7 +5,7 @@ The CoreProtect API enables you to log your own block changes, perform lookups,
|
||||
| API Details | |
|
||||
| --- | --- |
|
||||
| **API Version:** | 11 |
|
||||
| **Plugin Version:** | v24.0+ |
|
||||
| **Plugin Version:** | v23.1+ |
|
||||
| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
|
||||
|
||||
---
|
||||
@@ -28,8 +28,8 @@ CoreProtectPreLogEvent(String user)
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ensure you're using CoreProtect 24.0 or higher. Add it as an external jar to your plugin in your IDE.
|
||||
Alternatively, if using Maven, you can add it via the repository https://maven.playpro.com (net.coreprotect, 24.0).
|
||||
Ensure you're using CoreProtect 23.1 or higher. Add it as an external jar to your plugin in your IDE.
|
||||
Alternatively, if using Maven, you can add it via the repository https://maven.playpro.com (net.coreprotect, 23.1).
|
||||
|
||||
The first thing you need to do is get access to CoreProtect. You can do this by using code similar to the following:
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,72 @@
|
||||
# Automatic Purging
|
||||
|
||||
Automatic purging removes old CoreProtect data on a daily schedule, helping keep database growth under control without requiring manual `/co purge` runs.
|
||||
|
||||
> **Note:** Automatic purging is not enabled by default. This feature is exclusive to CoreProtect 24.0+ [Patreon builds](http://patreon.com/coreprotect).
|
||||
|
||||
## Configuration
|
||||
|
||||
To enable automatic purging, set `auto-purge` in `config.yml` to the amount of data you want to keep:
|
||||
|
||||
```yaml
|
||||
auto-purge: 180d
|
||||
```
|
||||
|
||||
This example keeps the most recent 180 days of CoreProtect data and automatically removes older data.
|
||||
|
||||
Supported values use the same style as CoreProtect command times, such as `30d`, `12w`, or `6mo`. The minimum automatic purge value is `30d`. Set `auto-purge: false` to disable automatic purging.
|
||||
|
||||
## Schedule
|
||||
|
||||
Automatic purging runs once per day using your server's local time. By default, it runs at midnight.
|
||||
|
||||
To change the daily runtime, manually add `auto-purge-time: 03:30` to `config.yml`.<br>
|
||||
Use 24-hour `HH:mm` server time.
|
||||
|
||||
After changing `auto-purge` or `auto-purge-time`, use `/co reload` or restart the server. Changes apply to the next scheduled run.
|
||||
|
||||
When automatic purging is enabled, CoreProtect logs the next scheduled run when the server starts and again after an automatic purge completes.
|
||||
|
||||
## How It Works
|
||||
|
||||
Automatic purging runs in the background and removes old data incrementally in small chunks, with short pauses between database work. The server can continue to be used normally while it runs.
|
||||
|
||||
Automatic purging uses the same CoreProtect data tables as manual purging, but it does not rebuild the SQLite database or optimize MySQL tables. It deletes old rows in place, which helps maintain the current database size over time but may not immediately reduce the database file size or table size on disk.
|
||||
|
||||
Only one automatic purge can run at a time. If the server shuts down, a manual purge starts, a database migration or conversion starts, or the consumer is manually paused, the automatic purge stops safely and can continue during the next scheduled run.
|
||||
|
||||
## Important Notes
|
||||
|
||||
* **Patreon exclusive:** Only available in CoreProtect 24.0+ [Patreon builds](http://patreon.com/coreprotect)
|
||||
* **Not enabled by default:** Set `auto-purge` in `config.yml` to enable automatic purging
|
||||
* **Background cleanup:** Automatic purging is designed to run while the server remains usable
|
||||
|
||||
## Existing Databases
|
||||
|
||||
If enabling automatic purging on a new database, no additional action is required.
|
||||
|
||||
If enabling automatic purging on an existing database, it is recommended to run a manual purge first using the same time value:
|
||||
|
||||
```text
|
||||
/co purge t:180d
|
||||
```
|
||||
|
||||
For MySQL, add `#optimize` if you want to reclaim disk space during the initial manual purge:
|
||||
|
||||
```text
|
||||
/co purge t:180d #optimize
|
||||
```
|
||||
|
||||
This lets the manual purge reduce the existing database size, while automatic purging helps keep the database from growing beyond the configured retention period afterward.
|
||||
|
||||
## Status
|
||||
|
||||
Use `/co status` to see how many rows have been automatically purged since the last server restart.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Automatic purging won't start:**
|
||||
|
||||
* Verify you're using a CoreProtect 24.0+ [Patreon build](http://patreon.com/coreprotect)
|
||||
* Verify `auto-purge` is set to a valid value of at least `30d`
|
||||
* Check the server console for automatic purge scheduling messages
|
||||
+23
-7
@@ -21,15 +21,31 @@ Secondary configuration files override the value specified in config.yml. If you
|
||||
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).
|
||||
2. Enter the names of the users, commands, blocks, or entities you'd like to disable logging for (each entry 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 "#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:
|
||||
The blacklist supports disabling logs for:
|
||||
|
||||
- Users, which includes Players and non-player users, such as "#creeper"
|
||||
- Commands, such as `/help`
|
||||
- Blocks, such as minecraft:stone. Only `block` actions are affected.
|
||||
- Entities, such as minecraft:creeper, which will disable logging the death for that entity. *Note: renamed entities will be logged even if blacklisted.*
|
||||
- Filters can also be specified for a particular user, by using the `@` symbol after the specific item, block, or entity namespaced ID. The format is `id@user`. This will filter all `block`, `kill`, `item` and `container` actions involving that particular block, item or mob, only when caused by the specified player or non-player user.
|
||||
- Items and container actions are only affected by filtered blacklist entries, not by generic item or block IDs.
|
||||
|
||||
*Please note that you must include the namespace (e.g. minecraft:) for blocks, entities and items.*
|
||||
|
||||
An example blacklist.txt file would look like this:
|
||||
|
||||
```text
|
||||
Notch
|
||||
#tnt
|
||||
/help
|
||||
minecraft:stone
|
||||
Notch ; User
|
||||
#tnt ; TNT explosions
|
||||
/help ; Help command
|
||||
minecraft:stone ; Stone blocks
|
||||
minecraft:creeper ; Creeper entity
|
||||
minecraft:shears@#dispenser ; Shears being dispensed
|
||||
```
|
||||
|
||||
*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".*
|
||||
|
||||
*Please note that to disable logging for blocks, CoreProtect v23+ is required.*
|
||||
*To disable logging for entities or to use filtering, CoreProtect v24+ is required.*
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
CoreProtect 23.0+ includes the ability to migrate your database between SQLite and MySQL without losing any data.
|
||||
|
||||
> **Note:** Database migration functionality is exclusive to CoreProtect 23.0+ Patreon builds for Patron supporters.
|
||||
> **Note:** Database migration functionality is exclusive to CoreProtect 23.0+ [Patreon builds](http://patreon.com/coreprotect) for Patron supporters.
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -82,7 +82,7 @@ The `/co migrate-db` command allows you to seamlessly transfer all your CoreProt
|
||||
|
||||
* **Console only:** Cannot be executed from in-game chat
|
||||
* **Interruption handling:** If interrupted, the target database must be manually wiped before restarting
|
||||
* **Patreon exclusive:** Only available in CoreProtect 23.0+ Patreon builds
|
||||
* **Patreon exclusive:** Only available in CoreProtect 23.0+ [Patreon builds](http://patreon.com/coreprotect)
|
||||
|
||||
---
|
||||
|
||||
@@ -92,7 +92,7 @@ The `/co migrate-db` command allows you to seamlessly transfer all your CoreProt
|
||||
|
||||
**Migration won't start:**
|
||||
|
||||
* Verify you're using a CoreProtect 23.0+ Patreon build
|
||||
* Verify you're using a CoreProtect 23.0+ [Patreon build](http://patreon.com/coreprotect)
|
||||
* Ensure you're not trying to migrate to the same database type
|
||||
* Check that no other CoreProtect operations are running
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
For more information about CoreProtect, visit [coreprotect.net](http://coreprotect.net).
|
||||
|
||||
Looking for another platform? Visit [CoreProtect for Fabric](https://coreprotect.net/fabric) or [CoreProtect for Hytale](https://coreprotect.net/hytale).
|
||||
|
||||
## Getting Started
|
||||
|
||||
Please visit one of the following links for more information.
|
||||
@@ -21,6 +23,9 @@ Log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
[**Database Migration**](/database-migration/)
|
||||
Migrate your CoreProtect database between SQLite and MySQL.
|
||||
|
||||
[**Automatic Purging**](/auto-purge/)
|
||||
Automatically remove old CoreProtect data on a daily schedule.
|
||||
|
||||
[**Compatible Third-Party Plugins & Tools**](/tools-integrations/)
|
||||
A list of plugins and tools that are compatible with CoreProtect.
|
||||
|
||||
|
||||
@@ -39,6 +39,9 @@ The following permissions can be used to restrict functionality within the plugi
|
||||
* **coreprotect.consumer** *(default: op)*
|
||||
Allows access to the CoreProtect consumer command.
|
||||
|
||||
* **coreprotect.give** *(default: false)*
|
||||
Allows access to the CoreProtect give command.
|
||||
|
||||
* **coreprotect.networking** *(default: op)*
|
||||
Allows access to the CoreProtect networking API.
|
||||
|
||||
@@ -46,6 +49,8 @@ The following permissions can be used to restrict functionality within the plugi
|
||||
|
||||
## Child Permissions
|
||||
|
||||
> **Note:** Child permissions are not presently supported by [CoreProtect for Hytale](https://coreprotect.net/hytale).
|
||||
|
||||
* **coreprotect.lookup.block** *(default: op)*
|
||||
Can be optionally used as a negative permission to prevent block lookups.
|
||||
|
||||
|
||||
@@ -66,6 +66,9 @@ HELP_PARAMS_6: "Include specific blocks/entities in the {lookup|rollback|restore
|
||||
HELP_PARAMS_7: "Exclude blocks/users from the {lookup|rollback|restore}."
|
||||
HELP_PURGE_1: "Delete data older than specified time."
|
||||
HELP_PURGE_2: "For example, \"{0}\" will delete all data older than one month, and only keep the last 30 days of data."
|
||||
HELP_PURGE_3: "Specify the amount of time to purge."
|
||||
HELP_PURGE_4: "Specify a world to limit the purge to."
|
||||
HELP_PURGE_5: "Include specific blocks in the purge."
|
||||
HELP_PURGE_COMMAND: "Delete old block data."
|
||||
HELP_RADIUS_1: "Specify a radius area."
|
||||
HELP_RADIUS_2: "Examples: [r:10] (Only make changes within 10 blocks of you)"
|
||||
@@ -94,6 +97,8 @@ INVALID_CONTAINER: "Please inspect a valid container first."
|
||||
INVALID_DONATION_KEY: "Invalid donation key."
|
||||
INVALID_INCLUDE: "\"{0}\" is an invalid block/entity name."
|
||||
INVALID_INCLUDE_COMBO: "That is an invalid block/entity combination."
|
||||
INVALID_ITEM_ID: "Please enter a valid item id."
|
||||
INVALID_PARAMETER: "\"{0}\" is not a supported parameter."
|
||||
INVALID_RADIUS: "Please enter a valid radius."
|
||||
INVALID_SELECTION: "{0} selection not found."
|
||||
INVALID_USERNAME: "\"{0}\" is an invalid username."
|
||||
@@ -142,6 +147,8 @@ PATCH_PROCESSING: "Processing new data. Please wait..."
|
||||
PATCH_SKIP_UPDATE: "Skipping {table|index} {update|creation|removal} on {0}."
|
||||
PATCH_STARTED: "Performing {0} upgrade. Please wait..."
|
||||
PATCH_SUCCESS: "Successfully upgraded to {0}."
|
||||
PATCH_TABLE_COMPLETED: "Successfully updated {0} table."
|
||||
PATCH_TABLE_STARTED: "Updating {0} table. Please wait..."
|
||||
PATCH_UPGRADING: "Database upgrade in progress. Please wait..."
|
||||
PLEASE_SELECT: "Please select: \"{0}\" or \"{1}\"."
|
||||
PREVIEW_CANCELLED: "Preview cancelled."
|
||||
@@ -180,6 +187,7 @@ ROLLBACK_STARTED: "{Rollback|Restore|Preview} started on \"{0}\"."
|
||||
ROLLBACK_TIME: "Time range: {0}."
|
||||
ROLLBACK_WORLD_ACTION: "Restricted to {world|action} \"{0}\"."
|
||||
SIGN_HEADER: "Sign Messages"
|
||||
STATUS_AUTO_PURGE: "Cleanup: {0} {row|rows} auto purged since restart."
|
||||
STATUS_CONSUMER: "Consumer: {0} {item|items} in queue."
|
||||
STATUS_DATABASE: "Database: Using {0}."
|
||||
STATUS_INTEGRATION: "{0}: Integration {enabled|disabled}."
|
||||
|
||||
+207
@@ -0,0 +1,207 @@
|
||||
# CoreProtect v24.0 Language Cache (tt)
|
||||
|
||||
ACTION_NOT_SUPPORTED: "Бу гамәл хупланмый."
|
||||
AMOUNT_BLOCK: "{0} {блок|блоклар}"
|
||||
AMOUNT_CHUNK: "{0} {кисәк|кисәкчәләр}"
|
||||
AMOUNT_ENTITY: "{0} {зат|затлар}"
|
||||
AMOUNT_ITEM: "{0} {әйбер|әйберләр}"
|
||||
API_TEST: "API тесты уңышлы үтте."
|
||||
CACHE_ERROR: "КИСӘТҮ: Валидацияләү вакытында хата килеп чыкты {0} кэш."
|
||||
CACHE_RELOAD: "Мәҗбүри яңадан йөкләү {картага төшерү|дөнья} мәгълүмат базасыннан алынган кэшлар."
|
||||
CHECK_CONFIG: "Зинһар, config.yml файлын тикшерегез"
|
||||
COMMAND_CONSOLE: "Зинһар, команданы консольдән башкарыгыз."
|
||||
COMMAND_NOT_FOUND: "Команда \"{0}\" табылмады.\""
|
||||
COMMAND_THROTTLED: "Зинһар, бераз көтегез һәм кабатлап карагыз."
|
||||
CONSUMER_ERROR: "Кулланучылар чиратлары эшкәртелә инде {туктатылган|дәвам иттерелгән}."
|
||||
CONSUMER_TOGGLED: "Кулланучылар чиратларын эшкәртү {туктатылган|дәвам иттерелгән}."
|
||||
CONTAINER_HEADER: "Контейнер транзакцияләре"
|
||||
CPU_CORES: "Үзәк процессор үзәкләре."
|
||||
DATABASE_BUSY: "Мәгълүмат базасы мәшгуль. Зинһар, соңрак кабатлап карагыз."
|
||||
DATABASE_INDEX_ERROR: "Мәгълүмат базасы индексларын тикшереп булмый."
|
||||
DATABASE_LOCKED_1: "Мәгълүмат базасы бикләнгән. 15 секундка кадәр көтәм..."
|
||||
DATABASE_LOCKED_2: "Мәгълүмат базасы инде кулланыла. Зинһар, кабатлап карагыз."
|
||||
DATABASE_LOCKED_3: "Мәгълүмат базасын блоклауны сүндерү өчен, \"database-lock: false\" куегыз."
|
||||
DATABASE_LOCKED_4: "Мәгълүмат базасын блоклауны сүндерү мәгълүматларның бозылуына китерергә мөмкин."
|
||||
DATABASE_UNREACHABLE: "Мәгълүматлар базасына кереп булмый. Мәгълүматларны юкка чыгаралар һәм сүндерәләр."
|
||||
DEVELOPMENT_BRANCH: "Үсеш тармагы ачыкланды, патч скриптларын үткәреп җибәрә."
|
||||
DIRT_BLOCK: "Сезнең астыгызга вакытлыча куркынычсызлык блогы куйдылар."
|
||||
DISABLE_SUCCESS: "Уңышлы! Инвалид {0}"
|
||||
ENABLE_FAILED: "{0} башлый алмады."
|
||||
ENABLE_SUCCESS: "{0} хәзер активлаштырылган!"
|
||||
ENJOY_COREPROTECT: "Рәхәтләнегез {0}Безнең белән кушылыгыз Discord!"
|
||||
FINISHING_CONVERSION: "Мәгълүматларны үзгәртү тәмамлана. Зинһар, көтегез..."
|
||||
FINISHING_LOGGING: "Мәгълүматларны теркәү тәмамлана. Зинһар, көтегез..."
|
||||
FIRST_VERSION: "Башлангыч мәгълүмат базасы: {0}"
|
||||
GLOBAL_LOOKUP: "Глобаль эзләү өчен радиус күрсәтмәгез."
|
||||
GLOBAL_ROLLBACK: "Куллану \"{0}\" глобаль эш башкарырга {кире кайтару|торгызу}"
|
||||
HELP_ACTION_1: "Эзләүне гамәл белән чикләгез."
|
||||
HELP_ACTION_2: "Мисаллар: [a:block], [a:+block], [a:-block] [a:click], [a:container], [a:inventory], [a:item], [a:kill], [a:chat], [a:command], [a:sign], [a:session], [a:username]"
|
||||
HELP_COMMAND: "Өстәмә мәгълүматны күрсәтегез."
|
||||
HELP_EXCLUDE_1: "Блокларны/кулланучыларны чыгарыгыз."
|
||||
HELP_EXCLUDE_2: "Мисаллар: [e:stone], [e:Notch], [e:stone,Notch]"
|
||||
HELP_HEADER: "{0} Ярдәм"
|
||||
HELP_INCLUDE_1: "Блокларны/объектларны кертегез."
|
||||
HELP_INCLUDE_2: "Мисаллар: [i:stone], [i:zombie], [i:stone,wood,bedrock]"
|
||||
HELP_INSPECT_1: "Инспекторны кабызганда, сез:"
|
||||
HELP_INSPECT_2: "Урынны карау өчен сул төймә белән басыгыз."
|
||||
HELP_INSPECT_3: "Күршедәге бетерүләрне карау өчен уң төймә белән басыгыз."
|
||||
HELP_INSPECT_4: "Алып ташлауны күрү өчен блок урнаштырыгыз."
|
||||
HELP_INSPECT_5: "Урынын күрү өчен, сыеклыкка блок салыгыз."
|
||||
HELP_INSPECT_6: "Күкрәк транзакцияләрен карау өчен уң төймә белән басыгыз."
|
||||
HELP_INSPECT_7: "Киңәш: Сез бары тик \"/co i\" куллана аласыз."
|
||||
HELP_INSPECT_COMMAND: "Блок инспекторын кабыза/яба."
|
||||
HELP_LIST: "Барлык командалар исемлеген күрсәтә."
|
||||
HELP_LOOKUP_1: "Команда кыска юлы"
|
||||
HELP_LOOKUP_2: "Өстәмә битләрне карау."
|
||||
HELP_LOOKUP_COMMAND: "Блок мәгълүматларын эзләү."
|
||||
HELP_NO_INFO: "Команда өчен мәгълүмат \"{0}\" табылмады.\""
|
||||
HELP_PARAMETER: "Зинһар, карагыз \"{0}\" параметрлар турында тулырак мәгълүмат алу өчен."
|
||||
HELP_PARAMS_1: "Башкарыгыз {эзләү|кайтару|торгызу}."
|
||||
HELP_PARAMS_2: "Кулланучыларны күрсәтегез {эзләү|кайтару|торгызу}."
|
||||
HELP_PARAMS_3: "Вакытны күрсәтегез {эзләү|кайтару|торгызу}."
|
||||
HELP_PARAMS_4: "Чикләү {эзләү|кайтару|торгызу} радиуска кадәр."
|
||||
HELP_PARAMS_5: "Чикләү {эзләү|кайтару|торгызу} гамәленә."
|
||||
HELP_PARAMS_6: "Блокларны/объектларны кертегез {эзләү|кайтару|торгызу}."
|
||||
HELP_PARAMS_7: "Блокларны/кулланучыларны чыгарыгыз {эзләү|кайтару|торгызу}."
|
||||
HELP_PURGE_1: "Иске мәгълүматларны бетерегез."
|
||||
HELP_PURGE_2: "Мәсәлән, \"{0}\" бер айдан иске барлык мәгълүматларны бетерәчәк һәм соңгы 30 көнлек мәгълүматларны гына саклаячак.\""
|
||||
HELP_PURGE_COMMAND: "Иске блок мәгълүматларын бетерегез."
|
||||
HELP_RADIUS_1: "Радиус мәйданын күрсәтегез."
|
||||
HELP_RADIUS_2: "Мисаллар: [r:10] (Үзгәрешләрне сездән 10 квартал эчендә генә кертегез)"
|
||||
HELP_RELOAD_COMMAND: "Конфигурация файлын яңадан йөкли."
|
||||
HELP_RESTORE_COMMAND: "Блок мәгълүматларын торгызу."
|
||||
HELP_ROLLBACK_COMMAND: "Кире кайтару блогы мәгълүматлары."
|
||||
HELP_STATUS: "Плагинның статусын карагыз."
|
||||
HELP_STATUS_COMMAND: "Плагин статусын күрсәтә."
|
||||
HELP_TELEPORT: "Телепорт."
|
||||
HELP_TIME_1: "Вакытны күрсәтегез."
|
||||
HELP_TIME_2: "Мисаллар: [t:2w,5d,7h,2m,10s], [t:5d2h], [t:2.50h]"
|
||||
HELP_USER_1: "Кулланучыларны күрсәтегез."
|
||||
HELP_USER_2: "Мисаллар: [u:Notch], [u:Notch,#enderman]"
|
||||
INCOMPATIBLE_ACTION: "\"{0}\" бу гамәл белән кулланыла алмый."
|
||||
INSPECTOR_ERROR: "Инспектор инде {активлаштырылган|сүндерелгән}."
|
||||
INSPECTOR_TOGGLED: "Инспектор хәзер {активлаштырылган|сүндерелгән}."
|
||||
INTEGRATION_ERROR: "Мөмкин түгел {башлангыч хәлгә китерү|сүндерү} {0} агач эшкәртү"
|
||||
INTEGRATION_SUCCESS: "{0} уңышлы теркәлү {башлангыч хәлгә китерелгән|сүндерелгән}."
|
||||
INTEGRATION_VERSION: "Яраксыз {0} версиясе табылды."
|
||||
INTERACTIONS_HEADER: "Уенчыларның үзара бәйләнеше"
|
||||
INVALID_ACTION: "Бу дөрес гамәл түгел."
|
||||
INVALID_BRANCH_1: "Плагин версиясе дөрес түгел (тармак куелмаган)."
|
||||
INVALID_BRANCH_2: "Дәвам итү өчен, проект тармагын \"эшләү\"гә куегыз."
|
||||
INVALID_BRANCH_3: "Эшләү кодын эшләтеп җибәрү мәгълүматларның бозылуына китерергә мөмкин."
|
||||
INVALID_CONTAINER: "Зинһар, башта яраклы контейнерны тикшерегез."
|
||||
INVALID_DONATION_KEY: "Иганә ачкычы дөрес түгел."
|
||||
INVALID_INCLUDE: "\"{0}\" - яраксыз кыйммәт."
|
||||
INVALID_INCLUDE_COMBO: "Бу яраксыз тип комбинациясе."
|
||||
INVALID_RADIUS: "Зинһар, дөрес радиус кертегез."
|
||||
INVALID_SELECTION: "{0} сайлау табылмады."
|
||||
INVALID_USERNAME: "\"{0}\" - яраксыз кулланучы исеме."
|
||||
INVALID_WORLD: "Зинһар, дөрес дөнья күрсәтегез."
|
||||
LATEST_VERSION: "Соңгы версия: {0}"
|
||||
LINK_DISCORD: "Discord: {0}"
|
||||
LINK_DOWNLOAD: "Йөкләү: {0}"
|
||||
LINK_PATREON: "Patreon: {0}"
|
||||
LINK_WIKI_BLOCK: "Блок исемнәре: {0}"
|
||||
LINK_WIKI_ENTITY: "Объект исемнәре: {0}"
|
||||
LOGGING_ITEMS: "{0} Элемтәгә кертергә калган әйберләр. Зинһар, көтегез..."
|
||||
LOGGING_TIME_LIMIT: "Журналлаштыру вакыты чикләнде. Мәгълүматлар юкка чыгарыла һәм сүндерелә."
|
||||
LOOKUP_BLOCK: "{0} {урнаштырылган|ватык} {1}."
|
||||
LOOKUP_CONTAINER: "{0} {өстәлде|алып ташланды} {1} {2}."
|
||||
LOOKUP_HEADER: "{0} Нәтиҗәләр"
|
||||
LOOKUP_INTERACTION: "{0} {басылды|үтерелде} {1}."
|
||||
LOOKUP_ITEM: "{0} {алды|ташлады} {1} {2}."
|
||||
LOOKUP_LOGIN: "{0} теркәлгән {керү|чыгу}."
|
||||
LOOKUP_PAGE: "Бит {0}"
|
||||
LOOKUP_PROJECTILE: "{0} {ыргытты|атты} {1} {2}."
|
||||
LOOKUP_ROWS_FOUND: "{0} {рәт|рәтләр} табылган."
|
||||
LOOKUP_SEARCHING: "Эзләү эзләнә. Зинһар, көтегез..."
|
||||
LOOKUP_STORAGE: "{0} {салынган|алынган} {1} {2}."
|
||||
LOOKUP_TIME: "{0} элек"
|
||||
LOOKUP_USERNAME: "{0} буларак керде {1}."
|
||||
MAXIMUM_RADIUS: "Максималь {эзләү|кайтару|торгызу} радиус {0}."
|
||||
MISSING_ACTION_USER: "Бу гамәлне куллану өчен, зинһар, кулланучыны күрсәтегез."
|
||||
MISSING_LOOKUP_TIME: "Зинһар, вакытны күрсәтегез {эзләү|кайтару|торгызу}."
|
||||
MISSING_LOOKUP_USER: "Зинһар, кулланучыны күрсәтегез яки {блок|радиус}."
|
||||
MISSING_PARAMETERS: "Зинһар, \" кулланыгыз{0}\"."
|
||||
MISSING_ROLLBACK_RADIUS: "Сез күрсәтмәдегез {кире кайтару|торгызу} радиус."
|
||||
MISSING_ROLLBACK_USER: "Сез күрсәтмәдегез {кире кайтару|торгызу} кулланучы."
|
||||
MYSQL_UNAVAILABLE: "Тоташып булмый MySQL сервер."
|
||||
NETWORK_CONNECTION: "Тоташу {0} {уңышлы|уңышсыз}Куллану {1} {2}."
|
||||
NETWORK_TEST: "Челтәр сынау мәгълүматлары уңышлы җибәрелде."
|
||||
NO_DATA: "Бернинди мәгълүмат табылмады {0}."
|
||||
NO_DATA_LOCATION: "Юк {мәгълүматлар|транзакцияләр|үзара бәйләнешләр|хәбәрләр} табылган."
|
||||
NO_PERMISSION: "Сезнең моны эшләргә рөхсәтегез юк."
|
||||
NO_RESULTS: "Нәтиҗәләр табылмады."
|
||||
NO_RESULTS_PAGE: "Юк {нәтиҗәләр|мәгълүматлар} шул бит өчен табылды."
|
||||
NO_ROLLBACK: "Юк {көтелгән|алдагы} кире кайтару/торгызу табылды."
|
||||
PATCH_INTERRUPTED: "Яңарту өзелде. Кабат эшләтеп җибәргәндә тагын бер кат тырышып карыйм."
|
||||
PATCH_OUTDATED_1: "Искерәк мәгълүмат базаларын яңартып булмый {0}."
|
||||
PATCH_OUTDATED_2: "Зинһар, ярдәм ителә торган версия белән яңартыгыз CoreProtect."
|
||||
PATCH_PROCESSING: "Яңа мәгълүматлар эшкәртелә. Зинһар, көтегез..."
|
||||
PATCH_SKIP_UPDATE: "Сикереп бару {таблица|индекс} {яңарту|булдыру|бетерү} өстендә {0}."
|
||||
PATCH_STARTED: "Башкару {0} яңарту. Зинһар, көтегез..."
|
||||
PATCH_SUCCESS: "Уңышлы рәвештә яңартылды {0}."
|
||||
PATCH_UPGRADING: "Мәгълүмат базасы яңартыла. Зинһар, көтегез..."
|
||||
PLEASE_SELECT: "Зинһар, сайлагыз: \"{0}\" яки \"{1}\"."
|
||||
PREVIEW_CANCELLED: "Алдан карау юкка чыгарылды."
|
||||
PREVIEW_CANCELLING: "Алдан карауны юкка чыгару..."
|
||||
PREVIEW_IN_GAME: "Сез кире кайтаруларны уен эчендә генә карый аласыз."
|
||||
PREVIEW_TRANSACTION: "Алдан карап булмый {контейнер|инвентаризация} транзакцияләр."
|
||||
PRIMARY_THREAD_ERROR: "Бу API ысулын төп җептә кулланып булмый."
|
||||
PURGE_ABORTED: "Чистарту уңышсыз тәмамланды. Мәгълүмат базасы бозылган булырга мөмкин."
|
||||
PURGE_ERROR: "Эшкәртеп булмый {0} мәгълүматлар!"
|
||||
PURGE_FAILED: "Чистарту уңышсыз тәмамланды. Зинһар, соңрак кабатлап карагыз."
|
||||
PURGE_IN_PROGRESS: "Чистарту бара. Зинһар, соңрак кабатлап карагыз."
|
||||
PURGE_MINIMUM_TIME: "Сез бары тик искерәк мәгълүматларны гына бетерә аласыз {0} {көннәр|сәгатьләр}."
|
||||
PURGE_NOTICE_1: "Зинһар, игътибар итегез, бу бераз вакыт алырга мөмкин."
|
||||
PURGE_NOTICE_2: "Серверны тәмамланганчы яңадан эшләтеп җибәрмәгез."
|
||||
PURGE_OPTIMIZING: "Мәгълүмат базасы оптимальләштерелә. Зинһар, көтегез..."
|
||||
PURGE_PROCESSING: "Эшкәртү {0} мәгълүматлар..."
|
||||
PURGE_REPAIRING: "Төзәтергә тырышам. Бу бераз вакыт алырга мөмкин..."
|
||||
PURGE_ROWS: "{0} {рәт|рәтләр} бетерелгән мәгълүматлар саны."
|
||||
PURGE_STARTED: "Мәгълүматларны чистарту башланды \"{0}\"."
|
||||
PURGE_SUCCESS: "Мәгълүматларны чистарту уңышлы тәмамланды."
|
||||
RAM_STATS: "{0}ГБ / {1}ГБ оператив хәтер"
|
||||
RELOAD_STARTED: "Конфигурация яңадан йөкләнә - зинһар, көтегез."
|
||||
RELOAD_SUCCESS: "Конфигурация уңышлы яңадан йөкләнде."
|
||||
ROLLBACK_ABORTED: "Кире кайтару яки торгызу туктатылды."
|
||||
ROLLBACK_CHUNKS_FOUND: "Табылды {0} {кисәк|кисәк} үзгәртү өчен."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "Үзгәртелгән {0}/{1} {кисәк|кисәкчәләр}."
|
||||
ROLLBACK_COMPLETED: "{Кире кайтару|Төзетү|Алдан карау} өчен тәмамланды \"{0}\"."
|
||||
ROLLBACK_EXCLUDED_USERS: "Чыгарылган {кулланучы|кулланучылар}: \"{0}\"."
|
||||
ROLLBACK_INCLUDE: "{Кертелгән|Чыгарылган} {блок|объект|максат} {төр|төрләр}: \"{0}\"."
|
||||
ROLLBACK_IN_PROGRESS: "Кире кайтару/торгызу процессы инде бара."
|
||||
ROLLBACK_LENGTH: "Кирәкле вакыт: {0} {секунд|секунд}."
|
||||
ROLLBACK_MODIFIED: "{Үзгәртелгән|Үзгәртелә} {0}."
|
||||
ROLLBACK_RADIUS: "Радиус: {0} {блок|блоклар}."
|
||||
ROLLBACK_SELECTION: "Радиус \"га куелды{0}\"."
|
||||
ROLLBACK_STARTED: "{Кире кайтару|Төзетү|Алдан карау} башланды \"{0}\"."
|
||||
ROLLBACK_TIME: "Вакыт диапазоны: {0}."
|
||||
ROLLBACK_WORLD_ACTION: "Чикләнгән {дөнья|гамәл} \"{0}\"."
|
||||
SIGN_HEADER: "Хәбәрләргә кул кую"
|
||||
STATUS_CONSUMER: "Кулланучы: {0} {әйбер|әйберләр} чиратта"
|
||||
STATUS_DATABASE: "Мәгълүмат базасы: Куллану {0}."
|
||||
STATUS_INTEGRATION: "{0}: Интеграция {активлаштырылган|сүндерелгән}."
|
||||
STATUS_LICENSE: "Лицензия: {0}"
|
||||
STATUS_SYSTEM: "Система: {0}"
|
||||
STATUS_VERSION: "Версия: {0}"
|
||||
TELEPORTED: "Телепортацияләнгән {0}."
|
||||
TELEPORTED_SAFETY: "Сезне куркынычсыз урынга телепортладылар."
|
||||
TELEPORT_PLAYERS: "Телепорт командасын бары тик уенчылар гына куллана ала."
|
||||
TIME_DAYS: "{0} {көн|көннәр}"
|
||||
TIME_HOURS: "{0} {сәгать|сәгатьләр}"
|
||||
TIME_MINUTES: "{0} {минут|минут}"
|
||||
TIME_SECONDS: "{0} {секунд|секунд}"
|
||||
TIME_WEEKS: "{0} {атна|атналар}"
|
||||
UPDATE_ERROR: "Яңартуларны тикшергәндә хата килеп чыкты."
|
||||
UPDATE_HEADER: "{0} Яңарту"
|
||||
UPDATE_NOTICE: "Игътибар: {0} хәзер мөмкин."
|
||||
UPGRADE_IN_PROGRESS: "Яңарту бара. Зинһар, соңрак кабатлап карагыз."
|
||||
USER_NOT_FOUND: "Кулланучы \"{0}\" табылмады.\""
|
||||
USER_OFFLINE: "Кулланучы \"{0}\" онлайн түгел.\""
|
||||
USING_MYSQL: "Куллану MySQL мәгълүматларны саклау өчен."
|
||||
USING_SQLITE: "Куллану SQLite мәгълүматларны саклау өчен."
|
||||
VALID_DONATION_KEY: "Гамәлдәге иганә ачкычы."
|
||||
VERSION_NOTICE: "Версия {0} хәзер мөмкин."
|
||||
VERSION_REQUIRED: "{0} {1} яки аннан да югарырак таләп ителә."
|
||||
WORLD_NOT_FOUND: "Дөнья \"{0}\" табылмады.\""
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>CoreProtect</artifactId>
|
||||
<version>23.1</version>
|
||||
<version>24.1</version>
|
||||
<properties>
|
||||
<project.branch></project.branch>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -26,7 +26,7 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<version>3.15.0</version>
|
||||
<configuration>
|
||||
<source>11</source>
|
||||
<target>11</target>
|
||||
@@ -47,7 +47,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<version>3.5.0</version>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
@@ -59,7 +59,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<version>3.6.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
@@ -73,6 +73,8 @@
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
<exclude>**/*.c</exclude>
|
||||
<exclude>module-info.class</exclude>
|
||||
<exclude>META-INF/versions/**/module-info.class</exclude>
|
||||
<exclude>META-INF/maven/**/pom.properties</exclude>
|
||||
<exclude>META-INF/services/**</exclude>
|
||||
</excludes>
|
||||
@@ -105,7 +107,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>3.2.3</version>
|
||||
<version>3.5.5</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<plugin.version>${project.version}</plugin.version>
|
||||
@@ -116,7 +118,7 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<version>3.6.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
@@ -152,7 +154,7 @@
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.2.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install-validation</id>
|
||||
@@ -209,32 +211,32 @@
|
||||
<dependencies>
|
||||
<!--
|
||||
paper-api: io.papermc.paper
|
||||
paper-api (<= 1.16): com.destroystokyo.paper
|
||||
paper-api (<= 1.16): com.destroystokyo.paper / 1.16.1-R0.1-SNAPSHOT
|
||||
spigot-api: org.spigotmc
|
||||
bukkit: org.bukkit
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.21.11-R0.1-SNAPSHOT</version>
|
||||
<version>26.2.build.48-alpha</version> <!-- https://repo.papermc.io/repository/maven-public/ -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<version>3.2.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastasyncworldedit</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Core</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<version>2.15.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastasyncworldedit</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Bukkit</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<version>2.15.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
@@ -246,22 +248,17 @@
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>5.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.oshi</groupId>
|
||||
<artifactId>oshi-core</artifactId>
|
||||
<version>6.6.2</version>
|
||||
<version>7.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.19.0</version>
|
||||
<version>2.25.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>2.19.0</version>
|
||||
<version>2.25.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.DeadSilenceIV</groupId>
|
||||
@@ -273,31 +270,31 @@
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<version>5.14.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<version>5.14.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.10.1</version>
|
||||
<version>5.14.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>5.16.1</version>
|
||||
<version>5.23.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<version>5.16.1</version>
|
||||
<version>5.23.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@@ -309,25 +306,25 @@
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<version>3.45.1.0</version>
|
||||
<version>3.53.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>2.0.12</version>
|
||||
<version>2.0.17</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.18.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.bytebuddy</groupId>
|
||||
<artifactId>byte-buddy-agent</artifactId>
|
||||
<version>1.16.1</version>
|
||||
<version>1.18.8</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coreprotect;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
@@ -16,8 +17,6 @@ import net.coreprotect.utility.Chat;
|
||||
public final class CoreProtect extends JavaPlugin {
|
||||
|
||||
private static CoreProtect instance;
|
||||
private boolean advancedChestsEnabled = false;
|
||||
|
||||
/**
|
||||
* Get the instance of CoreProtect
|
||||
*
|
||||
@@ -44,7 +43,6 @@ public final class CoreProtect extends JavaPlugin {
|
||||
instance = this;
|
||||
ConfigHandler.path = this.getDataFolder().getPath() + File.separator;
|
||||
|
||||
advancedChestsEnabled = getServer().getPluginManager().getPlugin("AdvancedChests") != null;
|
||||
// Initialize plugin using the initialization service
|
||||
boolean initialized = PluginInitializationService.initializePlugin(this);
|
||||
|
||||
@@ -61,6 +59,7 @@ public final class CoreProtect extends JavaPlugin {
|
||||
}
|
||||
|
||||
public boolean isAdvancedChestsEnabled() {
|
||||
return advancedChestsEnabled;
|
||||
Plugin advancedChests = getServer().getPluginManager().getPlugin("AdvancedChests");
|
||||
return advancedChests != null && advancedChests.isEnabled();
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,22 @@ import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import net.coreprotect.api.BlockAPI;
|
||||
import net.coreprotect.api.InventoryAPI;
|
||||
import net.coreprotect.api.ItemAPI;
|
||||
import net.coreprotect.api.LookupOptions;
|
||||
import net.coreprotect.api.MessageAPI;
|
||||
import net.coreprotect.api.QueueLookup;
|
||||
import net.coreprotect.api.SessionLookup;
|
||||
import net.coreprotect.api.SignAPI;
|
||||
import net.coreprotect.api.UsernameAPI;
|
||||
import net.coreprotect.api.result.BlockResult;
|
||||
import net.coreprotect.api.result.ContainerResult;
|
||||
import net.coreprotect.api.result.InventoryResult;
|
||||
import net.coreprotect.api.result.ItemResult;
|
||||
import net.coreprotect.api.result.MessageResult;
|
||||
import net.coreprotect.api.result.SignResult;
|
||||
import net.coreprotect.api.result.SessionResult;
|
||||
import net.coreprotect.api.result.UsernameResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.Database;
|
||||
@@ -29,6 +43,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.listener.player.InventoryChangeListener;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* The main API class for CoreProtect.
|
||||
@@ -41,7 +56,7 @@ public class CoreProtectAPI extends Queue {
|
||||
/**
|
||||
* Current version of the API
|
||||
*/
|
||||
private static final int API_VERSION = 11;
|
||||
private static final int API_VERSION = 12;
|
||||
|
||||
public static class ParseResult extends net.coreprotect.api.result.ParseResult {
|
||||
|
||||
@@ -68,7 +83,7 @@ public class CoreProtectAPI extends Queue {
|
||||
|
||||
if (list != null) {
|
||||
for (Object value : list) {
|
||||
if (value instanceof Material || value instanceof EntityType) {
|
||||
if (value instanceof Material || value instanceof EntityType || value instanceof String) {
|
||||
result.put(value, false);
|
||||
}
|
||||
else if (value instanceof Integer) {
|
||||
@@ -106,6 +121,22 @@ public class CoreProtectAPI extends Queue {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed block lookup at the specified block.
|
||||
*
|
||||
* @param block
|
||||
* The block to look up
|
||||
* @param options
|
||||
* Lookup options. User, time, and limit are applied; location and radius are ignored because the block supplies the exact location.
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<BlockResult> blockLookup(Block block, LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return BlockAPI.performLookup(block, options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a lookup on the queue data for the specified block.
|
||||
*
|
||||
@@ -117,6 +148,64 @@ public class CoreProtectAPI extends Queue {
|
||||
return QueueLookup.performLookup(block);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a container lookup at the specified location.
|
||||
*
|
||||
* @param location
|
||||
* The location to look up
|
||||
* @param time
|
||||
* Time constraint in seconds
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<ContainerResult> containerLookup(Location location, int time) {
|
||||
if (isEnabled()) {
|
||||
return BlockAPI.performContainerLookup(location, time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a container lookup with shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<ContainerResult> containerLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return BlockAPI.performContainerLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed lookup on world item transactions.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<ItemResult> itemLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return ItemAPI.performLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed lookup on player inventory transactions.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<InventoryResult> inventoryLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return InventoryAPI.performLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a lookup on session data for the specified user.
|
||||
*
|
||||
@@ -130,6 +219,140 @@ public class CoreProtectAPI extends Queue {
|
||||
return SessionLookup.performLookup(user, time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed lookup on session data.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<SessionResult> sessionLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return SessionLookup.performLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a username history lookup for the specified user.
|
||||
*
|
||||
* @param user
|
||||
* The user or UUID to look up, or #global/null for all users
|
||||
* @param time
|
||||
* Time constraint in seconds
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<UsernameResult> usernameLookup(String user, int time) {
|
||||
if (isEnabled()) {
|
||||
return UsernameAPI.performLookup(user, time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a username history lookup with shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options. User, time, and limit are applied; location and radius are ignored.
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<UsernameResult> usernameLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return UsernameAPI.performLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a chat message lookup for the specified user.
|
||||
*
|
||||
* @param user
|
||||
* The user to look up, or #global/null for all users
|
||||
* @param time
|
||||
* Time constraint in seconds
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<MessageResult> chatLookup(String user, int time) {
|
||||
if (isEnabled()) {
|
||||
return MessageAPI.performChatLookup(user, time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a chat message lookup with shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<MessageResult> chatLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return MessageAPI.performChatLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a command lookup for the specified user.
|
||||
*
|
||||
* @param user
|
||||
* The user to look up, or #global/null for all users
|
||||
* @param time
|
||||
* Time constraint in seconds
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<MessageResult> commandLookup(String user, int time) {
|
||||
if (isEnabled()) {
|
||||
return MessageAPI.performCommandLookup(user, time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a command lookup with shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<MessageResult> commandLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return MessageAPI.performCommandLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a sign text lookup at the specified location.
|
||||
*
|
||||
* @param location
|
||||
* The location to look up
|
||||
* @param time
|
||||
* Time constraint in seconds
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<SignResult> signLookup(Location location, int time) {
|
||||
if (isEnabled()) {
|
||||
return SignAPI.performLookup(location, time);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a sign text lookup with shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results or null if API is disabled
|
||||
*/
|
||||
public List<SignResult> signLookup(LookupOptions options) {
|
||||
if (isEnabled()) {
|
||||
return SignAPI.performLookup(options);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a user has placed a block at the specified location.
|
||||
*
|
||||
@@ -341,6 +564,27 @@ public class CoreProtectAPI extends Queue {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a block placement by a user with specific block data.
|
||||
*
|
||||
* @param user
|
||||
* The username
|
||||
* @param location
|
||||
* The location
|
||||
* @param blockData
|
||||
* The block data
|
||||
* @return True if the placement was logged
|
||||
*/
|
||||
public boolean logPlacement(String user, Location location, BlockData blockData) {
|
||||
if (!isEnabled() || !isValidUserAndLocation(user, location) || blockData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block block = location.getBlock();
|
||||
Queue.queueBlockPlace(user, block.getState(), block.getType(), null, block.getType(), -1, 0, blockData.getAsString());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a block placement by a user with a specific material and data value.
|
||||
*
|
||||
@@ -412,6 +656,28 @@ public class CoreProtectAPI extends Queue {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a block removal by a user with specific block data.
|
||||
*
|
||||
* @param user
|
||||
* The username
|
||||
* @param location
|
||||
* The location
|
||||
* @param blockData
|
||||
* The block data
|
||||
* @return True if the removal was logged
|
||||
*/
|
||||
public boolean logRemoval(String user, Location location, BlockData blockData) {
|
||||
if (!isEnabled() || !isValidUserAndLocation(user, location) || blockData == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Block block = location.getBlock();
|
||||
Database.containerBreakCheck(user, block.getType(), block, null, location);
|
||||
Queue.queueBlockBreak(user, block.getState(), block.getType(), blockData.getAsString(), 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a block removal by a user with a specific material and data value.
|
||||
*
|
||||
@@ -830,7 +1096,7 @@ public class CoreProtectAPI extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
import net.coreprotect.api.result.BlockResult;
|
||||
import net.coreprotect.api.result.ContainerResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
@@ -15,6 +19,7 @@ import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.StringUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for block-related lookups in the CoreProtect database.
|
||||
@@ -93,9 +98,187 @@ public class BlockAPI {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed lookup of block-related actions at the specified block.
|
||||
*
|
||||
* @param block
|
||||
* The block to look up
|
||||
* @param options
|
||||
* Lookup options. User, time, and limit are applied; location and radius are ignored because the block supplies the exact location.
|
||||
* @return List of results in a BlockResult format
|
||||
*/
|
||||
public static List<BlockResult> performLookup(Block block, LookupOptions options) {
|
||||
List<BlockResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (block == null || block.getWorld() == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (options == null) {
|
||||
options = LookupOptions.builder().build();
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Integer userId = MessageAPI.getUserId(connection, options.getUser());
|
||||
if (userId != null && userId == -1) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int checkTime = 0;
|
||||
if (options.getTime() > 0) {
|
||||
checkTime = (int) (System.currentTimeMillis() / 1000L) - options.getTime();
|
||||
}
|
||||
|
||||
int x = block.getX();
|
||||
int y = block.getY();
|
||||
int z = block.getZ();
|
||||
String worldName = block.getWorld().getName();
|
||||
int worldId = WorldUtils.getWorldId(worldName);
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,action,type,data,blockdata,rolled_back,wid,x,y,z FROM ");
|
||||
query.append(ConfigHandler.prefix).append("block ").append(WorldUtils.getWidIndex("block"));
|
||||
query.append("WHERE wid = ? AND x = ? AND z = ? AND y = ? AND time > ?");
|
||||
if (userId != null) {
|
||||
query.append(" AND user = ?");
|
||||
}
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
if (options.hasLimit()) {
|
||||
query.append(" LIMIT ").append(options.getLimitOffset()).append(", ").append(options.getLimitCount());
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
statement.setInt(1, worldId);
|
||||
statement.setInt(2, x);
|
||||
statement.setInt(3, z);
|
||||
statement.setInt(4, y);
|
||||
statement.setInt(5, checkTime);
|
||||
if (userId != null) {
|
||||
statement.setInt(6, userId);
|
||||
}
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseBlockResult(connection, results, worldName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a lookup of container transactions at the specified location.
|
||||
*
|
||||
* @param location
|
||||
* The location to look up
|
||||
* @param offset
|
||||
* Time constraint in seconds (0 means no time constraint)
|
||||
* @return List of results in a ContainerResult format
|
||||
*/
|
||||
public static List<ContainerResult> performContainerLookup(Location location, int offset) {
|
||||
if (location == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return performContainerLookup(LookupOptions.builder().time(offset).location(location).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a lookup of container transactions using shared lookup options.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of results in a ContainerResult format
|
||||
*/
|
||||
public static List<ContainerResult> performContainerLookup(LookupOptions options) {
|
||||
List<ContainerResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,action,type,data,amount,metadata,rolled_back FROM ");
|
||||
query.append(ConfigHandler.prefix).append("container ");
|
||||
if (filter.hasLocation()) {
|
||||
query.append(WorldUtils.getWidIndex("container"));
|
||||
}
|
||||
filter.appendWhere(query);
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
filter.appendLimit(query);
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
filter.bind(statement);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseContainerResult(connection, results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ContainerResult parseContainerResult(Connection connection, ResultSet results) throws Exception {
|
||||
int resultUserId = results.getInt("user");
|
||||
String resultUser = ConfigHandler.playerIdCacheReversed.get(resultUserId);
|
||||
if (resultUser == null) {
|
||||
resultUser = UserStatement.loadName(connection, resultUserId);
|
||||
}
|
||||
|
||||
return new ContainerResult(
|
||||
results.getLong("time"), resultUser, WorldUtils.getWorldName(results.getInt("wid")), results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
results.getInt("type"), results.getInt("data"), results.getInt("amount"), results.getBytes("metadata"),
|
||||
results.getInt("action"), results.getInt("rolled_back")
|
||||
);
|
||||
}
|
||||
|
||||
private static BlockResult parseBlockResult(Connection connection, ResultSet results, String worldName) throws Exception {
|
||||
int resultUserId = results.getInt("user");
|
||||
String resultUser = ConfigHandler.playerIdCacheReversed.get(resultUserId);
|
||||
if (resultUser == null) {
|
||||
resultUser = UserStatement.loadName(connection, resultUserId);
|
||||
}
|
||||
|
||||
int resultType = results.getInt("type");
|
||||
String blockData = BlockUtils.byteDataToString(results.getBytes("blockdata"), resultType);
|
||||
|
||||
return new BlockResult(
|
||||
results.getLong("time"), resultUser, worldName, results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
resultType, results.getInt("data"), blockData, results.getInt("action"), results.getInt("rolled_back")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
|
||||
/**
|
||||
* CoreProtect action identifiers used by lookup filters.
|
||||
*/
|
||||
public enum CoreProtectAction {
|
||||
BLOCK_BREAK(LookupActions.BLOCK_BREAK),
|
||||
BLOCK_PLACE(LookupActions.BLOCK_PLACE),
|
||||
INTERACTION(LookupActions.INTERACTION),
|
||||
ENTITY_KILL(LookupActions.ENTITY_KILL),
|
||||
CONTAINER(LookupActions.CONTAINER),
|
||||
CHAT(LookupActions.CHAT),
|
||||
COMMAND(LookupActions.COMMAND),
|
||||
SESSION(LookupActions.SESSION),
|
||||
USERNAME(LookupActions.USERNAME),
|
||||
SIGN(LookupActions.SIGN),
|
||||
ITEM(LookupActions.ITEM),
|
||||
UNKNOWN(-1);
|
||||
|
||||
private final int id;
|
||||
|
||||
CoreProtectAction(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int id() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String actionString() {
|
||||
return LookupActions.getActionString(id);
|
||||
}
|
||||
|
||||
public static CoreProtectAction fromId(int id) {
|
||||
for (CoreProtectAction action : values()) {
|
||||
if (action.id == id) {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.coreprotect.api.result.InventoryResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for normalized player inventory transaction lookups.
|
||||
*/
|
||||
public class InventoryAPI {
|
||||
|
||||
private InventoryAPI() {
|
||||
throw new IllegalStateException("API class");
|
||||
}
|
||||
|
||||
public static List<InventoryResult> performLookup(LookupOptions options) {
|
||||
List<InventoryResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (options == null) {
|
||||
options = LookupOptions.builder().build();
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder whereBuilder = new StringBuilder();
|
||||
filter.appendWhere(whereBuilder);
|
||||
String where = whereBuilder.toString();
|
||||
String query = buildQuery(where, options.hasLimit());
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query)) {
|
||||
int parameterIndex = filter.bind(statement);
|
||||
parameterIndex = filter.bind(statement, parameterIndex);
|
||||
parameterIndex = filter.bind(statement, parameterIndex);
|
||||
if (options.hasLimit()) {
|
||||
statement.setInt(parameterIndex++, options.getLimitOffset());
|
||||
statement.setInt(parameterIndex, options.getLimitCount());
|
||||
}
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseInventoryResult(connection, results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String buildQuery(String where, boolean hasLimit) {
|
||||
StringBuilder query = new StringBuilder("SELECT * FROM (");
|
||||
query.append("SELECT 0 AS source,rowid AS id,time,user,wid,x,y,z,type,data,1 AS amount,meta AS metadata,action,rolled_back FROM ")
|
||||
.append(ConfigHandler.prefix).append("block ").append(where).append(" AND action = 1");
|
||||
query.append(" UNION ALL ");
|
||||
query.append("SELECT 1 AS source,rowid AS id,time,user,wid,x,y,z,type,data,amount,metadata,action,rolled_back FROM ")
|
||||
.append(ConfigHandler.prefix).append("container ").append(where);
|
||||
query.append(" UNION ALL ");
|
||||
query.append("SELECT 2 AS source,rowid AS id,time,user,wid,x,y,z,type,0 AS data,amount,data AS metadata,action,rolled_back FROM ")
|
||||
.append(ConfigHandler.prefix).append("item ").append(where);
|
||||
query.append(") AS inventory_lookup ORDER BY time DESC, source DESC, id DESC");
|
||||
if (hasLimit) {
|
||||
query.append(" LIMIT ?, ?");
|
||||
}
|
||||
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
private static InventoryResult parseInventoryResult(Connection connection, ResultSet results) throws Exception {
|
||||
int userId = results.getInt("user");
|
||||
String username = ConfigHandler.playerIdCacheReversed.get(userId);
|
||||
if (username == null) {
|
||||
username = UserStatement.loadName(connection, userId);
|
||||
}
|
||||
|
||||
return new InventoryResult(
|
||||
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
|
||||
results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
results.getInt("type"), results.getInt("data"), results.getInt("amount"), results.getBytes("metadata"),
|
||||
results.getInt("action"), results.getInt("rolled_back"), results.getInt("source")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.coreprotect.api.result.ItemResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.logger.ItemLogger;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for world item transaction lookups.
|
||||
*/
|
||||
public class ItemAPI {
|
||||
|
||||
private ItemAPI() {
|
||||
throw new IllegalStateException("API class");
|
||||
}
|
||||
|
||||
public static List<ItemResult> performLookup(LookupOptions options) {
|
||||
List<ItemResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,type,data,amount,action,rolled_back FROM ");
|
||||
query.append(ConfigHandler.prefix).append("item ");
|
||||
if (filter.hasLocation()) {
|
||||
query.append(WorldUtils.getWidIndex("item"));
|
||||
}
|
||||
filter.appendWhere(query);
|
||||
query.append(" AND action NOT IN (")
|
||||
.append(ItemLogger.ITEM_BREAK).append(",")
|
||||
.append(ItemLogger.ITEM_DESTROY).append(",")
|
||||
.append(ItemLogger.ITEM_CREATE).append(",")
|
||||
.append(ItemLogger.ITEM_SELL).append(",")
|
||||
.append(ItemLogger.ITEM_BUY).append(")");
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
filter.appendLimit(query);
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
filter.bind(statement);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseItemResult(connection, results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static ItemResult parseItemResult(Connection connection, ResultSet results) throws Exception {
|
||||
int userId = results.getInt("user");
|
||||
String username = ConfigHandler.playerIdCacheReversed.get(userId);
|
||||
if (username == null) {
|
||||
username = UserStatement.loadName(connection, userId);
|
||||
}
|
||||
|
||||
return new ItemResult(
|
||||
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
|
||||
results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
results.getInt("type"), results.getInt("amount"), results.getBytes("data"),
|
||||
results.getInt("action"), results.getInt("rolled_back")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
|
||||
final class LookupFilter {
|
||||
private final Integer userId;
|
||||
private final int checkTime;
|
||||
private final Location location;
|
||||
private final int radius;
|
||||
private final int limitOffset;
|
||||
private final int limitCount;
|
||||
|
||||
private LookupFilter(Integer userId, int checkTime, Location location, int radius, int limitOffset, int limitCount) {
|
||||
this.userId = userId;
|
||||
this.checkTime = checkTime;
|
||||
this.location = location;
|
||||
this.radius = radius;
|
||||
this.limitOffset = limitOffset;
|
||||
this.limitCount = limitCount;
|
||||
}
|
||||
|
||||
static LookupFilter fromOptions(Connection connection, LookupOptions options) throws Exception {
|
||||
if (options == null) {
|
||||
options = LookupOptions.builder().build();
|
||||
}
|
||||
|
||||
Integer userId = MessageAPI.getUserId(connection, options.getUser());
|
||||
int checkTime = 0;
|
||||
if (options.getTime() > 0) {
|
||||
checkTime = (int) (System.currentTimeMillis() / 1000L) - options.getTime();
|
||||
}
|
||||
|
||||
return new LookupFilter(userId, checkTime, options.getLocation(), options.getRadius(), options.getLimitOffset(), options.getLimitCount());
|
||||
}
|
||||
|
||||
boolean hasInvalidUser() {
|
||||
return userId != null && userId == -1;
|
||||
}
|
||||
|
||||
boolean hasInvalidLocation() {
|
||||
return location != null && location.getWorld() == null;
|
||||
}
|
||||
|
||||
boolean hasLocation() {
|
||||
return location != null;
|
||||
}
|
||||
|
||||
void appendWhere(StringBuilder query) {
|
||||
query.append("WHERE time > ?");
|
||||
|
||||
if (userId != null) {
|
||||
query.append(" AND user = ?");
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
query.append(" AND wid = ?");
|
||||
if (radius > 0) {
|
||||
query.append(" AND x >= ? AND x <= ? AND z >= ? AND z <= ?");
|
||||
}
|
||||
else {
|
||||
query.append(" AND x = ? AND y = ? AND z = ?");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void appendLimit(StringBuilder query) {
|
||||
if (limitOffset >= 0 && limitCount >= 0) {
|
||||
query.append(" LIMIT ").append(limitOffset).append(", ").append(limitCount);
|
||||
}
|
||||
}
|
||||
|
||||
int bind(PreparedStatement statement) throws Exception {
|
||||
return bind(statement, 1);
|
||||
}
|
||||
|
||||
int bind(PreparedStatement statement, int parameterIndex) throws Exception {
|
||||
statement.setInt(parameterIndex++, checkTime);
|
||||
|
||||
if (userId != null) {
|
||||
statement.setInt(parameterIndex++, userId);
|
||||
}
|
||||
|
||||
if (location != null) {
|
||||
int x = location.getBlockX();
|
||||
int y = location.getBlockY();
|
||||
int z = location.getBlockZ();
|
||||
statement.setInt(parameterIndex++, WorldUtils.getWorldId(location.getWorld().getName()));
|
||||
|
||||
if (radius > 0) {
|
||||
statement.setInt(parameterIndex++, MessageAPI.clampToInt((long) x - radius));
|
||||
statement.setInt(parameterIndex++, MessageAPI.clampToInt((long) x + radius));
|
||||
statement.setInt(parameterIndex++, MessageAPI.clampToInt((long) z - radius));
|
||||
statement.setInt(parameterIndex++, MessageAPI.clampToInt((long) z + radius));
|
||||
}
|
||||
else {
|
||||
statement.setInt(parameterIndex++, x);
|
||||
statement.setInt(parameterIndex++, y);
|
||||
statement.setInt(parameterIndex++, z);
|
||||
}
|
||||
}
|
||||
|
||||
return parameterIndex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
/**
|
||||
* Shared options for typed lookup API methods.
|
||||
*/
|
||||
public final class LookupOptions {
|
||||
private final String user;
|
||||
private final int time;
|
||||
private final int radius;
|
||||
private final Location location;
|
||||
private final int limitOffset;
|
||||
private final int limitCount;
|
||||
|
||||
private LookupOptions(Builder builder) {
|
||||
this.user = builder.user;
|
||||
this.time = builder.time;
|
||||
this.radius = builder.radius;
|
||||
this.location = builder.location;
|
||||
this.limitOffset = builder.limitOffset;
|
||||
this.limitCount = builder.limitCount;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public String getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public int getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getRadius() {
|
||||
return radius;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getLimitOffset() {
|
||||
return limitOffset;
|
||||
}
|
||||
|
||||
public int getLimitCount() {
|
||||
return limitCount;
|
||||
}
|
||||
|
||||
public boolean hasLimit() {
|
||||
return limitOffset >= 0 && limitCount >= 0;
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String user;
|
||||
private int time;
|
||||
private int radius = -1;
|
||||
private Location location;
|
||||
private int limitOffset = -1;
|
||||
private int limitCount = -1;
|
||||
|
||||
private Builder() {
|
||||
}
|
||||
|
||||
public Builder user(String user) {
|
||||
this.user = user;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder time(int time) {
|
||||
this.time = time;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder location(Location location) {
|
||||
this.location = location;
|
||||
this.radius = 0;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder radius(Location location, int radius) {
|
||||
this.location = location;
|
||||
this.radius = radius;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder limit(int offset, int count) {
|
||||
this.limitOffset = offset;
|
||||
this.limitCount = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
public LookupOptions build() {
|
||||
return new LookupOptions(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import net.coreprotect.api.result.MessageResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for player chat and command lookups.
|
||||
*/
|
||||
public class MessageAPI {
|
||||
private MessageAPI() {
|
||||
throw new IllegalStateException("API class");
|
||||
}
|
||||
|
||||
public static List<MessageResult> performChatLookup(String user, int offset) {
|
||||
return performChatLookup(LookupOptions.builder().user(user).time(offset).build());
|
||||
}
|
||||
|
||||
public static List<MessageResult> performChatLookup(LookupOptions options) {
|
||||
return performLookup("chat", CoreProtectAction.CHAT, options);
|
||||
}
|
||||
|
||||
public static List<MessageResult> performCommandLookup(String user, int offset) {
|
||||
return performCommandLookup(LookupOptions.builder().user(user).time(offset).build());
|
||||
}
|
||||
|
||||
public static List<MessageResult> performCommandLookup(LookupOptions options) {
|
||||
return performLookup("command", CoreProtectAction.COMMAND, options);
|
||||
}
|
||||
|
||||
private static List<MessageResult> performLookup(String table, CoreProtectAction action, LookupOptions options) {
|
||||
List<MessageResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,message FROM ");
|
||||
query.append(ConfigHandler.prefix).append(table).append(" ");
|
||||
if (filter.hasLocation()) {
|
||||
query.append(WorldUtils.getWidIndex(table));
|
||||
}
|
||||
filter.appendWhere(query);
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
filter.appendLimit(query);
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
filter.bind(statement);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseMessageResult(connection, results, action.id()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static Integer getUserId(Connection connection, String user) throws Exception {
|
||||
if (user == null || user.isEmpty() || user.equalsIgnoreCase("#global")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer cachedId = ConfigHandler.playerIdCache.get(user.toLowerCase(java.util.Locale.ROOT));
|
||||
if (cachedId != null) {
|
||||
return cachedId;
|
||||
}
|
||||
|
||||
String collate = Config.getGlobal().MYSQL ? "" : " COLLATE NOCASE";
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT rowid AS id FROM " + ConfigHandler.prefix + "user WHERE user = ?" + collate + " ORDER BY rowid ASC LIMIT 0, 1")) {
|
||||
statement.setString(1, user);
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
if (results.next()) {
|
||||
int id = results.getInt("id");
|
||||
ConfigHandler.playerIdCache.put(user.toLowerCase(java.util.Locale.ROOT), id);
|
||||
ConfigHandler.playerIdCacheReversed.put(id, user);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static MessageResult parseMessageResult(Connection connection, ResultSet results, int actionId) throws Exception {
|
||||
int userId = results.getInt("user");
|
||||
String username = ConfigHandler.playerIdCacheReversed.get(userId);
|
||||
if (username == null) {
|
||||
username = UserStatement.loadName(connection, userId);
|
||||
}
|
||||
|
||||
return new MessageResult(
|
||||
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
|
||||
results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
results.getString("message"), actionId
|
||||
);
|
||||
}
|
||||
|
||||
static int clampToInt(long value) {
|
||||
if (value > Integer.MAX_VALUE) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
else if (value < Integer.MIN_VALUE) {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
|
||||
return (int) value;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package net.coreprotect.api;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
@@ -18,6 +17,7 @@ import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.StringUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for looking up block-related actions in the processing queue.
|
||||
@@ -70,9 +70,7 @@ public class QueueLookup extends Queue {
|
||||
Location blockLocation = block.getLocation();
|
||||
|
||||
// Check for block actions in the processing queue
|
||||
ListIterator<Object[]> iterator = consumerData.listIterator();
|
||||
while (iterator.hasNext()) {
|
||||
Object[] data = iterator.next();
|
||||
for (Object[] data : consumerData.toArray(Object[][]::new)) {
|
||||
int id = (int) data[0];
|
||||
int action = (int) data[1];
|
||||
|
||||
@@ -106,7 +104,7 @@ public class QueueLookup extends Queue {
|
||||
Collections.reverse(result);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.coreprotect.api.result.SessionResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for looking up player session data in the CoreProtect database.
|
||||
@@ -78,7 +82,57 @@ public class SessionLookup {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a typed lookup of session-related actions.
|
||||
*
|
||||
* @param options
|
||||
* Lookup options
|
||||
* @return List of typed session results, empty list if API is disabled or no results found
|
||||
*/
|
||||
public static List<SessionResult> performLookup(LookupOptions options) {
|
||||
List<SessionResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,action FROM ");
|
||||
query.append(ConfigHandler.prefix).append("session ");
|
||||
if (filter.hasLocation()) {
|
||||
query.append(WorldUtils.getWidIndex("session"));
|
||||
}
|
||||
filter.appendWhere(query);
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
filter.appendLimit(query);
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
filter.bind(statement);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseSessionResult(connection, results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -161,4 +215,17 @@ public class SessionLookup {
|
||||
// Create and return the session data array
|
||||
return new String[] { resultTime, resultUser, resultX, resultY, resultZ, resultWorldId, type, resultAction };
|
||||
}
|
||||
|
||||
private static SessionResult parseSessionResult(Connection connection, ResultSet results) throws Exception {
|
||||
int userId = results.getInt("user");
|
||||
String username = ConfigHandler.playerIdCacheReversed.get(userId);
|
||||
if (username == null) {
|
||||
username = UserStatement.loadName(connection, userId);
|
||||
}
|
||||
|
||||
return new SessionResult(
|
||||
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
|
||||
results.getInt("x"), results.getInt("y"), results.getInt("z"), results.getInt("action")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.bukkit.Location;
|
||||
|
||||
import net.coreprotect.api.result.SignResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.model.action.SignActions;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for sign text lookups.
|
||||
*/
|
||||
public class SignAPI {
|
||||
|
||||
private SignAPI() {
|
||||
throw new IllegalStateException("API class");
|
||||
}
|
||||
|
||||
public static List<SignResult> performLookup(Location location, int offset) {
|
||||
if (location == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return performLookup(LookupOptions.builder().time(offset).location(location).build());
|
||||
}
|
||||
|
||||
public static List<SignResult> performLookup(LookupOptions options) {
|
||||
List<SignResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LookupFilter filter = LookupFilter.fromOptions(connection, options);
|
||||
if (filter.hasInvalidUser() || filter.hasInvalidLocation()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,user,wid,x,y,z,action,color,color_secondary,data,waxed,face,line_1,line_2,line_3,line_4,line_5,line_6,line_7,line_8 FROM ");
|
||||
query.append(ConfigHandler.prefix).append("sign ");
|
||||
if (filter.hasLocation()) {
|
||||
query.append(WorldUtils.getWidIndex("sign"));
|
||||
}
|
||||
filter.appendWhere(query);
|
||||
query.append(" AND action = '").append(SignActions.PLACE).append("' AND (LENGTH(line_1) > 0 OR LENGTH(line_2) > 0 OR LENGTH(line_3) > 0 OR LENGTH(line_4) > 0 OR LENGTH(line_5) > 0 OR LENGTH(line_6) > 0 OR LENGTH(line_7) > 0 OR LENGTH(line_8) > 0)");
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
filter.appendLimit(query);
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
filter.bind(statement);
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseSignResult(connection, results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static SignResult parseSignResult(Connection connection, ResultSet results) throws Exception {
|
||||
int userId = results.getInt("user");
|
||||
String username = ConfigHandler.playerIdCacheReversed.get(userId);
|
||||
if (username == null) {
|
||||
username = UserStatement.loadName(connection, userId);
|
||||
}
|
||||
|
||||
String[] lines = new String[] {
|
||||
valueOrEmpty(results.getString("line_1")),
|
||||
valueOrEmpty(results.getString("line_2")),
|
||||
valueOrEmpty(results.getString("line_3")),
|
||||
valueOrEmpty(results.getString("line_4")),
|
||||
valueOrEmpty(results.getString("line_5")),
|
||||
valueOrEmpty(results.getString("line_6")),
|
||||
valueOrEmpty(results.getString("line_7")),
|
||||
valueOrEmpty(results.getString("line_8"))
|
||||
};
|
||||
|
||||
return new SignResult(
|
||||
results.getLong("time"), username, WorldUtils.getWorldName(results.getInt("wid")),
|
||||
results.getInt("x"), results.getInt("y"), results.getInt("z"),
|
||||
results.getInt("action"), results.getInt("color"), results.getInt("color_secondary"),
|
||||
results.getInt("data"), results.getInt("waxed") == 1, results.getInt("face") == 0, lines
|
||||
);
|
||||
}
|
||||
|
||||
private static String valueOrEmpty(String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package net.coreprotect.api;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import net.coreprotect.api.result.UsernameResult;
|
||||
import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
/**
|
||||
* Provides API methods for username history lookups.
|
||||
*/
|
||||
public class UsernameAPI {
|
||||
|
||||
private UsernameAPI() {
|
||||
throw new IllegalStateException("API class");
|
||||
}
|
||||
|
||||
public static List<UsernameResult> performLookup(String user, int offset) {
|
||||
return performLookup(LookupOptions.builder().user(user).time(offset).build());
|
||||
}
|
||||
|
||||
public static List<UsernameResult> performLookup(LookupOptions options) {
|
||||
List<UsernameResult> result = new ArrayList<>();
|
||||
|
||||
if (!Config.getGlobal().API_ENABLED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (options == null) {
|
||||
options = LookupOptions.builder().build();
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(false, 1000)) {
|
||||
if (connection == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
Set<String> uuids = getUuids(connection, options.getUser());
|
||||
if (uuids == null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
int checkTime = 0;
|
||||
if (options.getTime() > 0) {
|
||||
checkTime = (int) (System.currentTimeMillis() / 1000L) - options.getTime();
|
||||
}
|
||||
|
||||
StringBuilder query = new StringBuilder("SELECT time,uuid,user FROM ");
|
||||
query.append(ConfigHandler.prefix).append("username_log WHERE time > ?");
|
||||
if (!uuids.isEmpty()) {
|
||||
query.append(" AND uuid IN (");
|
||||
appendPlaceholders(query, uuids.size());
|
||||
query.append(")");
|
||||
}
|
||||
query.append(" ORDER BY rowid DESC");
|
||||
if (options.hasLimit()) {
|
||||
query.append(" LIMIT ").append(options.getLimitOffset()).append(", ").append(options.getLimitCount());
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement(query.toString())) {
|
||||
int parameterIndex = 1;
|
||||
statement.setInt(parameterIndex++, checkTime);
|
||||
for (String uuid : uuids) {
|
||||
statement.setString(parameterIndex++, uuid);
|
||||
}
|
||||
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(parseUsernameResult(results));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void appendPlaceholders(StringBuilder query, int count) {
|
||||
for (int index = 0; index < count; index++) {
|
||||
if (index > 0) {
|
||||
query.append(",");
|
||||
}
|
||||
query.append("?");
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> getUuids(Connection connection, String user) throws Exception {
|
||||
Set<String> result = new LinkedHashSet<>();
|
||||
|
||||
if (user == null || user.isEmpty() || user.equalsIgnoreCase("#global")) {
|
||||
return result;
|
||||
}
|
||||
|
||||
String cachedUuid = ConfigHandler.uuidCache.get(user.toLowerCase(Locale.ROOT));
|
||||
if (cachedUuid != null) {
|
||||
result.add(cachedUuid);
|
||||
}
|
||||
|
||||
String collate = Config.getGlobal().MYSQL ? "" : " COLLATE NOCASE";
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT uuid FROM " + ConfigHandler.prefix + "user WHERE user = ?" + collate)) {
|
||||
statement.setString(1, user);
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(results.getString("uuid"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try (PreparedStatement statement = connection.prepareStatement("SELECT uuid FROM " + ConfigHandler.prefix + "username_log WHERE user = ?" + collate)) {
|
||||
statement.setString(1, user);
|
||||
try (ResultSet results = statement.executeQuery()) {
|
||||
while (results.next()) {
|
||||
result.add(results.getString("uuid"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (looksLikeUuid(user)) {
|
||||
result.add(user);
|
||||
}
|
||||
|
||||
return result.isEmpty() ? null : result;
|
||||
}
|
||||
|
||||
private static boolean looksLikeUuid(String value) {
|
||||
return value.length() == 36 && value.charAt(8) == '-' && value.charAt(13) == '-' && value.charAt(18) == '-' && value.charAt(23) == '-';
|
||||
}
|
||||
|
||||
private static UsernameResult parseUsernameResult(ResultSet results) throws Exception {
|
||||
String uuid = results.getString("uuid");
|
||||
String username = results.getString("user");
|
||||
String player = ConfigHandler.uuidCacheReversed.get(uuid);
|
||||
if (player == null) {
|
||||
player = username;
|
||||
}
|
||||
|
||||
return new UsernameResult(results.getLong("time"), uuid, username, player);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents a logged block action.
|
||||
*/
|
||||
public class BlockResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int type;
|
||||
private final int data;
|
||||
private final String blockData;
|
||||
private final int actionId;
|
||||
private final int rolledBack;
|
||||
|
||||
public BlockResult(long time, String username, String world, int x, int y, int z, int type, int data, String blockData, int actionId, int rolledBack) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.blockData = blockData;
|
||||
this.actionId = actionId;
|
||||
this.rolledBack = rolledBack;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return LookupActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
if (actionId == LookupActions.ENTITY_KILL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Material material = MaterialUtils.getType(type);
|
||||
if (material == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String typeName = material.name().toLowerCase(Locale.ROOT);
|
||||
return MaterialUtils.getType(StringUtils.nameFilter(typeName, data));
|
||||
}
|
||||
|
||||
public EntityType getEntityType() {
|
||||
if (actionId != LookupActions.ENTITY_KILL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type == 0) {
|
||||
return EntityType.PLAYER;
|
||||
}
|
||||
|
||||
return EntityUtils.getEntityType(type);
|
||||
}
|
||||
|
||||
public BlockData getBlockData() {
|
||||
if (actionId == LookupActions.ENTITY_KILL) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (blockData == null || blockData.isEmpty()) {
|
||||
Material material = getType();
|
||||
if (material != null) {
|
||||
return material.createBlockData();
|
||||
}
|
||||
|
||||
return BlockUtils.createBlockData(type);
|
||||
}
|
||||
|
||||
BlockData result = BlockTypeUtils.createBlockDataFromString(blockData);
|
||||
return result != null ? result : Bukkit.getServer().createBlockData(blockData);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean isRolledBack() {
|
||||
return rolledBack == 1 || rolledBack == 3;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
|
||||
/**
|
||||
* Represents the result of a container action lookup with typed fields.
|
||||
*/
|
||||
public class ContainerResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int type;
|
||||
private final int data;
|
||||
private final int amount;
|
||||
private final byte[] metadata;
|
||||
private final int action;
|
||||
private final int rolledBack;
|
||||
|
||||
/**
|
||||
* Creates a new ContainerResult with the specified parameters.
|
||||
*
|
||||
* @param time The timestamp in seconds
|
||||
* @param username The username of the player who performed the action
|
||||
* @param world The world name where the action occurred
|
||||
* @param x The X coordinate
|
||||
* @param y The Y coordinate
|
||||
* @param z The Z coordinate
|
||||
* @param type The material type ID
|
||||
* @param data The data value
|
||||
* @param amount The amount of items
|
||||
* @param metadata The item metadata
|
||||
* @param action The action ID
|
||||
* @param rolledBack Whether the action has been rolled back
|
||||
*/
|
||||
public ContainerResult(long time, String username, String world, int x, int y, int z,
|
||||
int type, int data, int amount, byte[] metadata, int action, int rolledBack) {
|
||||
this.time = time;
|
||||
this.username = username != null ? username : "";
|
||||
this.world = world != null ? world : "";
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.amount = amount;
|
||||
this.metadata = metadata != null ? metadata.clone() : null;
|
||||
this.action = action;
|
||||
this.rolledBack = rolledBack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action ID.
|
||||
*
|
||||
* @return The action ID
|
||||
*/
|
||||
public int getActionId() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the action as a human-readable string.
|
||||
*
|
||||
* @return "remove", "add", or "unknown"
|
||||
*/
|
||||
public String getActionString() {
|
||||
return ItemTransactionActions.getActionString(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data value.
|
||||
*
|
||||
* @return The data value
|
||||
*/
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the amount of items.
|
||||
*
|
||||
* @return The amount
|
||||
*/
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username of the player who performed the action.
|
||||
*
|
||||
* @return The player username
|
||||
*/
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the timestamp in milliseconds.
|
||||
*
|
||||
* @return The timestamp in milliseconds
|
||||
*/
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the material type of the item.
|
||||
*
|
||||
* @return The Material, or null if unknown
|
||||
*/
|
||||
public Material getType() {
|
||||
return MaterialUtils.getType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the X coordinate.
|
||||
*
|
||||
* @return The X coordinate
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Y coordinate.
|
||||
*
|
||||
* @return The Y coordinate
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Z coordinate.
|
||||
*
|
||||
* @return The Z coordinate
|
||||
*/
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the item metadata.
|
||||
*
|
||||
* @return A copy of the metadata array, or null if no metadata
|
||||
*/
|
||||
public byte[] getMetadata() {
|
||||
return metadata != null ? metadata.clone() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this action has been rolled back.
|
||||
*
|
||||
* @return true if rolled back, false otherwise
|
||||
*/
|
||||
public boolean isRolledBack() {
|
||||
return rolledBack == 1 || rolledBack == 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the world name where the action occurred.
|
||||
*
|
||||
* @return The world name
|
||||
*/
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
/**
|
||||
* Common fields shared by typed CoreProtect lookup results.
|
||||
*/
|
||||
public interface CoreProtectResult {
|
||||
int getActionId();
|
||||
|
||||
String getActionString();
|
||||
|
||||
String getPlayer();
|
||||
|
||||
long getTimestamp();
|
||||
|
||||
int getX();
|
||||
|
||||
int getY();
|
||||
|
||||
int getZ();
|
||||
|
||||
String worldName();
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import net.coreprotect.model.item.InventorySources;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
|
||||
/**
|
||||
* Represents a normalized player inventory transaction.
|
||||
*/
|
||||
public class InventoryResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int type;
|
||||
private final int data;
|
||||
private final int amount;
|
||||
private final byte[] metadata;
|
||||
private final int actionId;
|
||||
private final int transactionActionId;
|
||||
private final int rolledBack;
|
||||
private final int sourceId;
|
||||
|
||||
public InventoryResult(long time, String username, String world, int x, int y, int z, int type, int data, int amount, byte[] metadata, int transactionActionId, int rolledBack, int sourceId) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.type = type;
|
||||
this.data = data;
|
||||
this.amount = amount;
|
||||
this.metadata = metadata != null ? metadata.clone() : null;
|
||||
this.transactionActionId = transactionActionId;
|
||||
this.rolledBack = rolledBack;
|
||||
this.sourceId = sourceId;
|
||||
this.actionId = ItemTransactionActions.getInventoryActionId(transactionActionId);
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return ItemTransactionActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public byte[] getMetadata() {
|
||||
return metadata != null ? metadata.clone() : null;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public int getSourceId() {
|
||||
return sourceId;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return InventorySources.getSourceString(sourceId);
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public int getTransactionActionId() {
|
||||
return transactionActionId;
|
||||
}
|
||||
|
||||
public String getTransactionActionString() {
|
||||
return ItemTransactionActions.getActionString(transactionActionId);
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
Material material = MaterialUtils.getType(type);
|
||||
if (sourceId == InventorySources.BLOCK) {
|
||||
return ItemUtils.itemFilter(material, true);
|
||||
}
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean isRolledBack() {
|
||||
return rolledBack == 2 || rolledBack == 3;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import org.bukkit.Material;
|
||||
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
|
||||
/**
|
||||
* Represents a logged world item transaction.
|
||||
*/
|
||||
public class ItemResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int type;
|
||||
private final int amount;
|
||||
private final byte[] metadata;
|
||||
private final int actionId;
|
||||
private final int rolledBack;
|
||||
|
||||
public ItemResult(long time, String username, String world, int x, int y, int z, int type, int amount, byte[] metadata, int actionId, int rolledBack) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
this.metadata = metadata != null ? metadata.clone() : null;
|
||||
this.actionId = actionId;
|
||||
this.rolledBack = rolledBack;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return ItemTransactionActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
public int getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public byte[] getMetadata() {
|
||||
return metadata != null ? metadata.clone() : null;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public Material getType() {
|
||||
return MaterialUtils.getType(type);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean isRolledBack() {
|
||||
return rolledBack == 1 || rolledBack == 3;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
|
||||
/**
|
||||
* Represents a logged player chat message or command.
|
||||
*/
|
||||
public class MessageResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final String message;
|
||||
private final int actionId;
|
||||
|
||||
public MessageResult(long time, String username, String world, int x, int y, int z, String message, int actionId) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.message = message;
|
||||
this.actionId = actionId;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return LookupActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,16 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import net.coreprotect.api.SessionLookup;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.StringUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
|
||||
public class ParseResult {
|
||||
public class ParseResult implements CoreProtectResult {
|
||||
private final String[] parse;
|
||||
|
||||
public ParseResult(String[] data) {
|
||||
@@ -26,31 +30,10 @@ public class ParseResult {
|
||||
public String getActionString() {
|
||||
int actionID = Integer.parseInt(parse[7]);
|
||||
if (parse.length < 13 && Integer.parseInt(parse[6]) == SessionLookup.ID) {
|
||||
switch (actionID) {
|
||||
case 0:
|
||||
return "logout";
|
||||
case 1:
|
||||
return "login";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
return SessionActions.getActionString(actionID);
|
||||
}
|
||||
|
||||
String result = "unknown";
|
||||
if (actionID == 0) {
|
||||
result = "break";
|
||||
}
|
||||
else if (actionID == 1) {
|
||||
result = "place";
|
||||
}
|
||||
else if (actionID == 2) {
|
||||
result = "click";
|
||||
}
|
||||
else if (actionID == 3) {
|
||||
result = "kill";
|
||||
}
|
||||
|
||||
return result;
|
||||
return LookupActions.getActionString(actionID);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -84,7 +67,12 @@ public class ParseResult {
|
||||
typeName = EntityUtils.getEntityType(type).name();
|
||||
}
|
||||
else {
|
||||
typeName = MaterialUtils.getType(type).name().toLowerCase(Locale.ROOT);
|
||||
Material material = MaterialUtils.getType(type);
|
||||
if (material == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
typeName = material.name().toLowerCase(Locale.ROOT);
|
||||
typeName = StringUtils.nameFilter(typeName, this.getData());
|
||||
}
|
||||
|
||||
@@ -98,9 +86,16 @@ public class ParseResult {
|
||||
|
||||
String blockData = parse[12];
|
||||
if (blockData == null || blockData.length() == 0) {
|
||||
return getType().createBlockData();
|
||||
Material type = getType();
|
||||
if (type != null) {
|
||||
return type.createBlockData();
|
||||
}
|
||||
|
||||
return BlockUtils.createBlockData(Integer.parseInt(parse[5]));
|
||||
}
|
||||
return Bukkit.getServer().createBlockData(blockData);
|
||||
|
||||
BlockData result = BlockTypeUtils.createBlockDataFromString(blockData);
|
||||
return result != null ? result : Bukkit.getServer().createBlockData(blockData);
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
|
||||
/**
|
||||
* Represents a logged player login or logout session event.
|
||||
*/
|
||||
public class SessionResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int actionId;
|
||||
|
||||
public SessionResult(long time, String username, String world, int x, int y, int z, int actionId) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.actionId = actionId;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return SessionActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import net.coreprotect.model.action.SignActions;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
|
||||
/**
|
||||
* Represents logged sign text.
|
||||
*/
|
||||
public class SignResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String username;
|
||||
private final String world;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int actionId;
|
||||
private final int color;
|
||||
private final int colorSecondary;
|
||||
private final int data;
|
||||
private final boolean waxed;
|
||||
private final boolean front;
|
||||
private final String[] lines;
|
||||
|
||||
public SignResult(long time, String username, String world, int x, int y, int z, int actionId, int color, int colorSecondary, int data, boolean waxed, boolean front, String[] lines) {
|
||||
this.time = time;
|
||||
this.username = username;
|
||||
this.world = world;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.actionId = actionId;
|
||||
this.color = color;
|
||||
this.colorSecondary = colorSecondary;
|
||||
this.data = data;
|
||||
this.waxed = waxed;
|
||||
this.front = front;
|
||||
this.lines = lines.clone();
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return actionId;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return SignActions.getActionString(actionId);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
public int getColorSecondary() {
|
||||
return colorSecondary;
|
||||
}
|
||||
|
||||
public int getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public String getLine(int line) {
|
||||
if (line < 0 || line >= lines.length) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return lines[line];
|
||||
}
|
||||
|
||||
public String[] getLines() {
|
||||
return lines.clone();
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
StringBuilder message = new StringBuilder();
|
||||
int startLine = front ? 0 : 4;
|
||||
int endLine = front ? 4 : 8;
|
||||
|
||||
for (int index = startLine; index < endLine; index++) {
|
||||
String line = lines[index];
|
||||
if (line != null && !line.isEmpty()) {
|
||||
message.append(line);
|
||||
if (!line.endsWith(" ")) {
|
||||
message.append(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
public boolean isBackGlowing() {
|
||||
return BlockUtils.isSideGlowing(false, data);
|
||||
}
|
||||
|
||||
public boolean isFront() {
|
||||
return front;
|
||||
}
|
||||
|
||||
public boolean isFrontGlowing() {
|
||||
return BlockUtils.isSideGlowing(true, data);
|
||||
}
|
||||
|
||||
public boolean isWaxed() {
|
||||
return waxed;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return world;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package net.coreprotect.api.result;
|
||||
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
|
||||
/**
|
||||
* Represents a logged username used by a player UUID.
|
||||
*/
|
||||
public class UsernameResult implements CoreProtectResult {
|
||||
private final long time;
|
||||
private final String uuid;
|
||||
private final String username;
|
||||
private final String player;
|
||||
|
||||
public UsernameResult(long time, String uuid, String username, String player) {
|
||||
this.time = time;
|
||||
this.uuid = uuid;
|
||||
this.username = username;
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public int getActionId() {
|
||||
return LookupActions.USERNAME;
|
||||
}
|
||||
|
||||
public String getActionString() {
|
||||
return LookupActions.getActionString(getActionId());
|
||||
}
|
||||
|
||||
public String getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
public long getTimestamp() {
|
||||
return time * 1000L;
|
||||
}
|
||||
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public int getX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getZ() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String worldName() {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,23 @@
|
||||
package net.coreprotect.bukkit;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -22,6 +28,10 @@ import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
@@ -56,6 +66,17 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
public static final int BUKKIT_V1_19 = 19;
|
||||
public static final int BUKKIT_V1_20 = 20;
|
||||
public static final int BUKKIT_V1_21 = 21;
|
||||
public static final int BUKKIT_V26_0 = 26000;
|
||||
public static final int BUKKIT_V26_1 = 26010;
|
||||
public static final int BUKKIT_V26_2 = 26020;
|
||||
|
||||
public static int getAdapterVersion(int major, int minor) {
|
||||
return getAdapterVersion(major, minor, 0);
|
||||
}
|
||||
|
||||
public static int getAdapterVersion(int major, int minor, int patch) {
|
||||
return major == 1 ? minor : (major * 1000) + (minor * 10) + patch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the appropriate Bukkit adapter based on the server version.
|
||||
@@ -82,9 +103,16 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
ADAPTER = new Bukkit_v1_20();
|
||||
break;
|
||||
case BUKKIT_V1_21:
|
||||
default:
|
||||
case BUKKIT_V26_0:
|
||||
case BUKKIT_V26_1:
|
||||
ADAPTER = new Bukkit_v1_21();
|
||||
break;
|
||||
case BUKKIT_V26_2:
|
||||
ADAPTER = new Bukkit_v26_2();
|
||||
break;
|
||||
default:
|
||||
ADAPTER = ConfigHandler.SERVER_VERSION >= BUKKIT_V26_2 ? new Bukkit_v26_2() : new Bukkit_v1_21();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +141,25 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMerchantRecipeMeta(MerchantRecipe recipe, List<Object> recipeData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMerchantRecipeMeta(MerchantRecipe recipe, List<?> recipeData) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshVillagerBrain(Villager villager) {
|
||||
try {
|
||||
Object handle = villager.getClass().getMethod("getHandle").invoke(villager);
|
||||
Object level = villager.getWorld().getClass().getMethod("getHandle").invoke(villager.getWorld());
|
||||
invokeSingleArgumentMethod(handle, "refreshBrain", level);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getWolfVariant(org.bukkit.entity.Wolf wolf, List<Object> info) {
|
||||
// Base implementation does nothing - Wolf variants only exist in 1.21+
|
||||
@@ -182,6 +229,24 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
private static void invokeSingleArgumentMethod(Object target, String methodName, Object argument) {
|
||||
if (target == null || argument == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Method method : target.getClass().getMethods()) {
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
if (method.getName().equals(methodName) && parameterTypes.length == 1 && parameterTypes[0].isInstance(argument)) {
|
||||
try {
|
||||
method.invoke(target, argument);
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- Block methods --------------------
|
||||
|
||||
@Override
|
||||
@@ -221,6 +286,21 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
return Material.AIR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBlockType(String key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData createBlockData(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData createBlockDataFromString(String blockData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvisible(Material material) {
|
||||
return BlockUtils.isAir(material);
|
||||
@@ -316,6 +396,17 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldLogExplosion(Event event){
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getExplodedBlock(BlockExplodeEvent event){
|
||||
// accoding to the Bukkit docs this will always return air
|
||||
return event.getBlock().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGlowing(Sign sign, boolean isFront, boolean isGlowing) {
|
||||
// Base implementation does nothing
|
||||
@@ -356,18 +447,58 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaintingArtKey(Painting painting) {
|
||||
try {
|
||||
return painting.getArt().name();
|
||||
}
|
||||
catch (IncompatibleClassChangeError e) {
|
||||
return painting.getArt().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Art getPaintingArt(String name) {
|
||||
if (name == null || name.isBlank()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return Art.getByName(name.toUpperCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCrafter(InventoryType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isBundle(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopperChest(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShelf(Material material){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Location> getShelfInteractionLocations(Block block, BlockFace blockFace) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Material> copperChestMaterials() {
|
||||
return EMPTY_SET;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Material> shelfMaterials() {
|
||||
return EMPTY_SET;
|
||||
}
|
||||
}
|
||||
@@ -4,9 +4,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
@@ -14,6 +17,10 @@ import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
@@ -74,6 +81,33 @@ public interface BukkitInterface {
|
||||
*/
|
||||
Material getBucketContents(Material material);
|
||||
|
||||
/**
|
||||
* Checks whether the runtime supports and contains a block type key.
|
||||
*
|
||||
* @param key
|
||||
* The namespaced block key
|
||||
* @return true if the block type exists, false otherwise
|
||||
*/
|
||||
boolean hasBlockType(String key);
|
||||
|
||||
/**
|
||||
* Creates default block data for a block type key.
|
||||
*
|
||||
* @param key
|
||||
* The namespaced block key
|
||||
* @return The block data, or null if unsupported/unavailable
|
||||
*/
|
||||
BlockData createBlockData(String key);
|
||||
|
||||
/**
|
||||
* Creates block data from a serialized block data string.
|
||||
*
|
||||
* @param blockData
|
||||
* The serialized block data
|
||||
* @return The block data, or null if unsupported/unavailable
|
||||
*/
|
||||
BlockData createBlockDataFromString(String blockData);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Material type checking methods
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -132,6 +166,19 @@ public interface BukkitInterface {
|
||||
*/
|
||||
boolean isChiseledBookshelf(Material material);
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a material is a shelf of any wood kind.
|
||||
*
|
||||
* @param material
|
||||
* The material to check
|
||||
* @return true if the material is a shelf, false otherwise
|
||||
*/
|
||||
boolean isShelf(Material material);
|
||||
|
||||
List<Location> getShelfInteractionLocations(Block block, BlockFace blockFace);
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a material is a bookshelf book.
|
||||
*
|
||||
@@ -141,6 +188,17 @@ public interface BukkitInterface {
|
||||
*/
|
||||
boolean isBookshelfBook(Material material);
|
||||
|
||||
|
||||
/**
|
||||
* Checks if a material is a bundle.
|
||||
*
|
||||
* @param material
|
||||
* The material to check
|
||||
* @return true if the material is a bundle, false otherwise
|
||||
*/
|
||||
boolean isBundle(Material material);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the seeds material for a plant material.
|
||||
*
|
||||
@@ -243,6 +301,12 @@ public interface BukkitInterface {
|
||||
*/
|
||||
boolean setEntityMeta(Entity entity, Object value, int count);
|
||||
|
||||
void addMerchantRecipeMeta(MerchantRecipe recipe, List<Object> recipeData);
|
||||
|
||||
void setMerchantRecipeMeta(MerchantRecipe recipe, List<?> recipeData);
|
||||
|
||||
void refreshVillagerBrain(Villager villager);
|
||||
|
||||
/**
|
||||
* Gets the wolf variant and adds it to the info list.
|
||||
* Only implemented in Minecraft 1.21+.
|
||||
@@ -402,6 +466,27 @@ public interface BukkitInterface {
|
||||
*/
|
||||
boolean isSignFront(SignChangeEvent event);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks whether an explosion event should be logged or not. (i.e. wind charge explosions)
|
||||
*
|
||||
* @param event
|
||||
* The explosion event (Block or Entity ExplodeEvent)
|
||||
* @return true if the explosion should affect blocks
|
||||
*/
|
||||
boolean shouldLogExplosion(Event event);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the material of the block that exploded
|
||||
*
|
||||
* @param event
|
||||
* The block explosion event
|
||||
* @return the material of the block that caused the explosion
|
||||
*/
|
||||
Material getExplodedBlock(BlockExplodeEvent event);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Registry methods
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -426,6 +511,10 @@ public interface BukkitInterface {
|
||||
*/
|
||||
Object getRegistryValue(String key, Object tClass);
|
||||
|
||||
String getPaintingArtKey(Painting painting);
|
||||
|
||||
Art getPaintingArt(String name);
|
||||
|
||||
/**
|
||||
* Parses a legacy material name.
|
||||
*
|
||||
@@ -441,4 +530,6 @@ public interface BukkitInterface {
|
||||
|
||||
Set<Material> copperChestMaterials();
|
||||
|
||||
Set<Material> shelfMaterials();
|
||||
|
||||
}
|
||||
@@ -152,9 +152,15 @@ public class Bukkit_v1_17 extends BukkitAdapter {
|
||||
return super.getItemMeta(itemMeta, list, metadata, slot);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBundle(Material material) {
|
||||
return material == Material.BUNDLE;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean setItemMeta(Material rowType, ItemStack itemstack, List<Map<String, Object>> map) {
|
||||
if (rowType == Material.BUNDLE) {
|
||||
if (BukkitAdapter.ADAPTER.isBundle(rowType)) {
|
||||
BundleMeta meta = (BundleMeta) itemstack.getItemMeta();
|
||||
for (Map<String, Object> itemData : map) {
|
||||
ItemStack itemStack = ItemUtils.unserializeItemStack(itemData);
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coreprotect.bukkit;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Color;
|
||||
@@ -13,9 +14,11 @@ import org.bukkit.block.ChiseledBookshelf;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.entity.Arrow;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.MerchantRecipe;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionType;
|
||||
@@ -297,4 +300,23 @@ public class Bukkit_v1_20 extends Bukkit_v1_19 {
|
||||
return super.getArrowMeta(arrow, itemStack);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Material getExplodedBlock(BlockExplodeEvent event){
|
||||
// accoding to the Bukkit docs this will always return air
|
||||
return event.getExplodedBlockState().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addMerchantRecipeMeta(MerchantRecipe recipe, List<Object> recipeData) {
|
||||
recipeData.add(recipe.getDemand());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMerchantRecipeMeta(MerchantRecipe recipe, List<?> recipeData) {
|
||||
if (recipeData.size() > 7 && recipeData.get(7) instanceof Number) {
|
||||
recipe.setDemand(((Number) recipeData.get(7)).intValue());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +1,36 @@
|
||||
package net.coreprotect.bukkit;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Art;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ExplosionResult;
|
||||
import org.bukkit.Keyed;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.Tag;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.BlockType;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Painting;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.block.BlockExplodeEvent;
|
||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
|
||||
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
|
||||
/**
|
||||
* Bukkit adapter implementation for Minecraft 1.21.
|
||||
@@ -23,9 +40,11 @@ import net.coreprotect.model.BlockGroup;
|
||||
* - Registry handling for named objects
|
||||
* - Updated interaction blocks
|
||||
*/
|
||||
public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
public class Bukkit_v1_21 extends Bukkit_v1_20 {
|
||||
|
||||
public static Set<Material> COPPER_CHESTS = new HashSet<>(Arrays.asList());
|
||||
public static Set<Material> SHELVES = new HashSet<>(Arrays.asList());
|
||||
public static Set<Material> BUNDLES = new HashSet<>(Arrays.asList());
|
||||
|
||||
/**
|
||||
* Initializes the Bukkit_v1_21 adapter with 1.21-specific block groups and mappings.
|
||||
@@ -34,9 +53,11 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
public Bukkit_v1_21() {
|
||||
initializeBlockGroups();
|
||||
initializeTrapdoorBlocks();
|
||||
initializeBundles();
|
||||
BlockGroup.INTERACT_BLOCKS.addAll(copperChestMaterials());
|
||||
BlockGroup.CONTAINERS.addAll(copperChestMaterials());
|
||||
BlockGroup.UPDATE_STATE.addAll(copperChestMaterials());
|
||||
BlockGroup.CONTAINERS.addAll(shelfMaterials());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +87,24 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the bundles group to enable the ability to roll back dyed bundles correctly.
|
||||
* It needs to check whether dyed bundles exist because they were added in 1.21.2.
|
||||
*/
|
||||
public void initializeBundles(){
|
||||
if (BUNDLES.isEmpty()) {
|
||||
Tag<Material> bundleTag = getMaterialTag(Tag.REGISTRY_ITEMS, "bundles");
|
||||
if (bundleTag != null) {
|
||||
BUNDLES.addAll(bundleTag.getValues());
|
||||
}
|
||||
|
||||
if (BUNDLES.isEmpty()) {
|
||||
addMaterialsEndingWith(BUNDLES, "_BUNDLE");
|
||||
}
|
||||
BUNDLES.add(Material.BUNDLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to add a block to a block group if it's not already present.
|
||||
*
|
||||
@@ -80,6 +119,43 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasBlockType(String key) {
|
||||
return getBlockType(key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData createBlockData(String key) {
|
||||
try {
|
||||
BlockType blockType = getBlockType(key);
|
||||
return blockType == null ? null : blockType.createBlockData();
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockData createBlockDataFromString(String blockData) {
|
||||
try {
|
||||
BlockType blockType = getBlockType(BlockTypeUtils.getBlockDataKey(blockData));
|
||||
if (blockType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String states = BlockTypeUtils.getBlockDataStates(blockData);
|
||||
return states == null ? blockType.createBlockData() : blockType.createBlockData(states);
|
||||
}
|
||||
catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private BlockType getBlockType(String key) {
|
||||
NamespacedKey namespacedKey = NamespacedKey.fromString(BlockTypeUtils.normalizeKey(key));
|
||||
return namespacedKey == null ? null : Registry.BLOCK.get(namespacedKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EntityType corresponding to a Material.
|
||||
* Maps Material to its equivalent EntityType for entity handling.
|
||||
@@ -111,6 +187,7 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
return ((Keyed) value).getKey().toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a registry value from a key string and class.
|
||||
* Used for deserializing registry objects.
|
||||
@@ -129,6 +206,51 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
return Bukkit.getRegistry((Class) tClass).get(namespacedKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPaintingArtKey(Painting painting) {
|
||||
try {
|
||||
NamespacedKey key = Registry.ART.getKey(painting.getArt());
|
||||
if (key != null) {
|
||||
return normalizePaintingArtKey(key.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
}
|
||||
|
||||
return normalizePaintingArtKey(super.getPaintingArtKey(painting));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Art getPaintingArt(String name) {
|
||||
NamespacedKey key = NamespacedKey.fromString(normalizePaintingArtLookupKey(name));
|
||||
if (key != null) {
|
||||
Art art = Registry.ART.get(key);
|
||||
if (art != null) {
|
||||
return art;
|
||||
}
|
||||
}
|
||||
|
||||
return super.getPaintingArt(name);
|
||||
}
|
||||
|
||||
private String normalizePaintingArtKey(String name) {
|
||||
if (name == null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
String normalized = name.toLowerCase(Locale.ROOT).trim();
|
||||
if (normalized.startsWith("minecraft:")) {
|
||||
return normalized.substring("minecraft:".length());
|
||||
}
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
private String normalizePaintingArtLookupKey(String name) {
|
||||
String normalized = normalizePaintingArtKey(name);
|
||||
return normalized.contains(":") ? normalized : "minecraft:" + normalized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the wolf variant and adds it to the info list.
|
||||
* This functionality is specific to Minecraft 1.21+.
|
||||
@@ -177,6 +299,17 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isShelf(Material material) {
|
||||
return SHELVES.contains(material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBundle(Material material) {
|
||||
return BUNDLES.contains(material);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Set<Material> copperChestMaterials() {
|
||||
if (COPPER_CHESTS.isEmpty()) {
|
||||
@@ -198,4 +331,117 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
|
||||
return COPPER_CHESTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Material> shelfMaterials() {
|
||||
if (SHELVES.isEmpty()) {
|
||||
Tag<Material> shelfTag = getMaterialTag(Tag.REGISTRY_BLOCKS, "wooden_shelves");
|
||||
if (shelfTag != null) {
|
||||
SHELVES.addAll(shelfTag.getValues());
|
||||
}
|
||||
|
||||
if (SHELVES.isEmpty()) {
|
||||
addMaterialsEndingWith(SHELVES, "_SHELF");
|
||||
}
|
||||
}
|
||||
|
||||
return SHELVES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Location> getShelfInteractionLocations(Block block, BlockFace blockFace) {
|
||||
List<Location> locations = new ArrayList<>();
|
||||
BlockData blockData = block.getBlockData();
|
||||
BlockFace facing = getShelfFacing(blockData);
|
||||
if (facing == null) {
|
||||
locations.add(block.getLocation());
|
||||
return locations;
|
||||
}
|
||||
|
||||
if (blockFace != facing) {
|
||||
return locations;
|
||||
}
|
||||
|
||||
String sideChain = getShelfSideChain(blockData);
|
||||
if ("UNCONNECTED".equals(sideChain)) {
|
||||
locations.add(block.getLocation());
|
||||
return locations;
|
||||
}
|
||||
|
||||
Block center = block;
|
||||
int directionX = facing.getModX();
|
||||
int directionZ = facing.getModZ();
|
||||
if ("LEFT".equals(sideChain)) {
|
||||
center = center.getRelative(directionZ, 0, -directionX);
|
||||
}
|
||||
else if ("RIGHT".equals(sideChain)) {
|
||||
center = center.getRelative(-directionZ, 0, directionX);
|
||||
}
|
||||
|
||||
String centerSideChain = getShelfSideChain(center.getBlockData());
|
||||
if (centerSideChain == null) {
|
||||
locations.add(block.getLocation());
|
||||
return locations;
|
||||
}
|
||||
|
||||
locations.add(center.getLocation());
|
||||
if (!"CENTER".equals(centerSideChain)) {
|
||||
locations.add(block.getLocation());
|
||||
return locations;
|
||||
}
|
||||
|
||||
locations.add(center.getRelative(-directionZ, 0, directionX).getLocation());
|
||||
locations.add(center.getRelative(directionZ, 0, -directionX).getLocation());
|
||||
return locations;
|
||||
}
|
||||
|
||||
private static Tag<Material> getMaterialTag(String registry, String key) {
|
||||
return Bukkit.getTag(registry, NamespacedKey.minecraft(key), Material.class);
|
||||
}
|
||||
|
||||
private static void addMaterialsEndingWith(Set<Material> materials, String suffix) {
|
||||
for (Material material : Material.values()) {
|
||||
if (material.name().endsWith(suffix)) {
|
||||
materials.add(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static BlockFace getShelfFacing(BlockData blockData) {
|
||||
Object facing = invokeNoArgumentMethod(blockData, "getFacing");
|
||||
return facing instanceof BlockFace ? (BlockFace) facing : null;
|
||||
}
|
||||
|
||||
private static String getShelfSideChain(BlockData blockData) {
|
||||
Object sideChain = invokeNoArgumentMethod(blockData, "getSideChain");
|
||||
return sideChain == null ? null : sideChain.toString();
|
||||
}
|
||||
|
||||
private static Object invokeNoArgumentMethod(Object target, String methodName) {
|
||||
if (target == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
Method method = target.getClass().getMethod(methodName);
|
||||
return method.invoke(target);
|
||||
}
|
||||
catch (ReflectiveOperationException | LinkageError e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldLogExplosion(Event event){
|
||||
ExplosionResult result = null;
|
||||
|
||||
if (event instanceof EntityExplodeEvent){
|
||||
result = ((EntityExplodeEvent)event).getExplosionResult();
|
||||
} else if (event instanceof BlockExplodeEvent){
|
||||
result = ((BlockExplodeEvent)event).getExplosionResult();
|
||||
}
|
||||
return !(result == ExplosionResult.KEEP ||
|
||||
result == ExplosionResult.TRIGGER_BLOCK
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package net.coreprotect.bukkit;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Speleothem;
|
||||
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
|
||||
/**
|
||||
* Bukkit adapter implementation for Minecraft 26.2.
|
||||
*/
|
||||
public class Bukkit_v26_2 extends Bukkit_v1_21 {
|
||||
|
||||
public Bukkit_v26_2() {
|
||||
initializeBlockGroups();
|
||||
}
|
||||
|
||||
private void initializeBlockGroups() {
|
||||
BlockGroup.TRACK_TOP_BOTTOM.add(Material.SULFUR_SPIKE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAttached(Block block, Block scanBlock, BlockData blockData, int scanMin) {
|
||||
if (blockData instanceof Speleothem) {
|
||||
Speleothem speleothem = (Speleothem) blockData;
|
||||
BlockFace blockFace = speleothem.getVerticalDirection();
|
||||
return scanBlock.getRelative(blockFace.getOppositeFace()).getLocation().equals(block.getLocation());
|
||||
}
|
||||
|
||||
return super.isAttached(block, scanBlock, blockData, scanMin);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ApplyCommand {
|
||||
protected static void runCommand(CommandSender user, Command command, boolean permission, String[] args) {
|
||||
@@ -41,7 +42,7 @@ public class ApplyCommand {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class CancelCommand {
|
||||
protected static void runCommand(CommandSender user, Command command, boolean permission, String[] args) {
|
||||
@@ -41,7 +42,7 @@ public class CancelCommand {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.Extensions;
|
||||
import net.coreprotect.utility.VersionUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class CommandHandler implements CommandExecutor {
|
||||
private static CommandHandler instance;
|
||||
@@ -75,6 +76,9 @@ public class CommandHandler implements CommandExecutor {
|
||||
else if (user.hasPermission("coreprotect.networking") && corecommand.equals("network-debug")) {
|
||||
permission = true;
|
||||
}
|
||||
else if (user.hasPermission("coreprotect.give") && corecommand.equals("give")) {
|
||||
permission = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (corecommand.equals("rollback") || corecommand.equals("restore") || corecommand.equals("rb") || corecommand.equals("rs") || corecommand.equals("ro") || corecommand.equals("re")) {
|
||||
@@ -119,6 +123,9 @@ public class CommandHandler implements CommandExecutor {
|
||||
else if (corecommand.equals("network-debug")) {
|
||||
NetworkDebugCommand.runCommand(user, permission, argumentArray);
|
||||
}
|
||||
else if (corecommand.equals("give")) {
|
||||
GiveCommand.runCommand(user, command, permission, argumentArray);
|
||||
}
|
||||
else if (corecommand.equals("migrate-db")) {
|
||||
if (!VersionUtils.validDonationKey()) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.DONATION_KEY_REQUIRED));
|
||||
@@ -138,25 +145,26 @@ public class CommandHandler implements CommandExecutor {
|
||||
if (user.isOp() && versionAlert.get(user.getName()) == null) {
|
||||
String latestVersion = NetworkHandler.latestVersion();
|
||||
String latestEdgeVersion = NetworkHandler.latestEdgeVersion();
|
||||
if (latestVersion != null || latestEdgeVersion != null) {
|
||||
boolean communityEdition = VersionUtils.isCommunityEdition();
|
||||
if (latestVersion != null || (latestEdgeVersion != null && !communityEdition)) {
|
||||
versionAlert.put(user.getName(), true);
|
||||
class updateAlert implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
Chat.sendMessage(user, Color.WHITE + "----- " + Color.DARK_AQUA + Phrase.build(Phrase.UPDATE_HEADER, "CoreProtect" + (VersionUtils.isCommunityEdition() ? " " + ConfigHandler.COMMUNITY_EDITION : "")) + Color.WHITE + " -----");
|
||||
Chat.sendMessage(user, Color.WHITE + "----- " + Color.DARK_AQUA + Phrase.build(Phrase.UPDATE_HEADER, "CoreProtect" + (communityEdition ? " " + ConfigHandler.COMMUNITY_EDITION : "")) + Color.WHITE + " -----");
|
||||
if (latestVersion != null) {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + Phrase.build(Phrase.UPDATE_NOTICE, Color.WHITE, "CoreProtect CE v" + latestVersion));
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + Phrase.build(Phrase.LINK_DOWNLOAD, Color.WHITE, "www.coreprotect.net/download/"));
|
||||
}
|
||||
else if (!VersionUtils.isCommunityEdition()) {
|
||||
else {
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + Phrase.build(Phrase.UPDATE_NOTICE, Color.WHITE, "CoreProtect v" + latestEdgeVersion));
|
||||
Chat.sendMessage(user, Color.DARK_AQUA + Phrase.build(Phrase.LINK_DOWNLOAD, Color.WHITE, "www.coreprotect.net/latest/"));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import net.coreprotect.command.parser.*;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import net.coreprotect.command.parser.ActionParser;
|
||||
import net.coreprotect.command.parser.LocationParser;
|
||||
import net.coreprotect.command.parser.MaterialParser;
|
||||
import net.coreprotect.command.parser.TimeParser;
|
||||
import net.coreprotect.command.parser.UserParser;
|
||||
import net.coreprotect.command.parser.WorldParser;
|
||||
|
||||
/**
|
||||
* Main parser class for CoreProtect commands.
|
||||
* Delegates to specialized parser classes for specific functionality.
|
||||
@@ -326,4 +320,7 @@ public class CommandParser {
|
||||
return input.stripTrailingZeros().toPlainString();
|
||||
}
|
||||
|
||||
protected static Integer parseGivableItemId(String[] inputArguments) {
|
||||
return GivableItemIdParser.parseGivableItemId(inputArguments);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.coreprotect.command;
|
||||
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.ChatMessage;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
public class GiveCommand {
|
||||
public static void runCommand(CommandSender sender, Command command, boolean permission, String[] args) {
|
||||
if (!permission) {
|
||||
Chat.sendMessage(sender, new ChatMessage(Phrase.build(Phrase.NO_PERMISSION)).build());
|
||||
return;
|
||||
}
|
||||
|
||||
Integer itemId = CommandParser.parseGivableItemId(args);
|
||||
if (itemId == null) {
|
||||
Chat.sendMessage(sender, new ChatMessage(Phrase.build(Phrase.MISSING_PARAMETERS, Color.WHITE, "/" + command.getName() + " give <itemId>")).build());
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStack item = ItemUtils.getGivableItem(itemId);
|
||||
if (item == null) {
|
||||
Chat.sendMessage(sender, new ChatMessage(Phrase.build(Phrase.INVALID_ITEM_ID)).build());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
Chat.sendMessage(sender, new ChatMessage(Phrase.build(Phrase.ACTION_NOT_SUPPORTED)).build());
|
||||
return;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
player.getInventory().addItem(item);
|
||||
}
|
||||
}
|
||||
@@ -67,8 +67,11 @@ public class HelpCommand {
|
||||
Chat.sendMessage(player, Color.GREY + Color.ITALIC + Phrase.build(Phrase.HELP_PARAMETER, "/co help params"));
|
||||
}
|
||||
else if (helpcommand.equals("purge") || helpcommand.equals("purges")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "/co purge t:<time> " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_PURGE_1));
|
||||
Chat.sendMessage(player, Color.GREY + Color.ITALIC + "" + Phrase.build(Phrase.HELP_PURGE_2, "/co purge t:30d"));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "/co purge " + Color.GREY + "<params> " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_PURGE_1));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "| " + Color.GREY + "t:<time> " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_PURGE_3));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "| " + Color.GREY + "r:<world> " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_PURGE_4));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "| " + Color.GREY + "i:<include> " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_PURGE_5));
|
||||
Chat.sendMessage(player, Color.GREY + Color.ITALIC + Phrase.build(Phrase.HELP_PURGE_2, "/co purge t:30d"));
|
||||
}
|
||||
else if (helpcommand.equals("reload")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "/co reload " + Color.WHITE + "- " + Phrase.build(Phrase.HELP_RELOAD_COMMAND));
|
||||
|
||||
@@ -22,10 +22,12 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.ChatMessage;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class LookupCommand {
|
||||
public static void runCommand(CommandSender player, Command command, boolean permission, String[] args) {
|
||||
@@ -67,15 +69,15 @@ public class LookupCommand {
|
||||
boolean hasBlock = false;
|
||||
boolean hasEntity = false;
|
||||
for (Object arg : argBlocks) {
|
||||
if (arg instanceof Material) {
|
||||
if (arg instanceof Material || arg instanceof String) {
|
||||
hasBlock = true;
|
||||
}
|
||||
else if (arg instanceof EntityType) {
|
||||
hasEntity = true;
|
||||
if (argAction.size() == 0) {
|
||||
argAction.add(3);
|
||||
argAction.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
else if (!argAction.contains(3)) {
|
||||
else if (!argAction.contains(LookupActions.ENTITY_KILL)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_INCLUDE_COMBO));
|
||||
return;
|
||||
}
|
||||
@@ -84,15 +86,15 @@ public class LookupCommand {
|
||||
|
||||
/* check for invalid block/entity combinations (exclude) */
|
||||
for (Object arg : argExclude.keySet()) {
|
||||
if (arg instanceof Material) {
|
||||
if (arg instanceof Material || arg instanceof String) {
|
||||
hasBlock = true;
|
||||
}
|
||||
else if (arg instanceof EntityType) {
|
||||
hasEntity = true;
|
||||
if (argAction.size() == 0) {
|
||||
argAction.add(3);
|
||||
argAction.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
else if (!argAction.contains(3)) {
|
||||
else if (!argAction.contains(LookupActions.ENTITY_KILL)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_INCLUDE_COMBO));
|
||||
return;
|
||||
}
|
||||
@@ -143,7 +145,7 @@ public class LookupCommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (argAction.contains(6) || argAction.contains(7) || argAction.contains(8) || argAction.contains(9) || argAction.contains(10)) {
|
||||
if (argAction.contains(LookupActions.CHAT) || argAction.contains(LookupActions.COMMAND) || argAction.contains(LookupActions.SESSION) || argAction.contains(LookupActions.USERNAME) || argAction.contains(LookupActions.SIGN)) {
|
||||
pageLookup = true;
|
||||
}
|
||||
|
||||
@@ -189,53 +191,53 @@ public class LookupCommand {
|
||||
allPermission = true;
|
||||
}
|
||||
if (!allPermission) {
|
||||
if (!pageLookup && (argAction.size() == 0 || (argAction.size() == 1 && (argAction.contains(0) || argAction.contains(1)))) && !player.hasPermission("coreprotect.lookup.block")) {
|
||||
if (!pageLookup && (argAction.size() == 0 || (argAction.size() == 1 && (argAction.contains(LookupActions.BLOCK_BREAK) || argAction.contains(LookupActions.BLOCK_PLACE)))) && !player.hasPermission("coreprotect.lookup.block")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(2) && !player.hasPermission("coreprotect.lookup.click")) {
|
||||
if (argAction.contains(LookupActions.INTERACTION) && !player.hasPermission("coreprotect.lookup.click")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(3) && !player.hasPermission("coreprotect.lookup.kill")) {
|
||||
if (argAction.contains(LookupActions.ENTITY_KILL) && !player.hasPermission("coreprotect.lookup.kill")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(4) && !argAction.contains(11) && !player.hasPermission("coreprotect.lookup.container")) {
|
||||
if (argAction.contains(LookupActions.CONTAINER) && !argAction.contains(LookupActions.ITEM) && !player.hasPermission("coreprotect.lookup.container")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(6) && !player.hasPermission("coreprotect.lookup.chat")) {
|
||||
if (argAction.contains(LookupActions.CHAT) && !player.hasPermission("coreprotect.lookup.chat")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(7) && !player.hasPermission("coreprotect.lookup.command")) {
|
||||
if (argAction.contains(LookupActions.COMMAND) && !player.hasPermission("coreprotect.lookup.command")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(8) && !player.hasPermission("coreprotect.lookup.session")) {
|
||||
if (argAction.contains(LookupActions.SESSION) && !player.hasPermission("coreprotect.lookup.session")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(9) && !player.hasPermission("coreprotect.lookup.username")) {
|
||||
if (argAction.contains(LookupActions.USERNAME) && !player.hasPermission("coreprotect.lookup.username")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(10) && !player.hasPermission("coreprotect.lookup.sign")) {
|
||||
if (argAction.contains(LookupActions.SIGN) && !player.hasPermission("coreprotect.lookup.sign")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(11) && !argAction.contains(4) && !player.hasPermission("coreprotect.lookup.item")) {
|
||||
if (argAction.contains(LookupActions.ITEM) && !argAction.contains(LookupActions.CONTAINER) && !player.hasPermission("coreprotect.lookup.item")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
if (argAction.contains(4) && argAction.contains(11) && !player.hasPermission("coreprotect.lookup.inventory")) {
|
||||
if (LookupActions.isInventoryLookup(argAction) && !player.hasPermission("coreprotect.lookup.inventory")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.NO_PERMISSION));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (argAction.contains(6) || argAction.contains(7) || argAction.contains(8) || argAction.contains(9) || argAction.contains(10)) {
|
||||
if (argAction.contains(9) && (argRadius != null || argWid > 0 || worldedit)) {
|
||||
if (argAction.contains(LookupActions.CHAT) || argAction.contains(LookupActions.COMMAND) || argAction.contains(LookupActions.SESSION) || argAction.contains(LookupActions.USERNAME) || argAction.contains(LookupActions.SIGN)) {
|
||||
if (argAction.contains(LookupActions.USERNAME) && (argRadius != null || argWid > 0 || worldedit)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INCOMPATIBLE_ACTION, "r:"));
|
||||
return;
|
||||
}
|
||||
@@ -254,7 +256,7 @@ public class LookupCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
if (argAction.contains(4) && argAction.contains(11)) { // a:inventory
|
||||
if (LookupActions.isInventoryLookup(argAction)) {
|
||||
if (argUsers.size() == 0) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_ACTION_USER));
|
||||
return;
|
||||
@@ -404,7 +406,7 @@ public class LookupCommand {
|
||||
boolean defaultRe = true;
|
||||
int pa = 1;
|
||||
int re = 4;
|
||||
if (argAction.contains(6) || argAction.contains(7) || argAction.contains(9) || (argAction.contains(4) && argAction.contains(11))) {
|
||||
if (argAction.contains(LookupActions.CHAT) || argAction.contains(LookupActions.COMMAND) || argAction.contains(LookupActions.USERNAME) || LookupActions.isInventoryLookup(argAction)) {
|
||||
re = 7;
|
||||
}
|
||||
if (parseRows > 0) {
|
||||
@@ -480,7 +482,7 @@ public class LookupCommand {
|
||||
}
|
||||
c++;
|
||||
|
||||
if (argAction.contains(4) && argAction.contains(11)) {
|
||||
if (LookupActions.isInventoryLookup(argAction)) {
|
||||
if (ruser.startsWith("#")) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_USERNAME, ruser));
|
||||
return;
|
||||
@@ -531,13 +533,13 @@ public class LookupCommand {
|
||||
}
|
||||
}
|
||||
|
||||
if (rollbackusers.size() == 1 && rollbackusers.contains("#global") && argAction.contains(9)) {
|
||||
if (rollbackusers.size() == 1 && rollbackusers.contains("#global") && argAction.contains(LookupActions.USERNAME)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_PARAMETERS, "/co l a:username u:<user>"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (rollbackusers.contains("#container")) {
|
||||
if (argAction.contains(6) || argAction.contains(7) || argAction.contains(8) || argAction.contains(9) || argAction.contains(10) || argAction.contains(11)) {
|
||||
if (argAction.contains(LookupActions.CHAT) || argAction.contains(LookupActions.COMMAND) || argAction.contains(LookupActions.SESSION) || argAction.contains(LookupActions.USERNAME) || argAction.contains(LookupActions.SIGN) || argAction.contains(LookupActions.ITEM)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_USERNAME, "#container"));
|
||||
return;
|
||||
}
|
||||
@@ -600,7 +602,7 @@ public class LookupCommand {
|
||||
thread.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -7,6 +7,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.listener.channel.PluginChannelListener;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class NetworkDebugCommand {
|
||||
protected static void runCommand(CommandSender player, boolean permission, String[] args) {
|
||||
@@ -19,7 +20,7 @@ public class NetworkDebugCommand {
|
||||
PluginChannelListener.getInstance().sendTest(player, args.length == 2 ? args[1] : "");
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,9 +31,55 @@ import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.VersionUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class PurgeCommand extends Consumer {
|
||||
|
||||
public static final List<String> PURGE_TABLES = Arrays.asList("sign", "container", "item", "skull", "session", "chat", "command", "entity", "block");
|
||||
|
||||
private static String findUnsupportedPurgeArgument(String[] args) {
|
||||
boolean includeContinuation = false;
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
String token = args[i].trim();
|
||||
if (token.length() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String argument = token.toLowerCase(Locale.ROOT);
|
||||
argument = argument.replaceAll("\\\\", "");
|
||||
argument = argument.replaceAll("'", "");
|
||||
|
||||
if (includeContinuation) {
|
||||
includeContinuation = argument.endsWith(",");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.equals("#optimize")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("i:") || argument.startsWith("include:") || argument.startsWith("item:") || argument.startsWith("items:") || argument.startsWith("b:") || argument.startsWith("block:") || argument.startsWith("blocks:")) {
|
||||
String includeValues = argument.replaceAll("include:", "").replaceAll("i:", "").replaceAll("items:", "").replaceAll("item:", "").replaceAll("blocks:", "").replaceAll("block:", "").replaceAll("b:", "");
|
||||
includeContinuation = includeValues.length() == 0 || includeValues.endsWith(",");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("t:") || argument.startsWith("time:")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.startsWith("r:") || argument.startsWith("radius:")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argument.contains(":")) {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void runCommand(final CommandSender player, boolean permission, String[] args) {
|
||||
int resultc = args.length;
|
||||
Location location = CommandParser.parseLocation(player, args);
|
||||
@@ -68,6 +114,12 @@ public class PurgeCommand extends Consumer {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_PARAMETERS, "/co purge t:<time>"));
|
||||
return;
|
||||
}
|
||||
String unsupportedArgument = findUnsupportedPurgeArgument(args);
|
||||
if (unsupportedArgument != null) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_PARAMETER, unsupportedArgument));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_PARAMETERS, "/co help purge"));
|
||||
return;
|
||||
}
|
||||
if (endTime <= 0) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_PARAMETERS, "/co purge t:<time>"));
|
||||
return;
|
||||
@@ -143,6 +195,18 @@ public class PurgeCommand extends Consumer {
|
||||
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
|
||||
entity = true;
|
||||
}
|
||||
else if (restrictTarget instanceof String) {
|
||||
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
|
||||
if (includeListMaterial.length() == 0) {
|
||||
includeListMaterial = includeListMaterial.append(blockId);
|
||||
}
|
||||
else {
|
||||
includeListMaterial.append(",").append(blockId);
|
||||
}
|
||||
|
||||
targetName = ((String) restrictTarget).toLowerCase(Locale.ROOT);
|
||||
hasBlock = true;
|
||||
}
|
||||
|
||||
if (restrictCount == 0) {
|
||||
restrict = restrict.append("" + targetName + "");
|
||||
@@ -253,14 +317,13 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
Database.createDatabaseTables(purgePrefix, false, null, Config.getGlobal().MYSQL, true);
|
||||
}
|
||||
|
||||
List<String> purgeTables = Arrays.asList("sign", "container", "item", "skull", "session", "chat", "command", "entity", "block");
|
||||
List<String> worldTables = Arrays.asList("sign", "container", "item", "session", "chat", "command", "block");
|
||||
List<String> restrictTables = Arrays.asList("block");
|
||||
List<String> excludeTables = Arrays.asList("database_lock"); // don't insert data into these tables
|
||||
@@ -289,7 +352,7 @@ public class PurgeCommand extends Consumer {
|
||||
try {
|
||||
boolean purge = true;
|
||||
String timeLimit = "";
|
||||
if (purgeTables.contains(table)) {
|
||||
if (PURGE_TABLES.contains(table)) {
|
||||
String blockRestriction = "(";
|
||||
if (hasBlockRestriction && restrictTables.contains(table)) {
|
||||
blockRestriction = "type NOT IN(" + includeBlockFinal + ") OR (type IN(" + includeBlockFinal + ") AND ";
|
||||
@@ -312,7 +375,7 @@ public class PurgeCommand extends Consumer {
|
||||
}
|
||||
catch (Exception e) {
|
||||
error = true;
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -327,7 +390,7 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -337,7 +400,7 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -348,13 +411,13 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
abort = true;
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
boolean purge = purgeTables.contains(table);
|
||||
boolean purge = PURGE_TABLES.contains(table);
|
||||
|
||||
String blockRestriction = "";
|
||||
if (hasBlockRestriction && restrictTables.contains(table)) {
|
||||
@@ -380,11 +443,11 @@ public class PurgeCommand extends Consumer {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (purgeTables.contains(table)) {
|
||||
if (PURGE_TABLES.contains(table)) {
|
||||
int oldCount = 0;
|
||||
try {
|
||||
query = "SELECT COUNT(*) as count FROM " + ConfigHandler.prefix + table + " LIMIT 0, 1";
|
||||
@@ -397,7 +460,7 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
int new_count = 0;
|
||||
@@ -412,7 +475,7 @@ public class PurgeCommand extends Consumer {
|
||||
preparedStmt.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
removed = removed + (oldCount - new_count);
|
||||
@@ -421,7 +484,7 @@ public class PurgeCommand extends Consumer {
|
||||
|
||||
if (Config.getGlobal().MYSQL) {
|
||||
try {
|
||||
boolean purge = purgeTables.contains(table);
|
||||
boolean purge = PURGE_TABLES.contains(table);
|
||||
|
||||
String blockRestriction = "";
|
||||
if (hasBlockRestriction && restrictTables.contains(table)) {
|
||||
@@ -453,7 +516,7 @@ public class PurgeCommand extends Consumer {
|
||||
return;
|
||||
}
|
||||
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,7 +556,7 @@ public class PurgeCommand extends Consumer {
|
||||
}
|
||||
catch (Exception e) {
|
||||
Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_FAILED));
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
Consumer.isPaused = false;
|
||||
|
||||
@@ -8,6 +8,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.thread.NetworkHandler;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ReloadCommand {
|
||||
protected static void runCommand(final CommandSender player, boolean permission, String[] args) {
|
||||
@@ -48,7 +49,7 @@ public class ReloadCommand {
|
||||
networkHandler.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
Consumer.isPaused = false;
|
||||
|
||||
@@ -27,9 +27,11 @@ 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.model.action.LookupActions;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class RollbackRestoreCommand {
|
||||
public static void runCommand(CommandSender player, Command command, boolean permission, String[] args, Location argLocation, long forceStart, long forceEnd) {
|
||||
@@ -61,15 +63,15 @@ public class RollbackRestoreCommand {
|
||||
boolean hasBlock = false;
|
||||
boolean hasEntity = false;
|
||||
for (Object arg : argBlocks) {
|
||||
if (arg instanceof Material) {
|
||||
if (arg instanceof Material || arg instanceof String) {
|
||||
hasBlock = true;
|
||||
}
|
||||
else if (arg instanceof EntityType) {
|
||||
hasEntity = true;
|
||||
if (argAction.size() == 0) {
|
||||
argAction.add(3);
|
||||
argAction.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
else if (!argAction.contains(3)) {
|
||||
else if (!argAction.contains(LookupActions.ENTITY_KILL)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_INCLUDE_COMBO));
|
||||
return;
|
||||
}
|
||||
@@ -78,15 +80,15 @@ public class RollbackRestoreCommand {
|
||||
|
||||
/* check for invalid block/entity combinations (exclude) */
|
||||
for (Object arg : argExclude.keySet()) {
|
||||
if (arg instanceof Material) {
|
||||
if (arg instanceof Material || arg instanceof String) {
|
||||
hasBlock = true;
|
||||
}
|
||||
else if (arg instanceof EntityType) {
|
||||
hasEntity = true;
|
||||
if (argAction.size() == 0) {
|
||||
argAction.add(3);
|
||||
argAction.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
else if (!argAction.contains(3)) {
|
||||
else if (!argAction.contains(LookupActions.ENTITY_KILL)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_INCLUDE_COMBO));
|
||||
return;
|
||||
}
|
||||
@@ -154,7 +156,7 @@ public class RollbackRestoreCommand {
|
||||
final int finalAction = a;
|
||||
|
||||
int DEFAULT_RADIUS = Config.getGlobal().DEFAULT_RADIUS;
|
||||
if ((player instanceof Player || player instanceof BlockCommandSender) && argRadius == null && DEFAULT_RADIUS > 0 && !forceglobal && !argAction.contains(11)) {
|
||||
if ((player instanceof Player || player instanceof BlockCommandSender) && argRadius == null && DEFAULT_RADIUS > 0 && !forceglobal && !argAction.contains(LookupActions.ITEM)) {
|
||||
Location location = lo;
|
||||
int xmin = location.getBlockX() - DEFAULT_RADIUS;
|
||||
int xmax = location.getBlockX() + DEFAULT_RADIUS;
|
||||
@@ -181,7 +183,7 @@ public class RollbackRestoreCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
if (argAction.contains(4) && argAction.contains(11)) { // a:inventory
|
||||
if (LookupActions.isInventoryLookup(argAction)) {
|
||||
if (argUsers.size() == 0) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_ACTION_USER));
|
||||
return;
|
||||
@@ -192,7 +194,7 @@ public class RollbackRestoreCommand {
|
||||
argExclude.put(Material.FARMLAND, false);
|
||||
argExcludeUsers.add("#hopper");
|
||||
}
|
||||
else if (!argAction.contains(4) && Config.getGlobal().EXCLUDE_TNT && !argExclude.containsKey(Material.TNT) && !argBlocks.contains(Material.TNT)) {
|
||||
else if (!argAction.contains(LookupActions.CONTAINER) && Config.getGlobal().EXCLUDE_TNT && !argExclude.containsKey(Material.TNT) && !argBlocks.contains(Material.TNT)) {
|
||||
argExclude.put(Material.TNT, true);
|
||||
}
|
||||
|
||||
@@ -207,17 +209,17 @@ public class RollbackRestoreCommand {
|
||||
}
|
||||
}
|
||||
if (argAction.size() > 0) {
|
||||
if (argAction.contains(4)) {
|
||||
if (argAction.contains(LookupActions.CONTAINER)) {
|
||||
if (argUsers.contains("#global") || (argUsers.size() == 0 && argRadius == null)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.MISSING_ACTION_USER));
|
||||
return;
|
||||
}
|
||||
else if (preview > 0) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_TRANSACTION, !argAction.contains(11) ? Selector.FIRST : Selector.SECOND));
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PREVIEW_TRANSACTION, !argAction.contains(LookupActions.ITEM) ? Selector.FIRST : Selector.SECOND));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (argAction.contains(8) || (argAction.contains(11) && !argAction.contains(4)) || (!argAction.contains(0) && !argAction.contains(1) && !argAction.contains(3) && !argAction.contains(4))) {
|
||||
if (argAction.contains(LookupActions.SESSION) || (argAction.contains(LookupActions.ITEM) && !argAction.contains(LookupActions.CONTAINER)) || (!argAction.contains(LookupActions.BLOCK_BREAK) && !argAction.contains(LookupActions.BLOCK_PLACE) && !argAction.contains(LookupActions.ENTITY_KILL) && !argAction.contains(LookupActions.CONTAINER))) {
|
||||
if (finalAction == 0) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ACTION_NOT_SUPPORTED));
|
||||
}
|
||||
@@ -244,7 +246,7 @@ public class RollbackRestoreCommand {
|
||||
}
|
||||
c++;
|
||||
|
||||
if (argAction.contains(4) && argAction.contains(11)) {
|
||||
if (LookupActions.isInventoryLookup(argAction)) {
|
||||
Player onlineUser = Bukkit.getServer().getPlayer(ruser);
|
||||
if (onlineUser == null || !onlineUser.isOnline()) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.USER_OFFLINE, ruser));
|
||||
@@ -258,7 +260,7 @@ public class RollbackRestoreCommand {
|
||||
int y = 0;
|
||||
int z = 0;
|
||||
if (rollbackusers.contains("#container")) {
|
||||
if (argAction.contains(11)) {
|
||||
if (argAction.contains(LookupActions.ITEM)) {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.INVALID_USERNAME, "#container"));
|
||||
return;
|
||||
}
|
||||
@@ -449,7 +451,7 @@ public class RollbackRestoreCommand {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
if (ConfigHandler.activeRollbacks.get(player2.getName()) != null) {
|
||||
ConfigHandler.activeRollbacks.remove(player2.getName());
|
||||
@@ -462,7 +464,7 @@ public class RollbackRestoreCommand {
|
||||
thread.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -19,6 +19,7 @@ import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.SystemUtils;
|
||||
import net.coreprotect.utility.VersionUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class StatusCommand {
|
||||
private static ConcurrentHashMap<String, Boolean> alert = new ConcurrentHashMap<>();
|
||||
@@ -104,13 +105,16 @@ public class StatusCommand {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + Phrase.build(Phrase.STATUS_CONSUMER, Color.WHITE, String.format("%,d", consumerCount), (consumerCount == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
long autoPurgeRowsPurged = ConfigHandler.autoPurgeRowsPurged.get();
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + Phrase.build(Phrase.STATUS_AUTO_PURGE, Color.WHITE, String.format("%,d", autoPurgeRowsPurged), (autoPurgeRowsPurged == 1 ? Selector.FIRST : Selector.SECOND)));
|
||||
|
||||
try {
|
||||
String cpuInfo = "";
|
||||
String cpuInfo = "x" + Runtime.getRuntime().availableProcessors() + " " + Phrase.build(Phrase.CPU_CORES);
|
||||
if (ConfigHandler.processorInfo != null) {
|
||||
String modelName = ConfigHandler.processorInfo.getProcessorIdentifier().getName();
|
||||
String modelName = ConfigHandler.processorInfo.getName();
|
||||
if (modelName.contains(" CPU")) {
|
||||
String[] split = modelName.split(" CPU")[0].split(" ");
|
||||
modelName = split[split.length - 1];
|
||||
@@ -120,7 +124,7 @@ public class StatusCommand {
|
||||
modelName = split[split.length - 1];
|
||||
}
|
||||
|
||||
String cpuSpeed = String.valueOf(ConfigHandler.processorInfo.getMaxFreq());
|
||||
String cpuSpeed = String.valueOf(ConfigHandler.processorInfo.getMaxFrequency());
|
||||
double speedVal = Long.valueOf(cpuSpeed) / 1000000000.0;
|
||||
|
||||
// Fix for Apple Silicon processors reporting 0 GHz
|
||||
@@ -132,10 +136,9 @@ public class StatusCommand {
|
||||
}
|
||||
|
||||
cpuSpeed = String.format("%.2f", speedVal);
|
||||
cpuInfo = "x" + Runtime.getRuntime().availableProcessors() + " " + cpuSpeed + "GHz " + modelName + ".";
|
||||
}
|
||||
else {
|
||||
cpuInfo = "x" + Runtime.getRuntime().availableProcessors() + " " + Phrase.build(Phrase.CPU_CORES);
|
||||
if (speedVal >= 0.01) {
|
||||
cpuInfo = "x" + Runtime.getRuntime().availableProcessors() + " " + cpuSpeed + "GHz " + modelName + ".";
|
||||
}
|
||||
}
|
||||
|
||||
int mb = 1024 * 1024;
|
||||
@@ -150,7 +153,7 @@ public class StatusCommand {
|
||||
Chat.sendMessage(player, Color.DARK_AQUA + Phrase.build(Phrase.STATUS_SYSTEM, Color.WHITE, systemInformation));
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
// Functions.sendMessage(player, Color.DARK_AQUA + "Website: " + Color.WHITE + "www.coreprotect.net/updates/");
|
||||
@@ -173,7 +176,7 @@ public class StatusCommand {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class TabHandler implements TabCompleter {
|
||||
String currentArg = args[args.length - 1].toLowerCase(Locale.ROOT).trim();
|
||||
String lastArg = args.length > 1 ? args[args.length - 2].toLowerCase(Locale.ROOT).trim() : "";
|
||||
|
||||
ParamState paramState = getParamState(args);
|
||||
ParamState paramState = getParamState(sender, args);
|
||||
|
||||
// Handle param-specific completions
|
||||
if (isActionParam(lastArg, currentArg) && hasLookupPermission(sender)) {
|
||||
@@ -160,10 +160,11 @@ public class TabHandler implements TabCompleter {
|
||||
boolean pageLookup;
|
||||
}
|
||||
|
||||
private ParamState getParamState(String[] args) {
|
||||
private ParamState getParamState(CommandSender sender, String[] args) {
|
||||
ParamState state = new ParamState();
|
||||
String senderName = sender.getName();
|
||||
|
||||
if (ConfigHandler.lookupType.get(args[0]) != null && ConfigHandler.lookupPage.get(args[0]) != null) {
|
||||
if (ConfigHandler.lookupType.get(senderName) != null && ConfigHandler.lookupPage.get(senderName) != null) {
|
||||
state.pageLookup = true;
|
||||
}
|
||||
|
||||
@@ -202,13 +203,14 @@ public class TabHandler implements TabCompleter {
|
||||
}
|
||||
|
||||
if (!state.hasContainer) {
|
||||
if (ConfigHandler.lookupType.get(args[0]) != null) {
|
||||
int lookupType = ConfigHandler.lookupType.get(args[0]);
|
||||
Integer lookupType = ConfigHandler.lookupType.get(senderName);
|
||||
if (lookupType != null) {
|
||||
if (lookupType == 1) {
|
||||
state.validContainer = true;
|
||||
}
|
||||
else if (lookupType == 5) {
|
||||
if (ConfigHandler.lookupUlist.get(args[0]).contains("#container")) {
|
||||
List<String> lookupUsers = ConfigHandler.lookupUlist.get(senderName);
|
||||
if (lookupUsers != null && lookupUsers.contains("#container")) {
|
||||
state.validContainer = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.ChatMessage;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.Teleport;
|
||||
import net.coreprotect.utility.Util;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
|
||||
public class TeleportCommand {
|
||||
@@ -56,6 +55,10 @@ public class TeleportCommand {
|
||||
World world = location.getWorld();
|
||||
if (wid > -1) {
|
||||
world = Bukkit.getServer().getWorld(WorldUtils.getWorldName(wid));
|
||||
if (world == null) {
|
||||
Chat.sendMessage(player, new ChatMessage(Phrase.build(Phrase.WORLD_NOT_FOUND, worldName)).build());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String x = null;
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class UndoCommand {
|
||||
protected static void runCommand(CommandSender user, Command command, boolean permission, String[] args) {
|
||||
@@ -47,7 +48,7 @@ public class UndoCommand {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import net.coreprotect.worldedit.WorldEditLogger;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class WorldEditHandler {
|
||||
|
||||
@@ -49,7 +50,7 @@ public class WorldEditHandler {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import net.coreprotect.database.lookup.SignMessageLookup;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class BlockLookupThread implements Runnable {
|
||||
private final CommandSender player;
|
||||
@@ -82,7 +83,7 @@ public class BlockLookupThread implements Runnable {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
ConfigHandler.lookupThrottle.put(player.getName(), new Object[] { false, System.currentTimeMillis() });
|
||||
|
||||
@@ -14,6 +14,7 @@ import net.coreprotect.database.lookup.ChestTransactionLookup;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ChestTransactionLookupThread implements Runnable {
|
||||
private final CommandSender player;
|
||||
@@ -47,7 +48,7 @@ public class ChestTransactionLookupThread implements Runnable {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
ConfigHandler.lookupThrottle.put(player.getName(), new Object[] { false, System.currentTimeMillis() });
|
||||
|
||||
@@ -20,13 +20,15 @@ import com.google.common.base.Strings;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.Lookup;
|
||||
import net.coreprotect.database.logger.ItemLogger;
|
||||
import net.coreprotect.database.lookup.PlayerLookup;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.language.Selector;
|
||||
import net.coreprotect.listener.channel.PluginChannelHandshakeListener;
|
||||
import net.coreprotect.listener.channel.PluginChannelListener;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.ChatUtils;
|
||||
import net.coreprotect.utility.Color;
|
||||
@@ -35,6 +37,7 @@ import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.StringUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class StandardLookupThread implements Runnable {
|
||||
private final CommandSender player;
|
||||
@@ -113,13 +116,13 @@ public class StandardLookupThread implements Runnable {
|
||||
Statement statement = connection.createStatement();
|
||||
String baduser = "";
|
||||
for (String check : rollbackUsers) {
|
||||
if ((!check.equals("#global") && !check.equals("#container")) || actions.contains(9)) {
|
||||
if ((!check.equals("#global") && !check.equals("#container")) || actions.contains(LookupActions.USERNAME)) {
|
||||
exists = PlayerLookup.playerExists(connection, check);
|
||||
if (!exists) {
|
||||
baduser = check;
|
||||
break;
|
||||
}
|
||||
else if (actions.contains(9)) {
|
||||
else if (actions.contains(LookupActions.USERNAME)) {
|
||||
if (ConfigHandler.uuidCache.get(check.toLowerCase(Locale.ROOT)) != null) {
|
||||
String uuid = ConfigHandler.uuidCache.get(check.toLowerCase(Locale.ROOT));
|
||||
uuidList.add(uuid);
|
||||
@@ -148,7 +151,7 @@ public class StandardLookupThread implements Runnable {
|
||||
|
||||
if (exists) {
|
||||
List<String> userList = new ArrayList<>();
|
||||
if (!actions.contains(9)) {
|
||||
if (!actions.contains(LookupActions.USERNAME)) {
|
||||
userList = rollbackUsers;
|
||||
}
|
||||
|
||||
@@ -196,7 +199,7 @@ public class StandardLookupThread implements Runnable {
|
||||
List<String[]> lookupList = Lookup.performPartialLookup(statement, player, uuidList, userList, blockList, excludedBlocks, excludedUsers, actions, finalLocation, radius, rowData, timeStart, timeEnd, (int) pageStart, displayResults, restrict_world, true);
|
||||
|
||||
Chat.sendMessage(player, Color.WHITE + "----- " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_HEADER, "CoreProtect" + Color.WHITE + " | " + Color.DARK_AQUA) + Color.WHITE + " -----");
|
||||
if (actions.contains(6) || actions.contains(7)) { // Chat/command
|
||||
if (actions.contains(LookupActions.CHAT) || actions.contains(LookupActions.COMMAND)) {
|
||||
for (String[] data : lookupList) {
|
||||
String time = data[0];
|
||||
String dplayer = data[1];
|
||||
@@ -212,7 +215,7 @@ public class StandardLookupThread implements Runnable {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (actions.contains(8)) { // login/logouts
|
||||
else if (actions.contains(LookupActions.SESSION)) {
|
||||
for (String[] data : lookupList) {
|
||||
String time = data[0];
|
||||
String dplayer = data[1];
|
||||
@@ -231,13 +234,13 @@ public class StandardLookupThread implements Runnable {
|
||||
leftPadding = leftPadding + Color.WHITE + Strings.padStart("", (timeLength - 50) / 4, ' ');
|
||||
}
|
||||
|
||||
String tag = (action != 0 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_LOGIN, Color.DARK_AQUA + dplayer + Color.WHITE, (action != 0 ? Selector.FIRST : Selector.SECOND)));
|
||||
String tag = (action != SessionActions.LOGOUT ? Color.GREEN + "+" : Color.RED + "-");
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Color.DARK_AQUA + Phrase.build(Phrase.LOOKUP_LOGIN, Color.DARK_AQUA + dplayer + Color.WHITE, (action != SessionActions.LOGOUT ? Selector.FIRST : Selector.SECOND)));
|
||||
Chat.sendComponent(player, Color.WHITE + leftPadding + Color.GREY + "^ " + ChatUtils.getCoordinates(command.getName(), wid, dataX, dataY, dataZ, true, true) + "");
|
||||
PluginChannelListener.getInstance().sendInfoData(player, Integer.parseInt(time), Phrase.LOOKUP_LOGIN, (action != 0 ? Selector.FIRST : Selector.SECOND), dplayer, -1, dataX, dataY, dataZ, wid);
|
||||
PluginChannelListener.getInstance().sendInfoData(player, Integer.parseInt(time), Phrase.LOOKUP_LOGIN, (action != SessionActions.LOGOUT ? Selector.FIRST : Selector.SECOND), dplayer, -1, dataX, dataY, dataZ, wid);
|
||||
}
|
||||
}
|
||||
else if (actions.contains(9)) { // username-changes
|
||||
else if (actions.contains(LookupActions.USERNAME)) {
|
||||
for (String[] data : lookupList) {
|
||||
String time = data[0];
|
||||
String user = ConfigHandler.uuidCacheReversed.get(data[1]);
|
||||
@@ -247,7 +250,7 @@ public class StandardLookupThread implements Runnable {
|
||||
PluginChannelListener.getInstance().sendUsernameData(player, Integer.parseInt(time), user, username);
|
||||
}
|
||||
}
|
||||
else if (actions.contains(10)) { // sign messages
|
||||
else if (actions.contains(LookupActions.SIGN)) {
|
||||
for (String[] data : lookupList) {
|
||||
String time = data[0];
|
||||
String dplayer = data[1];
|
||||
@@ -271,7 +274,7 @@ public class StandardLookupThread implements Runnable {
|
||||
PluginChannelListener.getInstance().sendMessageData(player, Integer.parseInt(time), dplayer, message, true, dataX, dataY, dataZ, wid);
|
||||
}
|
||||
}
|
||||
else if (actions.contains(4) && actions.contains(11)) { // inventory transactions
|
||||
else if (LookupActions.isInventoryLookup(actions)) {
|
||||
for (String[] data : lookupList) {
|
||||
String time = data[0];
|
||||
String dplayer = data[1];
|
||||
@@ -289,35 +292,36 @@ public class StandardLookupThread implements Runnable {
|
||||
String dname = StringUtils.nameFilter(blockType.name().toLowerCase(Locale.ROOT), ddata);
|
||||
byte[] metadata = data[11] == null ? null : data[11].getBytes(StandardCharsets.ISO_8859_1);
|
||||
String tooltip = ItemUtils.getEnchantments(metadata, dtype, amount);
|
||||
Integer itemId = ItemUtils.makeGivableItem(ItemUtils.getItemStack(metadata, dtype, amount));
|
||||
|
||||
String selector = Selector.FIRST;
|
||||
String tag = Color.WHITE + "-";
|
||||
if (daction == 2 || daction == 3) { // LOOKUP_ITEM
|
||||
selector = (daction != 2 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 2 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
if (daction == ItemTransactionActions.DROP || daction == ItemTransactionActions.PICKUP) {
|
||||
selector = (daction != ItemTransactionActions.DROP ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != ItemTransactionActions.DROP ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
else if (daction == 4 || daction == 5) { // LOOKUP_STORAGE
|
||||
selector = (daction == 4 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == 4 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
else if (daction == ItemTransactionActions.REMOVE_ENDER || daction == ItemTransactionActions.ADD_ENDER) {
|
||||
selector = (daction == ItemTransactionActions.REMOVE_ENDER ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemTransactionActions.REMOVE_ENDER ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
else if (daction == 6 || daction == 7) { // LOOKUP_PROJECTILE
|
||||
else if (daction == ItemTransactionActions.THROW || daction == ItemTransactionActions.SHOOT) {
|
||||
selector = Selector.SECOND;
|
||||
tag = Color.RED + "-";
|
||||
}
|
||||
else if (daction == ItemLogger.ITEM_BREAK || daction == ItemLogger.ITEM_DESTROY || daction == ItemLogger.ITEM_CREATE) {
|
||||
selector = (daction == ItemLogger.ITEM_CREATE ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemLogger.ITEM_CREATE ? Color.GREEN + "+" : Color.RED + "-");
|
||||
else if (daction == ItemTransactionActions.BREAK || daction == ItemTransactionActions.DESTROY || daction == ItemTransactionActions.CREATE) {
|
||||
selector = (daction == ItemTransactionActions.CREATE ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemTransactionActions.CREATE ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
else if (daction == ItemLogger.ITEM_SELL || daction == ItemLogger.ITEM_BUY) { // LOOKUP_TRADE
|
||||
selector = (daction == ItemLogger.ITEM_BUY ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemLogger.ITEM_BUY ? Color.GREEN + "+" : Color.RED + "-");
|
||||
else if (daction == ItemTransactionActions.SELL || daction == ItemTransactionActions.BUY) { // LOOKUP_TRADE
|
||||
selector = (daction == ItemTransactionActions.BUY ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemTransactionActions.BUY ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
else { // LOOKUP_CONTAINER
|
||||
selector = (daction == 0 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == 0 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
selector = (daction == ItemTransactionActions.REMOVE ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction == ItemTransactionActions.REMOVE ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + Color.WHITE, selector));
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(Phrase.LOOKUP_CONTAINER, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + ChatUtils.filterComponent(player.hasPermission("coreprotect.give"), ChatUtils.createGiveItemComponent(Color.GREY + "(↓)", command.getName(), itemId)) + Color.WHITE, selector));
|
||||
PluginChannelListener.getInstance().sendData(player, Integer.parseInt(time), Phrase.LOOKUP_CONTAINER, selector, dplayer, dname, amount, dataX, dataY, dataZ, wid, rbd, true, tag.contains("+"));
|
||||
}
|
||||
}
|
||||
@@ -353,7 +357,7 @@ public class StandardLookupThread implements Runnable {
|
||||
|
||||
String dname = "";
|
||||
boolean isPlayer = false;
|
||||
if (daction == 3 && !actions.contains(11) && amount == -1) {
|
||||
if (daction == LookupActions.ENTITY_KILL && !actions.contains(LookupActions.ITEM) && amount == -1) {
|
||||
if (dtype == 0) {
|
||||
if (ConfigHandler.playerIdCacheReversed.get(ddata) == null) {
|
||||
UserStatement.loadName(connection, ddata);
|
||||
@@ -366,10 +370,9 @@ public class StandardLookupThread implements Runnable {
|
||||
}
|
||||
}
|
||||
else {
|
||||
dname = MaterialUtils.getType(dtype).name().toLowerCase(Locale.ROOT);
|
||||
dname = StringUtils.nameFilter(dname, ddata);
|
||||
dname = MaterialUtils.getBlockDisplayName(dtype, ddata);
|
||||
}
|
||||
if (dname.length() > 0 && !isPlayer) {
|
||||
if (dname.length() > 0 && !isPlayer && !dname.contains(":")) {
|
||||
dname = "minecraft:" + dname.toLowerCase(Locale.ROOT) + "";
|
||||
}
|
||||
|
||||
@@ -384,49 +387,50 @@ public class StandardLookupThread implements Runnable {
|
||||
Phrase phrase = Phrase.LOOKUP_BLOCK;
|
||||
String selector = Selector.FIRST;
|
||||
String action = "a:block";
|
||||
if (actions.contains(4) || actions.contains(5) || actions.contains(11) || amount > -1) {
|
||||
if (actions.contains(LookupActions.CONTAINER) || actions.contains(5) || actions.contains(LookupActions.ITEM) || amount > -1) {
|
||||
byte[] metadata = data[11] == null ? null : data[11].getBytes(StandardCharsets.ISO_8859_1);
|
||||
String tooltip = ItemUtils.getEnchantments(metadata, dtype, amount);
|
||||
Integer itemId = ItemUtils.makeGivableItem(ItemUtils.getItemStack(metadata, dtype, amount));
|
||||
|
||||
if (daction == 2 || daction == 3) {
|
||||
if (daction == ItemTransactionActions.DROP || daction == ItemTransactionActions.PICKUP) {
|
||||
phrase = Phrase.LOOKUP_ITEM; // {picked up|dropped}
|
||||
selector = (daction != 2 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 2 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
selector = (daction != ItemTransactionActions.DROP ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != ItemTransactionActions.DROP ? Color.GREEN + "+" : Color.RED + "-");
|
||||
action = "a:item";
|
||||
}
|
||||
else if (daction == 4 || daction == 5) {
|
||||
else if (daction == ItemTransactionActions.REMOVE_ENDER || daction == ItemTransactionActions.ADD_ENDER) {
|
||||
phrase = Phrase.LOOKUP_STORAGE; // {deposited|withdrew}
|
||||
selector = (daction != 4 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 4 ? Color.RED + "-" : Color.GREEN + "+");
|
||||
selector = (daction != ItemTransactionActions.REMOVE_ENDER ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != ItemTransactionActions.REMOVE_ENDER ? Color.RED + "-" : Color.GREEN + "+");
|
||||
action = "a:item";
|
||||
}
|
||||
else if (daction == 6 || daction == 7) {
|
||||
else if (daction == ItemTransactionActions.THROW || daction == ItemTransactionActions.SHOOT) {
|
||||
phrase = Phrase.LOOKUP_PROJECTILE; // {threw|shot}
|
||||
selector = (daction != 7 ? Selector.FIRST : Selector.SECOND);
|
||||
selector = (daction != ItemTransactionActions.SHOOT ? Selector.FIRST : Selector.SECOND);
|
||||
tag = Color.RED + "-";
|
||||
action = "a:item";
|
||||
}
|
||||
else {
|
||||
phrase = Phrase.LOOKUP_CONTAINER; // {added|removed}
|
||||
selector = (daction != 0 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 0 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
selector = (daction != ItemTransactionActions.REMOVE ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != ItemTransactionActions.REMOVE ? Color.GREEN + "+" : Color.RED + "-");
|
||||
action = "a:container";
|
||||
}
|
||||
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(phrase, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + Color.WHITE, selector));
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(phrase, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, "x" + amount, ChatUtils.createTooltip(Color.DARK_AQUA + rbd + dname, tooltip) + ChatUtils.filterComponent(player.hasPermission("coreprotect.give"), ChatUtils.createGiveItemComponent(Color.GREY + "(↓)", command.getName(), itemId)) + Color.WHITE, selector));
|
||||
PluginChannelListener.getInstance().sendData(player, Integer.parseInt(time), phrase, selector, dplayer, dname, (tag.contains("+") ? 1 : -1), dataX, dataY, dataZ, wid, rbd, action.contains("container"), tag.contains("+"));
|
||||
}
|
||||
else {
|
||||
if (daction == 2 || daction == 3) {
|
||||
if (daction == LookupActions.INTERACTION || daction == LookupActions.ENTITY_KILL) {
|
||||
phrase = Phrase.LOOKUP_INTERACTION; // {clicked|killed}
|
||||
selector = (daction != 3 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 3 ? Color.WHITE + "-" : Color.RED + "-");
|
||||
action = (daction == 2 ? "a:click" : "a:kill");
|
||||
selector = (daction != LookupActions.ENTITY_KILL ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != LookupActions.ENTITY_KILL ? Color.WHITE + "-" : Color.RED + "-");
|
||||
action = (daction == LookupActions.INTERACTION ? "a:click" : "a:kill");
|
||||
}
|
||||
else {
|
||||
phrase = Phrase.LOOKUP_BLOCK; // {placed|broke}
|
||||
selector = (daction != 0 ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != 0 ? Color.GREEN + "+" : Color.RED + "-");
|
||||
selector = (daction != LookupActions.BLOCK_BREAK ? Selector.FIRST : Selector.SECOND);
|
||||
tag = (daction != LookupActions.BLOCK_BREAK ? Color.GREEN + "+" : Color.RED + "-");
|
||||
}
|
||||
|
||||
Chat.sendComponent(player, timeago + " " + tag + " " + Phrase.build(phrase, Color.DARK_AQUA + rbd + dplayer + Color.WHITE + rbd, Color.DARK_AQUA + rbd + dname + Color.WHITE, selector));
|
||||
@@ -439,7 +443,7 @@ public class StandardLookupThread implements Runnable {
|
||||
}
|
||||
if (rows > displayResults) {
|
||||
int total_pages = (int) Math.ceil(rows / (displayResults + 0.0));
|
||||
if (actions.contains(6) || actions.contains(7) || actions.contains(9) || (actions.contains(4) && actions.contains(11))) {
|
||||
if (actions.contains(LookupActions.CHAT) || actions.contains(LookupActions.COMMAND) || actions.contains(LookupActions.USERNAME) || LookupActions.isInventoryLookup(actions)) {
|
||||
Chat.sendMessage(player, "-----");
|
||||
}
|
||||
Chat.sendComponent(player, ChatUtils.getPageNavigation(command.getName(), page, total_pages));
|
||||
@@ -462,7 +466,7 @@ public class StandardLookupThread implements Runnable {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
ConfigHandler.lookupThrottle.put(player.getName(), new Object[] { false, System.currentTimeMillis() });
|
||||
|
||||
@@ -4,6 +4,10 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
|
||||
/**
|
||||
* Parser for action-related command arguments
|
||||
*/
|
||||
@@ -53,79 +57,79 @@ public class ActionParser {
|
||||
argument = argument.replaceFirst("#", "");
|
||||
}
|
||||
if (argument.equals("broke") || argument.equals("break") || argument.equals("remove") || argument.equals("destroy") || argument.equals("block-break") || argument.equals("block-remove") || argument.equals("-block") || argument.equals("-blocks") || argument.equals("block-")) {
|
||||
result.add(0);
|
||||
result.add(LookupActions.BLOCK_BREAK);
|
||||
}
|
||||
else if (argument.equals("placed") || argument.equals("place") || argument.equals("block-place") || argument.equals("+block") || argument.equals("+blocks") || argument.equals("block+")) {
|
||||
result.add(1);
|
||||
result.add(LookupActions.BLOCK_PLACE);
|
||||
}
|
||||
else if (argument.equals("block") || argument.equals("blocks") || argument.equals("block-change") || argument.equals("change") || argument.equals("changes")) {
|
||||
result.add(0);
|
||||
result.add(1);
|
||||
result.add(LookupActions.BLOCK_BREAK);
|
||||
result.add(LookupActions.BLOCK_PLACE);
|
||||
}
|
||||
else if (argument.equals("click") || argument.equals("clicks") || argument.equals("interact") || argument.equals("interaction") || argument.equals("player-interact") || argument.equals("player-interaction") || argument.equals("player-click")) {
|
||||
result.add(2);
|
||||
result.add(LookupActions.INTERACTION);
|
||||
}
|
||||
else if (argument.equals("death") || argument.equals("deaths") || argument.equals("entity-death") || argument.equals("entity-deaths") || argument.equals("kill") || argument.equals("kills") || argument.equals("entity-kill") || argument.equals("entity-kills")) {
|
||||
result.add(3);
|
||||
result.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
else if (argument.equals("container") || argument.equals("container-change") || argument.equals("containers") || argument.equals("chest") || argument.equals("transaction") || argument.equals("transactions")) {
|
||||
result.add(4);
|
||||
result.add(LookupActions.CONTAINER);
|
||||
}
|
||||
else if (argument.equals("-container") || argument.equals("container-") || argument.equals("remove-container")) {
|
||||
result.add(4);
|
||||
result.add(0);
|
||||
result.add(LookupActions.CONTAINER);
|
||||
result.add(ItemTransactionActions.REMOVE);
|
||||
}
|
||||
else if (argument.equals("+container") || argument.equals("container+") || argument.equals("container-add") || argument.equals("add-container")) {
|
||||
result.add(4);
|
||||
result.add(1);
|
||||
result.add(LookupActions.CONTAINER);
|
||||
result.add(ItemTransactionActions.ADD);
|
||||
}
|
||||
else if (argument.equals("chat") || argument.equals("chats")) {
|
||||
result.add(6);
|
||||
result.add(LookupActions.CHAT);
|
||||
}
|
||||
else if (argument.equals("command") || argument.equals("commands")) {
|
||||
result.add(7);
|
||||
result.add(LookupActions.COMMAND);
|
||||
}
|
||||
else if (argument.equals("logins") || argument.equals("login") || argument.equals("+session") || argument.equals("+sessions") || argument.equals("session+") || argument.equals("+connection") || argument.equals("connection+")) {
|
||||
result.add(8);
|
||||
result.add(1);
|
||||
result.add(LookupActions.SESSION);
|
||||
result.add(SessionActions.LOGIN);
|
||||
}
|
||||
else if (argument.equals("logout") || argument.equals("logouts") || argument.equals("-session") || argument.equals("-sessions") || argument.equals("session-") || argument.equals("-connection") || argument.equals("connection-")) {
|
||||
result.add(8);
|
||||
result.add(0);
|
||||
result.add(LookupActions.SESSION);
|
||||
result.add(SessionActions.LOGOUT);
|
||||
}
|
||||
else if (argument.equals("session") || argument.equals("sessions") || argument.equals("connection") || argument.equals("connections")) {
|
||||
result.add(8);
|
||||
result.add(LookupActions.SESSION);
|
||||
}
|
||||
else if (argument.equals("username") || argument.equals("usernames") || argument.equals("user") || argument.equals("users") || argument.equals("name") || argument.equals("names") || argument.equals("uuid") || argument.equals("uuids") || argument.equals("username-change") || argument.equals("username-changes") || argument.equals("name-change") || argument.equals("name-changes")) {
|
||||
result.add(9);
|
||||
result.add(LookupActions.USERNAME);
|
||||
}
|
||||
else if (argument.equals("sign") || argument.equals("signs")) {
|
||||
result.add(10);
|
||||
result.add(LookupActions.SIGN);
|
||||
}
|
||||
else if (argument.equals("inv") || argument.equals("inventory") || argument.equals("inventories")) {
|
||||
result.add(4); // container
|
||||
result.add(11); // item
|
||||
result.add(LookupActions.CONTAINER);
|
||||
result.add(LookupActions.ITEM);
|
||||
}
|
||||
else if (argument.equals("-inv") || argument.equals("inv-") || argument.equals("-inventory") || argument.equals("inventory-") || argument.equals("-inventories")) {
|
||||
result.add(4);
|
||||
result.add(11);
|
||||
result.add(1);
|
||||
result.add(LookupActions.CONTAINER);
|
||||
result.add(LookupActions.ITEM);
|
||||
result.add(ItemTransactionActions.ADD);
|
||||
}
|
||||
else if (argument.equals("+inv") || argument.equals("inv+") || argument.equals("+inventory") || argument.equals("inventory+") || argument.equals("+inventories")) {
|
||||
result.add(4);
|
||||
result.add(11);
|
||||
result.add(0);
|
||||
result.add(LookupActions.CONTAINER);
|
||||
result.add(LookupActions.ITEM);
|
||||
result.add(ItemTransactionActions.REMOVE);
|
||||
}
|
||||
else if (argument.equals("item") || argument.equals("items")) {
|
||||
result.add(11);
|
||||
result.add(LookupActions.ITEM);
|
||||
}
|
||||
else if (argument.equals("-item") || argument.equals("item-") || argument.equals("-items") || argument.equals("items-") || argument.equals("drop") || argument.equals("drops") || argument.equals("deposit") || argument.equals("deposits") || argument.equals("deposited")) {
|
||||
result.add(11);
|
||||
result.add(0);
|
||||
result.add(LookupActions.ITEM);
|
||||
result.add(ItemTransactionActions.REMOVE);
|
||||
}
|
||||
else if (argument.equals("+item") || argument.equals("item+") || argument.equals("+items") || argument.equals("items+") || argument.equals("pickup") || argument.equals("pickups") || argument.equals("withdraw") || argument.equals("withdraws") || argument.equals("withdrew")) {
|
||||
result.add(11);
|
||||
result.add(1);
|
||||
result.add(LookupActions.ITEM);
|
||||
result.add(ItemTransactionActions.ADD);
|
||||
}
|
||||
else {
|
||||
result.add(-1);
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.coreprotect.command.parser;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GivableItemIdParser {
|
||||
|
||||
protected static final Pattern PATTERN = Pattern.compile("#([0-9]+)");
|
||||
|
||||
public static Integer parseGivableItemId(String[] inputArguments) {
|
||||
for (String argument : inputArguments) {
|
||||
Matcher matcher = PATTERN.matcher(argument);
|
||||
if (matcher.find()) {
|
||||
return Integer.parseInt(matcher.group(1));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@ import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
@@ -62,9 +64,12 @@ public class MaterialParser {
|
||||
for (String i3 : i2) {
|
||||
if (!checkTags(i3, restricted)) {
|
||||
Material i3_material = MaterialUtils.getType(i3);
|
||||
if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) {
|
||||
if (i3_material != null && (i3_material.isBlock() || argAction.contains(LookupActions.CONTAINER))) {
|
||||
restricted.add(i3_material);
|
||||
}
|
||||
else if (!argAction.contains(LookupActions.CONTAINER) && BlockTypeUtils.hasBlockType(i3)) {
|
||||
restricted.add(BlockTypeUtils.normalizeKey(i3));
|
||||
}
|
||||
else {
|
||||
EntityType i3_entity = EntityUtils.getEntityType(i3);
|
||||
if (i3_entity != null) {
|
||||
@@ -91,9 +96,12 @@ public class MaterialParser {
|
||||
else {
|
||||
if (!checkTags(argument, restricted)) {
|
||||
Material material = MaterialUtils.getType(argument);
|
||||
if (material != null && (material.isBlock() || argAction.contains(4))) {
|
||||
if (material != null && (material.isBlock() || argAction.contains(LookupActions.CONTAINER))) {
|
||||
restricted.add(material);
|
||||
}
|
||||
else if (!argAction.contains(LookupActions.CONTAINER) && BlockTypeUtils.hasBlockType(argument)) {
|
||||
restricted.add(BlockTypeUtils.normalizeKey(argument));
|
||||
}
|
||||
else {
|
||||
EntityType entityType = EntityUtils.getEntityType(argument);
|
||||
if (entityType != null) {
|
||||
@@ -154,9 +162,12 @@ public class MaterialParser {
|
||||
for (String i3 : i2) {
|
||||
if (!checkTags(i3, excluded)) {
|
||||
Material i3_material = MaterialUtils.getType(i3);
|
||||
if (i3_material != null && (i3_material.isBlock() || argAction.contains(4))) {
|
||||
if (i3_material != null && (i3_material.isBlock() || argAction.contains(LookupActions.CONTAINER))) {
|
||||
excluded.put(i3_material, false);
|
||||
}
|
||||
else if (!argAction.contains(LookupActions.CONTAINER) && BlockTypeUtils.hasBlockType(i3)) {
|
||||
excluded.put(BlockTypeUtils.normalizeKey(i3), false);
|
||||
}
|
||||
else {
|
||||
EntityType i3_entity = EntityUtils.getEntityType(i3);
|
||||
if (i3_entity != null) {
|
||||
@@ -178,9 +189,12 @@ public class MaterialParser {
|
||||
else {
|
||||
if (!checkTags(argument, excluded)) {
|
||||
Material iMaterial = MaterialUtils.getType(argument);
|
||||
if (iMaterial != null && (iMaterial.isBlock() || argAction.contains(4))) {
|
||||
if (iMaterial != null && (iMaterial.isBlock() || argAction.contains(LookupActions.CONTAINER))) {
|
||||
excluded.put(iMaterial, false);
|
||||
}
|
||||
else if (!argAction.contains(LookupActions.CONTAINER) && BlockTypeUtils.hasBlockType(argument)) {
|
||||
excluded.put(BlockTypeUtils.normalizeKey(argument), false);
|
||||
}
|
||||
else {
|
||||
EntityType iEntity = EntityUtils.getEntityType(argument);
|
||||
if (iEntity != null) {
|
||||
@@ -216,6 +230,9 @@ public class MaterialParser {
|
||||
tagMap.put("#natural", BlockGroup.NATURAL_BLOCKS);
|
||||
tagMap.put("#pressure_plate", BlockGroup.PRESSURE_PLATES);
|
||||
tagMap.put("#shulker_box", BlockGroup.SHULKER_BOXES);
|
||||
if (!BlockGroup.BUNDLES.isEmpty()) {
|
||||
tagMap.put("#bundle", BlockGroup.BUNDLES);
|
||||
}
|
||||
return tagMap;
|
||||
}
|
||||
|
||||
@@ -296,6 +313,9 @@ public class MaterialParser {
|
||||
if (material != null) {
|
||||
isBlock = true;
|
||||
}
|
||||
else if (BlockTypeUtils.hasBlockType(argument)) {
|
||||
isBlock = true;
|
||||
}
|
||||
else {
|
||||
EntityType entityType = EntityUtils.getEntityType(argument);
|
||||
if (entityType != null) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.bukkit.World;
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.language.Language;
|
||||
import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.utility.VersionUtils;
|
||||
|
||||
public class Config extends Language {
|
||||
|
||||
@@ -40,16 +41,20 @@ public class Config extends Language {
|
||||
public String MYSQL_USERNAME;
|
||||
public String MYSQL_PASSWORD;
|
||||
public String LANGUAGE;
|
||||
public String AUTO_PURGE;
|
||||
public String AUTO_PURGE_TIME;
|
||||
public boolean ENABLE_SSL;
|
||||
public boolean DISABLE_WAL;
|
||||
public boolean HOVER_EVENTS;
|
||||
public boolean DATABASE_LOCK;
|
||||
public boolean LOG_CANCELLED_CHAT;
|
||||
public boolean HOPPER_FILTER_META;
|
||||
public boolean DUPLICATE_SUPPRESSION;
|
||||
public boolean EXCLUDE_TNT;
|
||||
public boolean NETWORK_DEBUG;
|
||||
public boolean MYSQL;
|
||||
public boolean CHECK_UPDATES;
|
||||
public boolean ERROR_REPORTING;
|
||||
public boolean API_ENABLED;
|
||||
public boolean VERBOSE;
|
||||
public boolean ROLLBACK_ITEMS;
|
||||
@@ -62,6 +67,7 @@ public class Config extends Language {
|
||||
public boolean PISTONS;
|
||||
public boolean BLOCK_BURN;
|
||||
public boolean BLOCK_IGNITE;
|
||||
public boolean FIRE_EXTINGUISH;
|
||||
public boolean EXPLOSIONS;
|
||||
public boolean ENTITY_CHANGE;
|
||||
public boolean ENTITY_KILLS;
|
||||
@@ -102,7 +108,9 @@ public class Config extends Language {
|
||||
DEFAULT_VALUES.put("mysql-username", "root");
|
||||
DEFAULT_VALUES.put("mysql-password", "");
|
||||
DEFAULT_VALUES.put("language", "en");
|
||||
DEFAULT_VALUES.put("auto-purge", "false");
|
||||
DEFAULT_VALUES.put("check-updates", "true");
|
||||
DEFAULT_VALUES.put("error-reporting", "true");
|
||||
DEFAULT_VALUES.put("api-enabled", "true");
|
||||
DEFAULT_VALUES.put("verbose", "true");
|
||||
DEFAULT_VALUES.put("default-radius", "10");
|
||||
@@ -117,6 +125,7 @@ public class Config extends Language {
|
||||
DEFAULT_VALUES.put("pistons", "true");
|
||||
DEFAULT_VALUES.put("block-burn", "true");
|
||||
DEFAULT_VALUES.put("block-ignite", "true");
|
||||
DEFAULT_VALUES.put("fire-extinguish", "false");
|
||||
DEFAULT_VALUES.put("explosions", "true");
|
||||
DEFAULT_VALUES.put("entity-change", "true");
|
||||
DEFAULT_VALUES.put("entity-kills", "true");
|
||||
@@ -145,7 +154,9 @@ public class Config extends Language {
|
||||
HEADERS.put("donation-key", new String[] { "# CoreProtect is donationware. Obtain a donation key from coreprotect.net/donate/" });
|
||||
HEADERS.put("use-mysql", new String[] { "# MySQL is optional and not required.", "# If you prefer to use MySQL, enable the following and fill out the fields." });
|
||||
HEADERS.put("language", new String[] { "# If modified, will automatically attempt to translate languages phrases.", "# List of language codes: https://coreprotect.net/languages/" });
|
||||
HEADERS.put("auto-purge", new String[] { "# Automatically purge data older than the configured time.", "# Examples: 30d, 12w, 6mo. Set to false to disable." });
|
||||
HEADERS.put("check-updates", new String[] { "# If enabled, CoreProtect will check for updates when your server starts up.", "# If an update is available, you'll be notified via your server console.", });
|
||||
HEADERS.put("error-reporting", new String[] { "# Automatically sends errors to the plugin author." });
|
||||
HEADERS.put("api-enabled", new String[] { "# If enabled, other plugins will be able to utilize the CoreProtect API.", });
|
||||
HEADERS.put("verbose", new String[] { "# If enabled, extra data is displayed during rollbacks and restores.", "# Can be manually triggered by adding \"#verbose\" to your rollback command." });
|
||||
HEADERS.put("default-radius", new String[] { "# If no radius is specified in a rollback or restore, this value will be", "# used as the radius. Set to \"0\" to disable automatically adding a radius." });
|
||||
@@ -160,6 +171,7 @@ public class Config extends Language {
|
||||
HEADERS.put("pistons", new String[] { "# Properly track blocks moved by pistons." });
|
||||
HEADERS.put("block-burn", new String[] { "# Logs blocks that burn up in a fire." });
|
||||
HEADERS.put("block-ignite", new String[] { "# Logs when a block naturally ignites, such as from fire spreading." });
|
||||
HEADERS.put("fire-extinguish", new String[] { "# Logs when fire naturally extinguishes." });
|
||||
HEADERS.put("explosions", new String[] { "# Logs explosions, such as TNT and Creepers." });
|
||||
HEADERS.put("entity-change", new String[] { "# Track when an entity changes a block, such as an Enderman destroying blocks." });
|
||||
HEADERS.put("entity-kills", new String[] { "# Logs killed entities, such as killed cows and enderman." });
|
||||
@@ -193,6 +205,7 @@ public class Config extends Language {
|
||||
this.DATABASE_LOCK = this.getBoolean("database-lock", true);
|
||||
this.LOG_CANCELLED_CHAT = this.getBoolean("log-cancelled-chat", true);
|
||||
this.HOPPER_FILTER_META = this.getBoolean("hopper-filter-meta", false);
|
||||
this.DUPLICATE_SUPPRESSION = this.getBoolean("duplicate-suppression", true);
|
||||
this.EXCLUDE_TNT = this.getBoolean("exclude-tnt", false);
|
||||
this.NETWORK_DEBUG = this.getBoolean("network-debug", false);
|
||||
this.UNKNOWN_LOGGING = this.getBoolean("unknown-logging", false);
|
||||
@@ -206,7 +219,10 @@ public class Config extends Language {
|
||||
this.MYSQL_USERNAME = this.getString("mysql-username");
|
||||
this.MYSQL_PASSWORD = this.getString("mysql-password");
|
||||
this.LANGUAGE = this.getString("language");
|
||||
this.AUTO_PURGE = this.getString("auto-purge");
|
||||
this.AUTO_PURGE_TIME = this.getString("auto-purge-time");
|
||||
this.CHECK_UPDATES = this.getBoolean("check-updates");
|
||||
this.ERROR_REPORTING = this.getBoolean("error-reporting");
|
||||
this.API_ENABLED = this.getBoolean("api-enabled");
|
||||
this.VERBOSE = this.getBoolean("verbose");
|
||||
this.DEFAULT_RADIUS = this.getInt("default-radius");
|
||||
@@ -221,6 +237,7 @@ public class Config extends Language {
|
||||
this.PISTONS = this.getBoolean("pistons");
|
||||
this.BLOCK_BURN = this.getBoolean("block-burn");
|
||||
this.BLOCK_IGNITE = this.getBoolean("block-ignite");
|
||||
this.FIRE_EXTINGUISH = this.getBoolean("fire-extinguish");
|
||||
this.EXPLOSIONS = this.getBoolean("explosions");
|
||||
this.ENTITY_CHANGE = this.getBoolean("entity-change");
|
||||
this.ENTITY_KILLS = this.getBoolean("entity-kills");
|
||||
@@ -463,6 +480,9 @@ public class Config extends Language {
|
||||
if (configuredValue != null) {
|
||||
continue;
|
||||
}
|
||||
if (key.equals("auto-purge") && VersionUtils.isCommunityEdition()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String[] header = HEADERS.get(key);
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.util.TreeMap;
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.language.Language;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ConfigFile extends Config {
|
||||
|
||||
@@ -201,7 +202,7 @@ public class ConfigFile extends Config {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +223,7 @@ public class ConfigFile extends Config {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@ import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
@@ -35,9 +38,9 @@ import net.coreprotect.patch.Patch;
|
||||
import net.coreprotect.spigot.SpigotAdapter;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
import net.coreprotect.utility.SystemUtils;
|
||||
import net.coreprotect.utility.VersionUtils;
|
||||
import oshi.hardware.CentralProcessor;
|
||||
|
||||
public class ConfigHandler extends Queue {
|
||||
|
||||
@@ -51,9 +54,9 @@ public class ConfigHandler extends Queue {
|
||||
public static final String EDITION_NAME = VersionUtils.getPluginName();
|
||||
public static final String COMMUNITY_EDITION = "Community Edition";
|
||||
public static final String JAVA_VERSION = "11.0";
|
||||
public static final String MINECRAFT_VERSION = "1.16";
|
||||
public static final String PATCH_VERSION = "23.1";
|
||||
public static final String LATEST_VERSION = "1.21.11";
|
||||
public static final String MINECRAFT_VERSION = "1.16.5";
|
||||
public static final String PATCH_VERSION = "24.1";
|
||||
public static final String LATEST_VERSION = "26.2";
|
||||
public static String path = "plugins/CoreProtect/";
|
||||
public static String sqlite = "database.db";
|
||||
public static String host = "127.0.0.1";
|
||||
@@ -65,8 +68,12 @@ public class ConfigHandler extends Queue {
|
||||
public static String prefixConfig = "co_";
|
||||
public static int maximumPoolSize = 10;
|
||||
|
||||
public static final String BLACKLIST_COMMENT_SEPARATOR = ";";
|
||||
public static final String BLACKLIST_FILTER_SEPARATOR = "@";
|
||||
public static final String BLACKLIST_FILENAME = "blacklist.txt";
|
||||
|
||||
public static HikariDataSource hikariDataSource = null;
|
||||
public static final CentralProcessor processorInfo = SystemUtils.getProcessorInfo();
|
||||
public static final SystemUtils.ProcessorInfo processorInfo = SystemUtils.getProcessorInfo();
|
||||
public static final boolean isSpigot = VersionUtils.isSpigot();
|
||||
public static final boolean isPaper = VersionUtils.isPaper();
|
||||
public static final boolean isFolia = VersionUtils.isFolia();
|
||||
@@ -82,6 +89,7 @@ public class ConfigHandler extends Queue {
|
||||
public static volatile int blockdataId = 0;
|
||||
public static volatile int entityId = 0;
|
||||
public static volatile int artId = 0;
|
||||
public static final AtomicLong autoPurgeRowsPurged = new AtomicLong(0);
|
||||
|
||||
private static <K, V> Map<K, V> syncMap() {
|
||||
return Collections.synchronizedMap(new HashMap<>());
|
||||
@@ -100,10 +108,11 @@ public class ConfigHandler extends Queue {
|
||||
public static Map<String, int[]> rollbackHash = syncMap();
|
||||
public static Map<String, Boolean> inspecting = syncMap();
|
||||
public static Map<String, Boolean> blacklist = syncMap();
|
||||
public static Map<String, HashSet<String>> FilteredBlacklist = syncMap();
|
||||
public static Map<String, Integer> loggingChest = syncMap();
|
||||
public static Map<String, Integer> loggingItem = syncMap();
|
||||
public static ConcurrentHashMap<String, List<Object>> transactingChest = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<String, List<ItemStack[]>> oldContainer = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<String, Set<String>> oldContainerViewers = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<String, List<ItemStack>> itemsPickup = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<String, List<ItemStack>> itemsDrop = new ConcurrentHashMap<>();
|
||||
public static ConcurrentHashMap<String, List<ItemStack>> itemsThrown = new ConcurrentHashMap<>();
|
||||
@@ -152,27 +161,73 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
|
||||
public static void addOldContainerViewer(String locationSuffix, String loggingId) {
|
||||
ConfigHandler.oldContainerViewers.compute(locationSuffix, (key, viewers) -> {
|
||||
if (viewers == null) {
|
||||
viewers = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
viewers.add(loggingId);
|
||||
return viewers;
|
||||
});
|
||||
}
|
||||
|
||||
public static void removeOldContainerViewer(String locationSuffix, String loggingId) {
|
||||
ConfigHandler.oldContainerViewers.computeIfPresent(locationSuffix, (key, viewers) -> {
|
||||
viewers.remove(loggingId);
|
||||
return viewers.isEmpty() ? null : viewers;
|
||||
});
|
||||
}
|
||||
|
||||
public static boolean isBlacklisted(String user) {
|
||||
return ConfigHandler.blacklist.containsKey(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
public static boolean isBlacklisted(String user, String object) {
|
||||
if (ConfigHandler.blacklist.containsKey(object) || ConfigHandler.blacklist.containsKey(user.toLowerCase(Locale.ROOT))) {
|
||||
return true;
|
||||
}
|
||||
return isFilterBlacklisted(user, object);
|
||||
}
|
||||
|
||||
public static boolean isFilterBlacklisted(String user, String object) {
|
||||
HashSet<String> blUserSet = FilteredBlacklist.get(object);
|
||||
if (blUserSet == null) {
|
||||
return false;
|
||||
}
|
||||
return blUserSet.contains(user.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
private static void loadBlacklist() {
|
||||
try {
|
||||
ConfigHandler.blacklist.clear();
|
||||
String blacklist = ConfigHandler.path + "blacklist.txt";
|
||||
boolean exists = (new File(blacklist)).exists();
|
||||
if (exists) {
|
||||
RandomAccessFile blfile = new RandomAccessFile(blacklist, "rw");
|
||||
long blc = blfile.length();
|
||||
if (blc > 0) {
|
||||
while (blfile.getFilePointer() < blfile.length()) {
|
||||
String blacklistUser = blfile.readLine().replaceAll(" ", "").toLowerCase(Locale.ROOT);
|
||||
if (blacklistUser.length() > 0) {
|
||||
ConfigHandler.blacklist.put(blacklistUser, true);
|
||||
}
|
||||
ConfigHandler.FilteredBlacklist.clear();
|
||||
|
||||
File file = new File(ConfigHandler.path, BLACKLIST_FILENAME);
|
||||
if (!file.exists()) {
|
||||
return;
|
||||
}
|
||||
try (RandomAccessFile blfile = new RandomAccessFile(file, "r")) {
|
||||
if (blfile.length() == 0) {
|
||||
return;
|
||||
}
|
||||
String blLine;
|
||||
while ((blLine = blfile.readLine()) != null) {
|
||||
blLine = blLine.replace(" ", "").toLowerCase(Locale.ROOT).split(BLACKLIST_COMMENT_SEPARATOR)[0];
|
||||
if (blLine.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
String[] blSplit = blLine.split(BLACKLIST_FILTER_SEPARATOR);
|
||||
if (blSplit.length == 1) {
|
||||
ConfigHandler.blacklist.put(blLine, true);
|
||||
}
|
||||
else {
|
||||
ConfigHandler.FilteredBlacklist.computeIfAbsent(blSplit[0], k -> new HashSet<>()).add(blSplit[1]);
|
||||
}
|
||||
}
|
||||
blfile.close();
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +254,7 @@ public class ConfigHandler extends Queue {
|
||||
ConfigHandler.loadBlacklist(); // Load the blacklist file if it exists.
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,7 +289,7 @@ public class ConfigHandler extends Queue {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -294,7 +349,7 @@ public class ConfigHandler extends Queue {
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +373,7 @@ public class ConfigHandler extends Queue {
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,7 +397,7 @@ public class ConfigHandler extends Queue {
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,7 +421,7 @@ public class ConfigHandler extends Queue {
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -425,7 +480,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@@ -463,7 +518,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +557,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -523,7 +578,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(true, 0)) {
|
||||
@@ -558,7 +613,7 @@ public class ConfigHandler extends Queue {
|
||||
return validVersion && databaseLock;
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -570,7 +625,7 @@ public class ConfigHandler extends Queue {
|
||||
ListenerHandler.unregisterNetworking(); // Unregister channels for networking API
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class Consumer extends Process implements Runnable, Thread.UncaughtExceptionHandler {
|
||||
|
||||
@@ -51,7 +52,7 @@ public class Consumer extends Process implements Runnable, Thread.UncaughtExcept
|
||||
Thread.sleep(30000); // 30 seconds
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ public class Consumer extends Process implements Runnable, Thread.UncaughtExcept
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
pausedSuccess = false;
|
||||
}
|
||||
@@ -133,7 +134,7 @@ public class Consumer extends Process implements Runnable, Thread.UncaughtExcept
|
||||
Process.processConsumer(process_id, lastRun);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
errorDelay();
|
||||
}
|
||||
}
|
||||
@@ -141,7 +142,7 @@ public class Consumer extends Process implements Runnable, Thread.UncaughtExcept
|
||||
|
||||
@Override
|
||||
public void uncaughtException(Thread thread, Throwable e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
Bukkit.getPluginManager().disablePlugin(CoreProtect.getInstance());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package net.coreprotect.consumer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@@ -9,8 +10,10 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.CreatureSpawner;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Bisected;
|
||||
import org.bukkit.block.data.Bisected.Half;
|
||||
import org.bukkit.block.data.Waterlogged;
|
||||
import org.bukkit.block.data.type.Bed;
|
||||
import org.bukkit.block.data.type.Bed.Part;
|
||||
import org.bukkit.entity.EntityType;
|
||||
@@ -25,25 +28,58 @@ import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.listener.block.BlockUtil;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class Queue {
|
||||
|
||||
protected static synchronized int modifyForceContainer(String id, ItemStack[] container) {
|
||||
public static synchronized void addForceContainer(String id, ItemStack[] container) {
|
||||
if (container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ConfigHandler.forceContainer.computeIfAbsent(id, k -> new ArrayList<>()).add(container);
|
||||
}
|
||||
|
||||
public static synchronized void setForceContainer(String id, ItemStack[] container) {
|
||||
if (container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemStack[]> forceList = new ArrayList<>();
|
||||
forceList.add(container);
|
||||
ConfigHandler.forceContainer.put(id, forceList);
|
||||
}
|
||||
|
||||
public static synchronized ItemStack[] pollForceContainer(String id) {
|
||||
List<ItemStack[]> forceList = ConfigHandler.forceContainer.get(id);
|
||||
if (forceList == null) {
|
||||
return 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (container == null) {
|
||||
forceList.remove(0);
|
||||
}
|
||||
else {
|
||||
forceList.add(container);
|
||||
ItemStack[] container = forceList.isEmpty() ? null : forceList.remove(0);
|
||||
if (forceList.isEmpty()) {
|
||||
ConfigHandler.forceContainer.remove(id);
|
||||
}
|
||||
|
||||
return forceList.size();
|
||||
return container;
|
||||
}
|
||||
|
||||
public static synchronized ItemStack[] peekForceContainer(String id) {
|
||||
List<ItemStack[]> forceList = ConfigHandler.forceContainer.get(id);
|
||||
return (forceList == null || forceList.isEmpty()) ? null : forceList.get(0);
|
||||
}
|
||||
|
||||
public static synchronized int getForceContainerSize(String id) {
|
||||
List<ItemStack[]> forceList = ConfigHandler.forceContainer.get(id);
|
||||
return forceList == null ? 0 : forceList.size();
|
||||
}
|
||||
|
||||
public static synchronized void removeForceContainer(String id) {
|
||||
ConfigHandler.forceContainer.remove(id);
|
||||
}
|
||||
|
||||
protected static synchronized int getChestId(String id) {
|
||||
@@ -68,6 +104,10 @@ public class Queue {
|
||||
Consumer.consumer_id.put(currentConsumer, new Integer[] { Consumer.consumer_id.get(currentConsumer)[0], 0 });
|
||||
}
|
||||
|
||||
private static Location getBlockLocation(Location location) {
|
||||
return new Location(location.getWorld(), location.getBlockX(), location.getBlockY(), location.getBlockZ());
|
||||
}
|
||||
|
||||
protected static void queueAdvancedBreak(String user, BlockState block, Material type, String blockData, int data, Material breakType, int blockNumber) {
|
||||
int currentConsumer = Consumer.currentConsumer;
|
||||
int consumerId = Consumer.newConsumerId(currentConsumer);
|
||||
@@ -89,12 +129,12 @@ public class Queue {
|
||||
protected static void queueBlockBreakValidate(final String user, final Block block, final BlockState blockState, final Material type, final String blockData, final int extraData, int ticks) {
|
||||
Scheduler.scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> {
|
||||
try {
|
||||
if (!block.getType().equals(type)) {
|
||||
if (!Objects.equals(block.getType(), type)) {
|
||||
queueBlockBreak(user, blockState, type, blockData, null, extraData, 0);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}, block.getLocation(), ticks);
|
||||
}
|
||||
@@ -104,7 +144,7 @@ public class Queue {
|
||||
CreatureSpawner mobSpawner = (CreatureSpawner) block;
|
||||
extraData = EntityUtils.getSpawnerType(mobSpawner.getSpawnedType());
|
||||
}
|
||||
else if (type == Material.IRON_DOOR || BlockGroup.DOORS.contains(type) || type.equals(Material.SUNFLOWER) || type.equals(Material.LILAC) || type.equals(Material.TALL_GRASS) || type.equals(Material.LARGE_FERN) || type.equals(Material.ROSE_BUSH) || type.equals(Material.PEONY)) { // Double plant
|
||||
else if (type != null && (type == Material.IRON_DOOR || BlockGroup.DOORS.contains(type) || type.equals(Material.SUNFLOWER) || type.equals(Material.LILAC) || type.equals(Material.TALL_GRASS) || type.equals(Material.LARGE_FERN) || type.equals(Material.ROSE_BUSH) || type.equals(Material.PEONY))) { // Double plant
|
||||
if (block.getBlockData() instanceof Bisected) {
|
||||
if (((Bisected) block.getBlockData()).getHalf().equals(Half.TOP)) {
|
||||
if (blockNumber == 5) {
|
||||
@@ -122,7 +162,7 @@ public class Queue {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type.name().endsWith("_BED") && block.getBlockData() instanceof Bed) {
|
||||
else if (type != null && type.name().endsWith("_BED") && block.getBlockData() instanceof Bed) {
|
||||
if (((Bed) block.getBlockData()).getPart().equals(Part.HEAD)) {
|
||||
return;
|
||||
}
|
||||
@@ -151,7 +191,7 @@ public class Queue {
|
||||
replaceType = blockReplaced.getType();
|
||||
replaceData = 0;
|
||||
|
||||
if ((replaceType == Material.IRON_DOOR || BlockGroup.DOORS.contains(replaceType) || replaceType.equals(Material.SUNFLOWER) || replaceType.equals(Material.LILAC) || replaceType.equals(Material.TALL_GRASS) || replaceType.equals(Material.LARGE_FERN) || replaceType.equals(Material.ROSE_BUSH) || replaceType.equals(Material.PEONY)) && replaceData >= 8) { // Double plant top half
|
||||
if (replaceType != null && (replaceType == Material.IRON_DOOR || BlockGroup.DOORS.contains(replaceType) || replaceType.equals(Material.SUNFLOWER) || replaceType.equals(Material.LILAC) || replaceType.equals(Material.TALL_GRASS) || replaceType.equals(Material.LARGE_FERN) || replaceType.equals(Material.ROSE_BUSH) || replaceType.equals(Material.PEONY)) && replaceData >= 8) { // Double plant top half
|
||||
BlockState blockBelow = blockReplaced.getWorld().getBlockAt(blockReplaced.getX(), blockReplaced.getY() - 1, blockReplaced.getZ()).getState();
|
||||
Material belowType = blockBelow.getType();
|
||||
Queue.queueBlockBreak(user, blockBelow, belowType, blockBelow.getBlockData().getAsString(), 0);
|
||||
@@ -185,44 +225,64 @@ public class Queue {
|
||||
queueBlockPlace(user, placed.getBlock().getState(), type, replaced, null, -1, 0, blockData);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}, placed, ticks);
|
||||
}
|
||||
|
||||
protected static void queueBlockPlaceValidate(final String user, final BlockState blockLocation, final Block block, final BlockState blockReplaced, final Material forceT, final int forceD, final int forceData, final String blockData, int ticks) {
|
||||
queueBlockPlaceValidate(user, blockLocation, block, blockReplaced, forceT, forceD, forceData, blockData, ticks, false);
|
||||
}
|
||||
|
||||
protected static void queueBlockPlaceValidate(final String user, final BlockState blockLocation, final Block block, final BlockState blockReplaced, final Material forceT, final int forceD, final int forceData, final String blockData, int ticks, boolean cacheLookup) {
|
||||
Scheduler.scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> {
|
||||
try {
|
||||
Material blockType = block.getType();
|
||||
if (blockType.equals(forceT)) {
|
||||
BlockState replacedBlock = blockReplaced;
|
||||
boolean placed = Objects.equals(blockType, forceT);
|
||||
if (!placed && forceT == Material.WATER) {
|
||||
BlockData currentBlockData = block.getBlockData();
|
||||
if (currentBlockData instanceof Waterlogged) {
|
||||
Waterlogged waterlogged = (Waterlogged) currentBlockData;
|
||||
if (waterlogged.isWaterlogged()) {
|
||||
boolean wasWaterlogged = false;
|
||||
if (blockReplaced != null) {
|
||||
BlockData replacedBlockData = blockReplaced.getBlockData();
|
||||
if (replacedBlockData instanceof Waterlogged) {
|
||||
wasWaterlogged = ((Waterlogged) replacedBlockData).isWaterlogged();
|
||||
}
|
||||
}
|
||||
|
||||
if (!wasWaterlogged) {
|
||||
placed = true;
|
||||
replacedBlock = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (placed) {
|
||||
BlockState blockStateLocation = blockLocation;
|
||||
if (Config.getConfig(blockLocation.getWorld()).BLOCK_MOVEMENT) {
|
||||
if (blockType != null && Objects.equals(blockType, forceT) && Config.getConfig(blockLocation.getWorld()).BLOCK_MOVEMENT) {
|
||||
blockStateLocation = BlockUtil.gravityScan(blockLocation.getLocation(), blockType, user).getState();
|
||||
}
|
||||
|
||||
queueBlockPlace(user, blockStateLocation, blockType, blockReplaced, forceT, forceD, forceData, blockData);
|
||||
if (cacheLookup) {
|
||||
Location cacheLocation = blockStateLocation.getLocation();
|
||||
int worldId = WorldUtils.getWorldId(cacheLocation.getWorld().getName());
|
||||
int unixTimestamp = (int) (System.currentTimeMillis() / 1000L);
|
||||
CacheHandler.lookupCache.put(cacheLocation.getBlockX() + "." + cacheLocation.getBlockY() + "." + cacheLocation.getBlockZ() + "." + worldId, new Object[] { unixTimestamp, user, forceT });
|
||||
}
|
||||
|
||||
queueBlockPlace(user, blockStateLocation, blockType, replacedBlock, forceT, forceD, forceData, blockData);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}, blockLocation.getLocation(), ticks);
|
||||
}
|
||||
|
||||
protected static void queueBlockGravityValidate(final String user, final Location location, final Block block, final Material blockType, int ticks) {
|
||||
Scheduler.scheduleSyncDelayedTask(CoreProtect.getInstance(), () -> {
|
||||
try {
|
||||
Block placementBlock = BlockUtil.gravityScan(location, blockType, user);
|
||||
if (!block.equals(placementBlock)) {
|
||||
queueBlockPlace(user, placementBlock.getState(), blockType, null, blockType, -1, 0, null);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, location, ticks);
|
||||
}
|
||||
|
||||
protected static void queueContainerBreak(String user, Location location, Material type, ItemStack[] oldInventory) {
|
||||
int currentConsumer = Consumer.currentConsumer;
|
||||
int consumerId = Consumer.newConsumerId(currentConsumer);
|
||||
@@ -258,7 +318,7 @@ public class Queue {
|
||||
int consumerId = Consumer.newConsumerId(currentConsumer);
|
||||
addConsumer(currentConsumer, new Object[] { consumerId, Process.ENTITY_KILL, null, 0, null, 0, 0 });
|
||||
Consumer.consumerObjectList.get(currentConsumer).put(consumerId, data);
|
||||
queueStandardData(consumerId, currentConsumer, new String[] { user, null }, new Object[] { location.getBlock().getState(), type, null });
|
||||
queueStandardData(consumerId, currentConsumer, new String[] { user, null }, new Object[] { getBlockLocation(location), type, null });
|
||||
}
|
||||
|
||||
protected static void queueEntitySpawn(String user, BlockState block, EntityType type, int data) {
|
||||
@@ -322,7 +382,7 @@ public class Queue {
|
||||
int currentConsumer = Consumer.currentConsumer;
|
||||
int consumerId = Consumer.newConsumerId(currentConsumer);
|
||||
addConsumer(currentConsumer, new Object[] { consumerId, Process.PLAYER_KILL, null, 0, null, 0, 0, null });
|
||||
queueStandardData(consumerId, currentConsumer, new String[] { user, null }, new Object[] { location.getBlock().getState(), player });
|
||||
queueStandardData(consumerId, currentConsumer, new String[] { user, null }, new Object[] { getBlockLocation(location), player });
|
||||
}
|
||||
|
||||
protected static void queuePlayerLogin(Player player, int time, int configSessions, int configUsernames) {
|
||||
|
||||
@@ -18,11 +18,11 @@ class BlockBreakProcess {
|
||||
if (object instanceof BlockState) {
|
||||
BlockState block = (BlockState) object;
|
||||
List<Object> meta = BlockUtils.processMeta(block);
|
||||
if (block instanceof Skull) {
|
||||
if (block instanceof Skull && blockType != null && blockType.equals(block.getType())) {
|
||||
SkullBreakLogger.log(preparedStmt, preparedStmtSkulls, batchCount, user, block);
|
||||
}
|
||||
else {
|
||||
BlockBreakLogger.log(preparedStmt, batchCount, user, block.getLocation(), MaterialUtils.getBlockId(blockType), blockDataId, meta, block.getBlockData().getAsString(), blockData);
|
||||
BlockBreakLogger.log(preparedStmt, batchCount, user, block.getLocation(), MaterialUtils.getBlockId(blockType), blockDataId, meta, blockData, blockData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ class BlockPlaceProcess {
|
||||
if (object instanceof BlockState) {
|
||||
BlockState block = (BlockState) object;
|
||||
List<Object> meta = BlockUtils.processMeta(block);
|
||||
if (blockType.equals(Material.SKELETON_SKULL) || blockType.equals(Material.SKELETON_WALL_SKULL) || blockType.equals(Material.WITHER_SKELETON_SKULL) || blockType.equals(Material.WITHER_SKELETON_WALL_SKULL) || blockType.equals(Material.ZOMBIE_HEAD) || blockType.equals(Material.ZOMBIE_WALL_HEAD) || blockType.equals(Material.PLAYER_HEAD) || blockType.equals(Material.PLAYER_WALL_HEAD) || blockType.equals(Material.CREEPER_HEAD) || blockType.equals(Material.CREEPER_WALL_HEAD) || blockType.equals(Material.DRAGON_HEAD) || blockType.equals(Material.DRAGON_WALL_HEAD)) {
|
||||
if (blockType != null && (blockType.equals(Material.SKELETON_SKULL) || blockType.equals(Material.SKELETON_WALL_SKULL) || blockType.equals(Material.WITHER_SKELETON_SKULL) || blockType.equals(Material.WITHER_SKELETON_WALL_SKULL) || blockType.equals(Material.ZOMBIE_HEAD) || blockType.equals(Material.ZOMBIE_WALL_HEAD) || blockType.equals(Material.PLAYER_HEAD) || blockType.equals(Material.PLAYER_WALL_HEAD) || blockType.equals(Material.CREEPER_HEAD) || blockType.equals(Material.CREEPER_WALL_HEAD) || blockType.equals(Material.DRAGON_HEAD) || blockType.equals(Material.DRAGON_WALL_HEAD))) {
|
||||
SkullPlaceLogger.log(preparedStmt, preparedStmtSkulls, batchCount, user, block, MaterialUtils.getBlockId(replaceType), replaceData);
|
||||
}
|
||||
else if (forceData == 1) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.database.logger.ContainerBreakLogger;
|
||||
import net.coreprotect.utility.HopperTransactionUtils;
|
||||
|
||||
class ContainerBreakProcess {
|
||||
|
||||
@@ -18,7 +19,8 @@ class ContainerBreakProcess {
|
||||
Map<Integer, ItemStack[]> containers = Consumer.consumerContainers.get(processId);
|
||||
if (containers.get(id) != null) {
|
||||
ItemStack[] container = containers.get(id);
|
||||
ContainerBreakLogger.log(preparedStmt, batchCount, user, location, type, container);
|
||||
String transactionId = HopperTransactionUtils.getTransactionId(location);
|
||||
HopperTransactionUtils.synchronizeTransaction(transactionId, () -> ContainerBreakLogger.log(preparedStmt, batchCount, user, location, type, container));
|
||||
containers.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,13 +2,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;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -17,75 +13,88 @@ import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.logger.ContainerLogger;
|
||||
import net.coreprotect.utility.HopperTransactionUtils;
|
||||
|
||||
class ContainerTransactionProcess {
|
||||
|
||||
static void process(PreparedStatement preparedStmtContainer, PreparedStatement preparedStmtItems, int batchCount, int processId, int id, Material type, int forceData, String user, Object object) {
|
||||
if (object instanceof Location) {
|
||||
Location location = (Location) object;
|
||||
Map<Integer, Object> inventories = Consumer.consumerInventories.get(processId);
|
||||
if (inventories.get(id) != null) {
|
||||
Object inventory = inventories.get(id);
|
||||
String transactingChestId = location.getWorld().getUID().toString() + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
String loggingChestId = user.toLowerCase(Locale.ROOT) + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
if (ConfigHandler.loggingChest.get(loggingChestId) != null) {
|
||||
int current_chest = ConfigHandler.loggingChest.get(loggingChestId);
|
||||
if (ConfigHandler.oldContainer.get(loggingChestId) == null) {
|
||||
return;
|
||||
}
|
||||
int force_size = 0;
|
||||
if (ConfigHandler.forceContainer.get(loggingChestId) != null) {
|
||||
force_size = ConfigHandler.forceContainer.get(loggingChestId).size();
|
||||
}
|
||||
if (current_chest == forceData || force_size > 0) { // This prevents client side chest sorting mods from messing things up.
|
||||
ContainerLogger.log(preparedStmtContainer, preparedStmtItems, batchCount, user, type, inventory, location);
|
||||
List<ItemStack[]> old = ConfigHandler.oldContainer.get(loggingChestId);
|
||||
if (old.size() == 0) {
|
||||
ConfigHandler.oldContainer.remove(loggingChestId);
|
||||
ConfigHandler.loggingChest.remove(loggingChestId);
|
||||
ConfigHandler.transactingChest.remove(transactingChestId);
|
||||
}
|
||||
}
|
||||
else if (loggingChestId.startsWith("#hopper")) {
|
||||
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;
|
||||
maxInventorySize = checkInventory.getSize() * checkInventory.getMaxStackSize();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// use default of 5,346
|
||||
}
|
||||
if (!(object instanceof Location)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loopCount > maxInventorySize) {
|
||||
ItemStack[] destinationContents = null;
|
||||
ItemStack movedItem = null;
|
||||
Location location = (Location) object;
|
||||
Map<Integer, Object> inventories = Consumer.consumerInventories.get(processId);
|
||||
Object inventory = inventories.remove(id);
|
||||
if (inventory == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String hopperPush = "#hopper-push." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
Object[] hopperPushData = ConfigHandler.hopperSuccess.remove(hopperPush);
|
||||
if (hopperPushData != null) {
|
||||
destinationContents = (ItemStack[]) hopperPushData[0];
|
||||
movedItem = (ItemStack) hopperPushData[1];
|
||||
}
|
||||
String transactingChestId = HopperTransactionUtils.getTransactionId(location);
|
||||
String loggingChestIdSuffix = HopperTransactionUtils.getLoggingIdSuffix(location);
|
||||
String loggingChestId = HopperTransactionUtils.getLoggingId(user, loggingChestIdSuffix);
|
||||
HopperTransactionUtils.synchronizeTransaction(transactingChestId,
|
||||
() -> processTransaction(preparedStmtContainer, preparedStmtItems, batchCount, type, forceData, user, inventory, location, transactingChestId, loggingChestIdSuffix, loggingChestId));
|
||||
}
|
||||
|
||||
if (destinationContents != null) {
|
||||
Set<ItemStack> movedItems = new HashSet<>();
|
||||
Object[] lastAbort = ConfigHandler.hopperAbort.get(hopperPush);
|
||||
if (lastAbort != null && Arrays.equals(destinationContents, (ItemStack[]) lastAbort[1])) {
|
||||
((Set<?>) lastAbort[0]).forEach(itemStack -> movedItems.add((ItemStack) itemStack));
|
||||
}
|
||||
movedItems.add(movedItem);
|
||||
ConfigHandler.hopperAbort.put(hopperPush, new Object[] { movedItems, destinationContents });
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void processTransaction(PreparedStatement preparedStmtContainer, PreparedStatement preparedStmtItems, int batchCount, Material type, int forceData, String user, Object inventory,
|
||||
Location location, String transactingChestId, String loggingChestIdSuffix, String loggingChestId) {
|
||||
if (ConfigHandler.loggingChest.get(loggingChestId) == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int current_chest = ConfigHandler.loggingChest.get(loggingChestId);
|
||||
if (ConfigHandler.oldContainer.get(loggingChestId) == null) {
|
||||
clearContainerTransaction(transactingChestId, loggingChestIdSuffix, loggingChestId);
|
||||
return;
|
||||
}
|
||||
int force_size = Queue.getForceContainerSize(loggingChestId);
|
||||
if (current_chest == forceData || force_size > 0) { // This prevents client side chest sorting mods from messing things up.
|
||||
ContainerLogger.log(preparedStmtContainer, preparedStmtItems, batchCount, user, type, inventory, location);
|
||||
List<ItemStack[]> old = ConfigHandler.oldContainer.get(loggingChestId);
|
||||
if (old == null || old.isEmpty()) {
|
||||
clearContainerTransaction(transactingChestId, loggingChestIdSuffix, loggingChestId);
|
||||
}
|
||||
}
|
||||
else if (loggingChestId.startsWith("#hopper")) {
|
||||
if (force_size == 0 && ConfigHandler.oldContainer.getOrDefault(loggingChestId, Collections.synchronizedList(new ArrayList<>())).size() == 1
|
||||
&& HopperTransactionUtils.pendingDeltaCount(transactingChestId) == 0) {
|
||||
int loopCount = ConfigHandler.loggingChest.getOrDefault(loggingChestId, 0);
|
||||
int maxInventorySize = (99 * 54);
|
||||
try {
|
||||
Inventory checkInventory = (Inventory) inventory;
|
||||
maxInventorySize = checkInventory.getSize() * checkInventory.getMaxStackSize();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// use default of 5,346
|
||||
}
|
||||
|
||||
if (loopCount > maxInventorySize) {
|
||||
ItemStack[] destinationContents = null;
|
||||
ItemStack movedItem = null;
|
||||
|
||||
String hopperPush = HopperTransactionUtils.getHopperPushId(location);
|
||||
Object[] hopperPushData = ConfigHandler.hopperSuccess.remove(hopperPush);
|
||||
if (hopperPushData != null) {
|
||||
destinationContents = (ItemStack[]) hopperPushData[0];
|
||||
movedItem = (ItemStack) hopperPushData[1];
|
||||
}
|
||||
|
||||
if (destinationContents != null) {
|
||||
Object[] lastAbort = ConfigHandler.hopperAbort.get(hopperPush);
|
||||
ConfigHandler.hopperAbort.put(hopperPush, HopperTransactionUtils.createAbortState(lastAbort, destinationContents, movedItem));
|
||||
}
|
||||
}
|
||||
inventories.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void clearContainerTransaction(String transactionId, String locationSuffix, String loggingId) {
|
||||
ConfigHandler.oldContainer.remove(loggingId);
|
||||
ConfigHandler.removeOldContainerViewer(locationSuffix, loggingId);
|
||||
ConfigHandler.loggingChest.remove(loggingId);
|
||||
Queue.removeForceContainer(loggingId);
|
||||
HopperTransactionUtils.removeOwner(transactionId, loggingId);
|
||||
}
|
||||
}
|
||||
@@ -4,27 +4,45 @@ import java.sql.PreparedStatement;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.database.logger.EntityKillLogger;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.Util;
|
||||
|
||||
class EntityKillProcess {
|
||||
|
||||
static void process(PreparedStatement preparedStmt, PreparedStatement preparedStmtEntities, int batchCount, int processId, int id, Object object, String user) {
|
||||
if (object instanceof Object[]) {
|
||||
BlockState block = (BlockState) ((Object[]) object)[0];
|
||||
EntityType type = (EntityType) ((Object[]) object)[1];
|
||||
Object[] values = (Object[]) object;
|
||||
if (values.length <= 1 || !isLocationData(values[0]) || !(values[1] instanceof EntityType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = getLocation(values[0]);
|
||||
EntityType type = (EntityType) values[1];
|
||||
Map<Integer, List<Object>> objectLists = Consumer.consumerObjectList.get(processId);
|
||||
if (objectLists.get(id) != null) {
|
||||
if (objectLists != null && objectLists.get(id) != null) {
|
||||
List<Object> objectList = objectLists.get(id);
|
||||
int entityId = EntityUtils.getEntityId(type);
|
||||
EntityKillLogger.log(preparedStmt, preparedStmtEntities, batchCount, user, block, objectList, entityId);
|
||||
EntityKillLogger.log(preparedStmt, preparedStmtEntities, batchCount, user, location, objectList, entityId);
|
||||
objectLists.remove(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLocationData(Object value) {
|
||||
return value instanceof Location || value instanceof BlockState;
|
||||
}
|
||||
|
||||
private static Location getLocation(Object value) {
|
||||
if (value instanceof Location) {
|
||||
return ((Location) value).clone();
|
||||
}
|
||||
|
||||
BlockState block = (BlockState) value;
|
||||
return new Location(block.getWorld(), block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package net.coreprotect.consumer.process;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockState;
|
||||
|
||||
import net.coreprotect.database.logger.PlayerKillLogger;
|
||||
@@ -10,9 +11,27 @@ class PlayerKillProcess {
|
||||
|
||||
static void process(PreparedStatement preparedStmt, int batchCount, int id, Object object, String user) {
|
||||
if (object instanceof Object[]) {
|
||||
BlockState block = (BlockState) ((Object[]) object)[0];
|
||||
String player = (String) ((Object[]) object)[1];
|
||||
PlayerKillLogger.log(preparedStmt, batchCount, user, block, player);
|
||||
Object[] values = (Object[]) object;
|
||||
if (values.length <= 1 || !isLocationData(values[0]) || !(values[1] instanceof String)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Location location = getLocation(values[0]);
|
||||
String player = (String) values[1];
|
||||
PlayerKillLogger.log(preparedStmt, batchCount, user, location, player);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isLocationData(Object value) {
|
||||
return value instanceof Location || value instanceof BlockState;
|
||||
}
|
||||
|
||||
private static Location getLocation(Object value) {
|
||||
if (value instanceof Location) {
|
||||
return ((Location) value).clone();
|
||||
}
|
||||
|
||||
BlockState block = (BlockState) value;
|
||||
return new Location(block.getWorld(), block.getX(), block.getY(), block.getZ());
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.Location;
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.database.logger.PlayerSessionLogger;
|
||||
import net.coreprotect.database.logger.UsernameLogger;
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
|
||||
class PlayerLoginProcess {
|
||||
|
||||
@@ -20,7 +21,7 @@ class PlayerLoginProcess {
|
||||
Location location = (Location) object;
|
||||
UsernameLogger.log(connection, user, uuid, configUsernames, time);
|
||||
if (configSessions == 1) {
|
||||
PlayerSessionLogger.log(preparedStmt, batchCount, user, location, time, 1);
|
||||
PlayerSessionLogger.log(preparedStmt, batchCount, user, location, time, SessionActions.LOGIN);
|
||||
}
|
||||
strings.remove(id);
|
||||
}
|
||||
|
||||
@@ -5,13 +5,14 @@ import java.sql.PreparedStatement;
|
||||
import org.bukkit.Location;
|
||||
|
||||
import net.coreprotect.database.logger.PlayerSessionLogger;
|
||||
import net.coreprotect.model.action.SessionActions;
|
||||
|
||||
class PlayerLogoutProcess {
|
||||
|
||||
static void process(PreparedStatement preparedStmt, int batchCount, Object object, int time, String user) {
|
||||
if (object instanceof Location) {
|
||||
Location location = (Location) object;
|
||||
PlayerSessionLogger.log(preparedStmt, batchCount, user, location, time, 0);
|
||||
PlayerSessionLogger.log(preparedStmt, batchCount, user, location, time, SessionActions.LOGOUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.model.rollback.RollbackUpdateTargets;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class Process {
|
||||
|
||||
@@ -64,7 +66,7 @@ public class Process {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,19 +169,19 @@ public class Process {
|
||||
StructureGrowthProcess.process(statement, preparedStmtBlocks, i, processId, id, user, object, forceData);
|
||||
break;
|
||||
case Process.ROLLBACK_UPDATE:
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, 0);
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, RollbackUpdateTargets.BLOCK);
|
||||
break;
|
||||
case Process.CONTAINER_ROLLBACK_UPDATE:
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, 1);
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, RollbackUpdateTargets.CONTAINER);
|
||||
break;
|
||||
case Process.INVENTORY_ROLLBACK_UPDATE:
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, 2);
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, RollbackUpdateTargets.INVENTORY_ITEM);
|
||||
break;
|
||||
case Process.INVENTORY_CONTAINER_ROLLBACK_UPDATE:
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, 3);
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, RollbackUpdateTargets.INVENTORY_CONTAINER);
|
||||
break;
|
||||
case Process.BLOCK_INVENTORY_ROLLBACK_UPDATE:
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, 4);
|
||||
RollbackUpdateProcess.process(statement, processId, id, forceData, RollbackUpdateTargets.BLOCK_INVENTORY);
|
||||
break;
|
||||
case Process.WORLD_INSERT:
|
||||
WorldInsertProcess.process(preparedStmtWorlds, i, statement, object, forceData);
|
||||
@@ -247,7 +249,7 @@ public class Process {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -280,7 +282,7 @@ public class Process {
|
||||
consumerData.clear();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
Consumer.consumer_id.put(processId, new Integer[] { 0, 0 });
|
||||
@@ -306,7 +308,7 @@ public class Process {
|
||||
Database.commitTransaction(statement, Config.getGlobal().MYSQL);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
package net.coreprotect.consumer.process;
|
||||
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.model.rollback.RollbackUpdateTargets;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
|
||||
class RollbackUpdateProcess {
|
||||
@@ -14,13 +18,19 @@ class RollbackUpdateProcess {
|
||||
Map<Integer, List<Object[]>> updateLists = Consumer.consumerObjectArrayList.get(processId);
|
||||
if (updateLists.get(id) != null) {
|
||||
List<Object[]> list = updateLists.get(id);
|
||||
boolean inventoryState = RollbackUpdateTargets.usesInventoryRollbackState(table);
|
||||
Map<Integer, List<Long>> rowIdsByValue = new HashMap<>();
|
||||
for (Object[] listRow : list) {
|
||||
long rowid = (Long) listRow[0];
|
||||
int rolledBack = (Integer) listRow[9];
|
||||
if (MaterialUtils.rolledBack(rolledBack, (table == 2 || table == 3 || table == 4)) == action) { // 1 = restore, 0 = rollback
|
||||
Database.performUpdate(statement, rowid, rolledBack, table);
|
||||
if (MaterialUtils.rolledBack(rolledBack, inventoryState) == action) { // 1 = restore, 0 = rollback
|
||||
int toggledValue = MaterialUtils.toggleRolledBack(rolledBack, inventoryState);
|
||||
rowIdsByValue.computeIfAbsent(toggledValue, key -> new ArrayList<>()).add(rowid);
|
||||
}
|
||||
}
|
||||
for (Entry<Integer, List<Long>> entry : rowIdsByValue.entrySet()) {
|
||||
Database.performRolledBackUpdate(statement, entry.getKey(), entry.getValue(), table);
|
||||
}
|
||||
updateLists.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class BlockLookup {
|
||||
|
||||
@@ -48,7 +49,7 @@ public class BlockLookup {
|
||||
results.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -83,7 +84,7 @@ public class BlockLookup {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -111,7 +112,7 @@ public class BlockLookup {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.bukkit.entity.ArmorStand;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.ItemFrame;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
@@ -24,12 +25,14 @@ 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.listener.player.InventoryChangeListener;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.thread.Scheduler;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ContainerRollback extends Rollback {
|
||||
|
||||
@@ -90,6 +93,9 @@ public class ContainerRollback extends Rollback {
|
||||
|
||||
int modifyCount = 0;
|
||||
if (container != null) {
|
||||
if (container instanceof Inventory) {
|
||||
InventoryChangeListener.flushPendingContainer((Inventory) container, location);
|
||||
}
|
||||
for (Object[] lookupRow : lookupList) {
|
||||
// int unixtimestamp = (int) (System.currentTimeMillis() / 1000L);
|
||||
// int rowId = lookupRow[0];
|
||||
@@ -147,7 +153,7 @@ public class ContainerRollback extends Rollback {
|
||||
ConfigHandler.rollbackHash.put(finalUserString, new int[] { itemCount, modifyCount, entityCount, 1, 1 });
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}, location, 0);
|
||||
@@ -184,7 +190,7 @@ public class ContainerRollback extends Rollback {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -23,11 +24,13 @@ import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.consumer.process.Process;
|
||||
import net.coreprotect.language.Phrase;
|
||||
import net.coreprotect.listener.player.InventoryChangeListener;
|
||||
import net.coreprotect.model.BlockGroup;
|
||||
import net.coreprotect.model.rollback.RollbackUpdateTargets;
|
||||
import net.coreprotect.utility.Chat;
|
||||
import net.coreprotect.utility.Color;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class Database extends Queue {
|
||||
|
||||
@@ -46,6 +49,8 @@ public class Database extends Queue {
|
||||
public static final int BLOCKDATA = 12;
|
||||
public static final int ITEM = 13;
|
||||
|
||||
private static final int ROLLED_BACK_UPDATE_BATCH_SIZE = 1000;
|
||||
|
||||
private static final Map<Integer, String> SQL_QUERIES = new HashMap<>();
|
||||
|
||||
static {
|
||||
@@ -78,7 +83,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +107,7 @@ public class Database extends Queue {
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +130,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,21 +139,23 @@ public class Database extends Queue {
|
||||
}
|
||||
|
||||
public static void containerBreakCheck(String user, Material type, Object container, ItemStack[] contents, Location location) {
|
||||
if (BlockGroup.CONTAINERS.contains(type) && !BlockGroup.SHULKER_BOXES.contains(type)) {
|
||||
if (BlockGroup.CONTAINERS.contains(type)) {
|
||||
if (Config.getConfig(location.getWorld()).ITEM_TRANSACTIONS) {
|
||||
try {
|
||||
if (contents == null) {
|
||||
contents = ItemUtils.getContainerContents(type, container, location);
|
||||
}
|
||||
if (contents != null) {
|
||||
List<ItemStack[]> forceList = new ArrayList<>();
|
||||
forceList.add(ItemUtils.getContainerState(contents));
|
||||
ConfigHandler.forceContainer.put(user.toLowerCase(Locale.ROOT) + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ(), forceList);
|
||||
Queue.queueContainerBreak(user, location, type, contents);
|
||||
if (BlockGroup.SHULKER_BOXES.contains(type)) {
|
||||
InventoryChangeListener.flushPendingContainer(location, contents);
|
||||
}
|
||||
else {
|
||||
InventoryChangeListener.queueContainerBreak(user, location, type, contents);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +184,7 @@ public class Database extends Queue {
|
||||
catch (Exception e) {
|
||||
ConfigHandler.databaseReachable = false;
|
||||
Chat.sendConsoleMessage(Color.RED + "[CoreProtect] " + Phrase.build(Phrase.MYSQL_UNAVAILABLE));
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -202,7 +209,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return connection;
|
||||
@@ -216,25 +223,39 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void performUpdate(Statement statement, long id, int rb, int table) {
|
||||
public static void performRolledBackUpdate(Statement statement, int rolledBack, List<Long> rowIds, int table) {
|
||||
String tableName;
|
||||
if (RollbackUpdateTargets.updatesContainerTable(table)) {
|
||||
tableName = "container";
|
||||
}
|
||||
else if (RollbackUpdateTargets.updatesItemTable(table)) {
|
||||
tableName = "item";
|
||||
}
|
||||
else {
|
||||
tableName = "block";
|
||||
}
|
||||
|
||||
try {
|
||||
int rolledBack = MaterialUtils.toggleRolledBack(rb, (table == 2 || table == 3 || table == 4)); // co_item, co_container, co_block
|
||||
if (table == 1 || table == 3) {
|
||||
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "container SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
|
||||
}
|
||||
else if (table == 2) {
|
||||
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "item SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
|
||||
}
|
||||
else {
|
||||
statement.executeUpdate("UPDATE " + ConfigHandler.prefix + "block SET rolled_back='" + rolledBack + "' WHERE rowid='" + id + "'");
|
||||
int listSize = rowIds.size();
|
||||
for (int startIndex = 0; startIndex < listSize; startIndex += ROLLED_BACK_UPDATE_BATCH_SIZE) {
|
||||
int endIndex = Math.min(startIndex + ROLLED_BACK_UPDATE_BATCH_SIZE, listSize);
|
||||
StringBuilder query = new StringBuilder("UPDATE " + ConfigHandler.prefix + tableName + " SET rolled_back='" + rolledBack + "' WHERE rowid IN(");
|
||||
for (int index = startIndex; index < endIndex; index++) {
|
||||
if (index > startIndex) {
|
||||
query.append(",");
|
||||
}
|
||||
query.append(rowIds.get(index).longValue());
|
||||
}
|
||||
query.append(")");
|
||||
statement.executeUpdate(query.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +269,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return preparedStatement;
|
||||
@@ -270,7 +291,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return preparedStatement;
|
||||
@@ -302,7 +323,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +347,7 @@ public class Database extends Queue {
|
||||
if (connection != null) {
|
||||
Statement statement = connection.createStatement();
|
||||
createMySQLTableStructures(prefix, statement);
|
||||
createMySQLIndexes(prefix, statement, purge);
|
||||
if (!purge && forceConnection == null) {
|
||||
initializeTables(prefix, statement);
|
||||
}
|
||||
@@ -334,7 +356,7 @@ public class Database extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
if (!success && forceConnection == null) {
|
||||
Config.getGlobal().MYSQL = false;
|
||||
@@ -362,11 +384,11 @@ public class Database extends Queue {
|
||||
|
||||
// Container
|
||||
index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)";
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, amount int, metadata blob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "container(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data int, amount int, metadata mediumblob, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
|
||||
// Item
|
||||
index = ", INDEX(wid,x,z,time), INDEX(user,time), INDEX(type,time)";
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data blob, amount int, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "item(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, user int, wid int, x int, y int, z int, type int, data mediumblob, amount int, action tinyint, rolled_back tinyint" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
|
||||
// Database lock
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "database_lock(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),status tinyint,time int) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
@@ -395,7 +417,7 @@ public class Database extends Queue {
|
||||
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");
|
||||
|
||||
// Skull
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "skull(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid), time int, owner varchar(255), skin varchar(255)) 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), skin text) ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
|
||||
// User
|
||||
index = ", INDEX(user), INDEX(uuid)";
|
||||
@@ -413,6 +435,103 @@ public class Database extends Queue {
|
||||
statement.executeUpdate("CREATE TABLE IF NOT EXISTS " + prefix + "world(rowid int NOT NULL AUTO_INCREMENT,PRIMARY KEY(rowid),id int,world varchar(255)" + index + ") ENGINE=InnoDB DEFAULT CHARACTER SET utf8mb4");
|
||||
}
|
||||
|
||||
private static void createMySQLIndexes(String prefix, Statement statement, boolean purge) {
|
||||
try {
|
||||
ensureMySQLIndex(statement, prefix + "block", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "block", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "block", "type", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "container", "type", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "wid", "x", "z", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "user", "time");
|
||||
ensureMySQLIndex(statement, prefix + "item", "type", "time");
|
||||
}
|
||||
catch (Exception e) {
|
||||
Chat.console(Phrase.build(Phrase.DATABASE_INDEX_ERROR));
|
||||
if (purge) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ensureMySQLIndex(Statement statement, String tableName, String... columns) throws SQLException {
|
||||
if (hasMySQLIndex(statement, tableName, columns)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String indexName = createMySQLIndexName(tableName, columns);
|
||||
String indexColumns = String.join(",", columns);
|
||||
statement.executeUpdate("CREATE INDEX " + indexName + " ON " + tableName + "(" + indexColumns + ")");
|
||||
}
|
||||
|
||||
private static boolean hasMySQLIndex(Statement statement, String tableName, String... columns) {
|
||||
Map<String, TreeMap<Integer, String>> indexData = new HashMap<>();
|
||||
|
||||
try (ResultSet resultSet = statement.executeQuery("SHOW INDEX FROM " + tableName)) {
|
||||
while (resultSet.next()) {
|
||||
String keyName = resultSet.getString("Key_name");
|
||||
int sequence = resultSet.getInt("Seq_in_index");
|
||||
String columnName = resultSet.getString("Column_name");
|
||||
if (keyName == null || columnName == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
indexData.computeIfAbsent(keyName, key -> new TreeMap<>()).put(sequence, columnName.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<String> expected = new ArrayList<>(columns.length);
|
||||
for (String column : columns) {
|
||||
expected.add(column.toLowerCase(Locale.ROOT));
|
||||
}
|
||||
|
||||
for (TreeMap<Integer, String> indexColumns : indexData.values()) {
|
||||
if (indexColumns.size() < expected.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean matchesPrefix = true;
|
||||
int position = 0;
|
||||
for (String column : indexColumns.values()) {
|
||||
if (!column.equals(expected.get(position))) {
|
||||
matchesPrefix = false;
|
||||
break;
|
||||
}
|
||||
position++;
|
||||
if (position == expected.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (matchesPrefix && position == expected.size()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String createMySQLIndexName(String tableName, String... columns) {
|
||||
String normalizedTable = tableName.replaceAll("[^A-Za-z0-9_]", "_");
|
||||
String joinedColumns = String.join("_", columns);
|
||||
String candidate = normalizedTable + "_" + joinedColumns + "_idx";
|
||||
if (candidate.length() <= 64) {
|
||||
return candidate;
|
||||
}
|
||||
|
||||
String hash = Integer.toHexString(candidate.hashCode());
|
||||
int maxPrefixLength = 64 - (hash.length() + 1);
|
||||
if (maxPrefixLength < 1) {
|
||||
maxPrefixLength = 1;
|
||||
}
|
||||
|
||||
return candidate.substring(0, maxPrefixLength) + "_" + hash;
|
||||
}
|
||||
|
||||
private static void createSQLiteTables(String prefix, boolean forcePrefix, Connection forceConnection, boolean purge) {
|
||||
try (Connection connection = (forceConnection != null ? forceConnection : Database.getConnection(true, 0))) {
|
||||
Statement statement = connection.createStatement();
|
||||
@@ -438,7 +557,7 @@ public class Database extends Queue {
|
||||
statement.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -550,7 +669,7 @@ public class Database extends Queue {
|
||||
catch (Exception e) {
|
||||
Chat.console(Phrase.build(Phrase.DATABASE_INDEX_ERROR));
|
||||
if (purge) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.bukkit.command.CommandSender;
|
||||
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class Lookup extends Queue {
|
||||
|
||||
@@ -35,7 +36,7 @@ public class Lookup extends Queue {
|
||||
results.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
Consumer.isPaused = false;
|
||||
@@ -51,7 +52,7 @@ public class Lookup extends Queue {
|
||||
newList = LookupConverter.convertRawLookup(statement, lookupList);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return newList;
|
||||
@@ -65,7 +66,7 @@ public class Lookup extends Queue {
|
||||
newList = LookupConverter.convertRawLookup(statement, lookupList);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return newList;
|
||||
|
||||
@@ -8,6 +8,7 @@ import java.util.List;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class LookupConverter {
|
||||
|
||||
@@ -54,7 +55,7 @@ public class LookupConverter {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
newList.add(results);
|
||||
|
||||
@@ -18,25 +18,28 @@ import net.coreprotect.config.Config;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Consumer;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.logger.ItemLogger;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.listener.channel.PluginChannelHandshakeListener;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.model.action.SignActions;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.EntityUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class LookupRaw extends Queue {
|
||||
|
||||
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);
|
||||
invalidRollbackActions.add(LookupActions.INTERACTION);
|
||||
|
||||
if (!Config.getGlobal().ROLLBACK_ENTITIES && !actionList.contains(3)) {
|
||||
invalidRollbackActions.add(3);
|
||||
if (!Config.getGlobal().ROLLBACK_ENTITIES && !actionList.contains(LookupActions.ENTITY_KILL)) {
|
||||
invalidRollbackActions.add(LookupActions.ENTITY_KILL);
|
||||
}
|
||||
|
||||
if (actionList.contains(4) && actionList.contains(11)) {
|
||||
if (LookupActions.isInventoryLookup(actionList)) {
|
||||
invalidRollbackActions.clear();
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ public class LookupRaw extends Queue {
|
||||
ResultSet results = rawLookupResultSet(statement, user, checkUuids, checkUsers, restrictList, excludeList, excludeUserList, actionList, location, radius, rowData, startTime, endTime, limitOffset, limitCount, restrictWorld, lookup, false);
|
||||
|
||||
while (results.next()) {
|
||||
if (actionList.contains(6) || actionList.contains(7)) {
|
||||
if (actionList.contains(LookupActions.CHAT) || actionList.contains(LookupActions.COMMAND)) {
|
||||
long resultId = results.getLong("id");
|
||||
int resultTime = results.getInt("time");
|
||||
int resultUserId = results.getInt("user");
|
||||
@@ -66,7 +69,7 @@ public class LookupRaw extends Queue {
|
||||
}
|
||||
list.add(dataArray);
|
||||
}
|
||||
else if (actionList.contains(8)) {
|
||||
else if (actionList.contains(LookupActions.SESSION)) {
|
||||
long resultId = results.getLong("id");
|
||||
int resultTime = results.getInt("time");
|
||||
int resultUserId = results.getInt("user");
|
||||
@@ -79,7 +82,7 @@ public class LookupRaw extends Queue {
|
||||
Object[] dataArray = new Object[] { resultId, resultTime, resultUserId, resultWorldId, resultX, resultY, resultZ, resultAction };
|
||||
list.add(dataArray);
|
||||
}
|
||||
else if (actionList.contains(9)) {
|
||||
else if (actionList.contains(LookupActions.USERNAME)) {
|
||||
long resultId = results.getLong("id");
|
||||
int resultTime = results.getInt("time");
|
||||
String resultUuid = results.getString("uuid");
|
||||
@@ -88,7 +91,7 @@ public class LookupRaw extends Queue {
|
||||
Object[] dataArray = new Object[] { resultId, resultTime, resultUuid, resultUser };
|
||||
list.add(dataArray);
|
||||
}
|
||||
else if (actionList.contains(10)) {
|
||||
else if (actionList.contains(LookupActions.SIGN)) {
|
||||
long resultId = results.getLong("id");
|
||||
int resultTime = results.getInt("time");
|
||||
int resultUserId = results.getInt("user");
|
||||
@@ -177,7 +180,7 @@ public class LookupRaw extends Queue {
|
||||
int resultWorldId = results.getInt("wid");
|
||||
|
||||
boolean hasTbl = false;
|
||||
if ((lookup && actionList.size() == 0) || actionList.contains(4) || actionList.contains(5) || actionList.contains(11)) {
|
||||
if ((lookup && actionList.size() == 0) || actionList.contains(LookupActions.CONTAINER) || actionList.contains(5) || actionList.contains(LookupActions.ITEM)) {
|
||||
resultData = results.getInt("data");
|
||||
resultAmount = results.getInt("amount");
|
||||
resultMeta = results.getBytes("metadata");
|
||||
@@ -212,7 +215,7 @@ public class LookupRaw extends Queue {
|
||||
results.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
Consumer.isPaused = false;
|
||||
@@ -223,12 +226,12 @@ public class LookupRaw extends Queue {
|
||||
ResultSet results = null;
|
||||
|
||||
try {
|
||||
List<Integer> validActions = Arrays.asList(0, 1, 2, 3);
|
||||
List<Integer> validActions = Arrays.asList(LookupActions.BLOCK_BREAK, LookupActions.BLOCK_PLACE, LookupActions.INTERACTION, LookupActions.ENTITY_KILL);
|
||||
if (radius != null) {
|
||||
restrictWorld = true;
|
||||
}
|
||||
|
||||
boolean inventoryQuery = (actionList.contains(4) && actionList.contains(11));
|
||||
boolean inventoryQuery = LookupActions.isInventoryLookup(actionList);
|
||||
boolean validAction = false;
|
||||
String queryBlock = "";
|
||||
String queryEntity = "";
|
||||
@@ -314,6 +317,15 @@ public class LookupRaw extends Queue {
|
||||
includeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false));
|
||||
}
|
||||
}
|
||||
else if (restrictTarget instanceof String) {
|
||||
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
|
||||
if (includeListMaterial.length() == 0) {
|
||||
includeListMaterial = includeListMaterial.append(blockId);
|
||||
}
|
||||
else {
|
||||
includeListMaterial.append(",").append(blockId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
includeBlock = includeListMaterial.toString();
|
||||
@@ -351,6 +363,17 @@ public class LookupRaw extends Queue {
|
||||
excludeListEntity.append(",").append(EntityUtils.getEntityId(targetName, false));
|
||||
}
|
||||
}
|
||||
else if (restrictTarget instanceof String) {
|
||||
int blockId = MaterialUtils.getBlockId((String) restrictTarget, false);
|
||||
if (blockId > -1) {
|
||||
if (excludeListMaterial.length() == 0) {
|
||||
excludeListMaterial = excludeListMaterial.append(blockId);
|
||||
}
|
||||
else {
|
||||
excludeListMaterial.append(",").append(blockId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
excludeBlock = excludeListMaterial.toString();
|
||||
@@ -378,13 +401,13 @@ public class LookupRaw extends Queue {
|
||||
}
|
||||
|
||||
// Specify actions to exclude from a:item
|
||||
if ((lookup && actionList.size() == 0) || (actionList.contains(11) && actionList.size() == 1)) {
|
||||
if ((lookup && actionList.size() == 0) || (actionList.contains(LookupActions.ITEM) && actionList.size() == 1)) {
|
||||
StringBuilder actionText = new StringBuilder();
|
||||
actionText = actionText.append(ItemLogger.ITEM_BREAK);
|
||||
actionText.append(",").append(ItemLogger.ITEM_DESTROY);
|
||||
actionText.append(",").append(ItemLogger.ITEM_CREATE);
|
||||
actionText.append(",").append(ItemLogger.ITEM_SELL);
|
||||
actionText.append(",").append(ItemLogger.ITEM_BUY);
|
||||
actionText = actionText.append(ItemTransactionActions.BREAK);
|
||||
actionText.append(",").append(ItemTransactionActions.DESTROY);
|
||||
actionText.append(",").append(ItemTransactionActions.CREATE);
|
||||
actionText.append(",").append(ItemTransactionActions.SELL);
|
||||
actionText.append(",").append(ItemTransactionActions.BUY);
|
||||
actionExclude = actionText.toString();
|
||||
}
|
||||
|
||||
@@ -393,12 +416,12 @@ public class LookupRaw extends Queue {
|
||||
for (Integer actionTarget : actionList) {
|
||||
if (validActions.contains(actionTarget)) {
|
||||
// If just looking up drops/pickups, remap the actions to the correct values
|
||||
if (actionList.contains(11) && !actionList.contains(4)) {
|
||||
if (actionTarget == ItemLogger.ITEM_REMOVE && !actionList.contains(ItemLogger.ITEM_DROP)) {
|
||||
actionTarget = ItemLogger.ITEM_DROP;
|
||||
if (actionList.contains(LookupActions.ITEM) && !actionList.contains(LookupActions.CONTAINER)) {
|
||||
if (actionTarget == ItemTransactionActions.REMOVE && !actionList.contains(ItemTransactionActions.DROP)) {
|
||||
actionTarget = ItemTransactionActions.DROP;
|
||||
}
|
||||
else if (actionTarget == ItemLogger.ITEM_ADD && !actionList.contains(ItemLogger.ITEM_PICKUP)) {
|
||||
actionTarget = ItemLogger.ITEM_PICKUP;
|
||||
else if (actionTarget == ItemTransactionActions.ADD && !actionList.contains(ItemTransactionActions.PICKUP)) {
|
||||
actionTarget = ItemTransactionActions.PICKUP;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,32 +433,32 @@ public class LookupRaw extends Queue {
|
||||
}
|
||||
|
||||
// If selecting from co_item & co_container, add in actions for both transaction types
|
||||
if (actionList.contains(11) && actionList.contains(4)) {
|
||||
if (actionTarget == ItemLogger.ITEM_REMOVE) {
|
||||
actionText.append(",").append(ItemLogger.ITEM_PICKUP);
|
||||
actionText.append(",").append(ItemLogger.ITEM_REMOVE_ENDER);
|
||||
actionText.append(",").append(ItemLogger.ITEM_CREATE);
|
||||
actionText.append(",").append(ItemLogger.ITEM_BUY);
|
||||
if (LookupActions.isInventoryLookup(actionList)) {
|
||||
if (actionTarget == ItemTransactionActions.REMOVE) {
|
||||
actionText.append(",").append(ItemTransactionActions.PICKUP);
|
||||
actionText.append(",").append(ItemTransactionActions.REMOVE_ENDER);
|
||||
actionText.append(",").append(ItemTransactionActions.CREATE);
|
||||
actionText.append(",").append(ItemTransactionActions.BUY);
|
||||
}
|
||||
if (actionTarget == ItemLogger.ITEM_ADD) {
|
||||
actionText.append(",").append(ItemLogger.ITEM_DROP);
|
||||
actionText.append(",").append(ItemLogger.ITEM_ADD_ENDER);
|
||||
actionText.append(",").append(ItemLogger.ITEM_THROW);
|
||||
actionText.append(",").append(ItemLogger.ITEM_SHOOT);
|
||||
actionText.append(",").append(ItemLogger.ITEM_BREAK);
|
||||
actionText.append(",").append(ItemLogger.ITEM_DESTROY);
|
||||
actionText.append(",").append(ItemLogger.ITEM_SELL);
|
||||
if (actionTarget == ItemTransactionActions.ADD) {
|
||||
actionText.append(",").append(ItemTransactionActions.DROP);
|
||||
actionText.append(",").append(ItemTransactionActions.ADD_ENDER);
|
||||
actionText.append(",").append(ItemTransactionActions.THROW);
|
||||
actionText.append(",").append(ItemTransactionActions.SHOOT);
|
||||
actionText.append(",").append(ItemTransactionActions.BREAK);
|
||||
actionText.append(",").append(ItemTransactionActions.DESTROY);
|
||||
actionText.append(",").append(ItemTransactionActions.SELL);
|
||||
}
|
||||
}
|
||||
// If just looking up drops/pickups, include ender chest transactions
|
||||
else if (actionList.contains(11) && !actionList.contains(4)) {
|
||||
if (actionTarget == ItemLogger.ITEM_DROP) {
|
||||
actionText.append(",").append(ItemLogger.ITEM_ADD_ENDER);
|
||||
actionText.append(",").append(ItemLogger.ITEM_THROW);
|
||||
actionText.append(",").append(ItemLogger.ITEM_SHOOT);
|
||||
else if (actionList.contains(LookupActions.ITEM) && !actionList.contains(LookupActions.CONTAINER)) {
|
||||
if (actionTarget == ItemTransactionActions.DROP) {
|
||||
actionText.append(",").append(ItemTransactionActions.ADD_ENDER);
|
||||
actionText.append(",").append(ItemTransactionActions.THROW);
|
||||
actionText.append(",").append(ItemTransactionActions.SHOOT);
|
||||
}
|
||||
if (actionTarget == ItemLogger.ITEM_PICKUP) {
|
||||
actionText.append(",").append(ItemLogger.ITEM_REMOVE_ENDER);
|
||||
if (actionTarget == ItemTransactionActions.PICKUP) {
|
||||
actionText.append(",").append(ItemTransactionActions.REMOVE_ENDER);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -515,8 +538,8 @@ public class LookupRaw extends Queue {
|
||||
queryBlock = queryBlock + " time <= '" + endTime + "' AND";
|
||||
}
|
||||
|
||||
if (actionList.contains(10)) {
|
||||
queryBlock = queryBlock + " action = '1' AND (LENGTH(line_1) > 0 OR LENGTH(line_2) > 0 OR LENGTH(line_3) > 0 OR LENGTH(line_4) > 0 OR LENGTH(line_5) > 0 OR LENGTH(line_6) > 0 OR LENGTH(line_7) > 0 OR LENGTH(line_8) > 0) AND";
|
||||
if (actionList.contains(LookupActions.SIGN)) {
|
||||
queryBlock = queryBlock + " action = '" + SignActions.PLACE + "' AND (LENGTH(line_1) > 0 OR LENGTH(line_2) > 0 OR LENGTH(line_3) > 0 OR LENGTH(line_4) > 0 OR LENGTH(line_5) > 0 OR LENGTH(line_6) > 0 OR LENGTH(line_7) > 0 OR LENGTH(line_8) > 0) AND";
|
||||
}
|
||||
|
||||
if (queryBlock.length() > 0) {
|
||||
@@ -544,34 +567,34 @@ public class LookupRaw extends Queue {
|
||||
String rows = "rowid as id,time,user,wid,x,y,z,action,type,data,meta,blockdata,rolled_back";
|
||||
String queryOrder = " ORDER BY rowid DESC";
|
||||
|
||||
if (actionList.contains(4) || actionList.contains(5)) {
|
||||
if (actionList.contains(LookupActions.CONTAINER) || actionList.contains(5)) {
|
||||
queryTable = "container";
|
||||
rows = "rowid as id,time,user,wid,x,y,z,action,type,data,rolled_back,amount,metadata";
|
||||
}
|
||||
else if (actionList.contains(6) || actionList.contains(7)) {
|
||||
else if (actionList.contains(LookupActions.CHAT) || actionList.contains(LookupActions.COMMAND)) {
|
||||
queryTable = "chat";
|
||||
rows = "rowid as id,time,user,message";
|
||||
if (PluginChannelHandshakeListener.getInstance().isPluginChannelPlayer(user)) {
|
||||
rows += ",wid,x,y,z";
|
||||
}
|
||||
|
||||
if (actionList.contains(7)) {
|
||||
if (actionList.contains(LookupActions.COMMAND)) {
|
||||
queryTable = "command";
|
||||
}
|
||||
}
|
||||
else if (actionList.contains(8)) {
|
||||
else if (actionList.contains(LookupActions.SESSION)) {
|
||||
queryTable = "session";
|
||||
rows = "rowid as id,time,user,wid,x,y,z,action";
|
||||
}
|
||||
else if (actionList.contains(9)) {
|
||||
else if (actionList.contains(LookupActions.USERNAME)) {
|
||||
queryTable = "username_log";
|
||||
rows = "rowid as id,time,uuid,user";
|
||||
}
|
||||
else if (actionList.contains(10)) {
|
||||
else if (actionList.contains(LookupActions.SIGN)) {
|
||||
queryTable = "sign";
|
||||
rows = "rowid as id,time,user,wid,x,y,z,face,line_1,line_2,line_3,line_4,line_5,line_6,line_7,line_8";
|
||||
}
|
||||
else if (actionList.contains(11)) {
|
||||
else if (actionList.contains(LookupActions.ITEM)) {
|
||||
queryTable = "item";
|
||||
rows = "rowid as id,time,user,wid,x,y,z,type,data as metadata,0 as data,amount,action,0 as rolled_back";
|
||||
}
|
||||
@@ -586,17 +609,17 @@ public class LookupRaw extends Queue {
|
||||
String unionSelect = "SELECT * FROM (";
|
||||
if (Config.getGlobal().MYSQL) {
|
||||
if (queryTable.equals("block")) {
|
||||
if (includeBlock.length() > 0 || includeEntity.length() > 0) {
|
||||
index = "USE INDEX(type) IGNORE INDEX(user,wid) ";
|
||||
}
|
||||
if (users.length() > 0) {
|
||||
index = "USE INDEX(user) IGNORE INDEX(type,wid) ";
|
||||
}
|
||||
if (radius != null && (radius[2] - radius[1]) <= 50 && (radius[6] - radius[5]) <= 50) {
|
||||
index = "USE INDEX(wid) IGNORE INDEX(type,user) ";
|
||||
index = "USE INDEX(wid) ";
|
||||
}
|
||||
if ((restrictWorld && (users.length() > 0 || includeBlock.length() > 0 || includeEntity.length() > 0))) {
|
||||
index = "IGNORE INDEX(PRIMARY) ";
|
||||
else if (users.length() > 0) {
|
||||
index = "USE INDEX(user) ";
|
||||
}
|
||||
else if (includeBlock.length() > 0 || includeEntity.length() > 0) {
|
||||
index = "USE INDEX(type) ";
|
||||
}
|
||||
else if (restrictWorld) {
|
||||
index = "USE INDEX(wid) ";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,17 +643,17 @@ public class LookupRaw extends Queue {
|
||||
}
|
||||
|
||||
boolean itemLookup = inventoryQuery;
|
||||
if ((lookup && actionList.size() == 0) || (itemLookup && !actionList.contains(0))) {
|
||||
if ((lookup && actionList.size() == 0) || (itemLookup && !actionList.contains(LookupActions.BLOCK_BREAK))) {
|
||||
if (!count) {
|
||||
rows = "rowid as id,time,user,wid,x,y,z,type,meta as metadata,data,-1 as amount,action,rolled_back";
|
||||
}
|
||||
|
||||
if (inventoryQuery) {
|
||||
if (validAction) {
|
||||
baseQuery = baseQuery.replace("action IN(" + action + ")", "action IN(1)");
|
||||
baseQuery = baseQuery.replace("action IN(" + action + ")", "action IN(" + LookupActions.BLOCK_PLACE + ")");
|
||||
}
|
||||
else {
|
||||
baseQuery = baseQuery.replace("action NOT IN(-1)", "action IN(1)");
|
||||
baseQuery = baseQuery.replace("action NOT IN(-1)", "action IN(" + LookupActions.BLOCK_PLACE + ")");
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
@@ -639,7 +662,7 @@ public class LookupRaw extends Queue {
|
||||
}
|
||||
|
||||
if (includeBlock.length() > 0 || excludeBlock.length() > 0) {
|
||||
baseQuery = baseQuery.replace("action NOT IN(-1)", "action NOT IN(3)"); // if block specified for include/exclude, filter out entity data
|
||||
baseQuery = baseQuery.replace("action NOT IN(-1)", "action NOT IN(" + LookupActions.ENTITY_KILL + ")"); // if block specified for include/exclude, filter out entity data
|
||||
}
|
||||
|
||||
query = unionSelect + "SELECT " + "'0' as tbl," + rows + " FROM " + ConfigHandler.prefix + "block " + index + "WHERE" + baseQuery + unionLimit + ") UNION ALL ";
|
||||
@@ -676,7 +699,7 @@ public class LookupRaw extends Queue {
|
||||
results = statement.executeQuery(query);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return results;
|
||||
|
||||
@@ -15,8 +15,12 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.BlockStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class BlockBreakLogger {
|
||||
|
||||
@@ -26,19 +30,30 @@ public class BlockBreakLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, int type, int data, List<Object> meta, String blockData, String overrideData) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null || location == null) {
|
||||
Material checkType = MaterialUtils.getType(type);
|
||||
String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
|
||||
if (blockKey.length() == 0 && checkType != null) {
|
||||
blockKey = checkType.getKey().toString();
|
||||
}
|
||||
else if (checkType != null && (checkType == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(checkType) || checkType == Material.ARMOR_STAND || checkType == Material.END_CRYSTAL)) {
|
||||
blockKey = checkType.getKey().toString();
|
||||
}
|
||||
if (checkType != null && blockKey.length() > 0) {
|
||||
Material blockDataType = MaterialUtils.getType(blockKey);
|
||||
if (blockDataType != null && !blockDataType.equals(checkType)) {
|
||||
blockKey = checkType.getKey().toString();
|
||||
blockData = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (checkType == null && blockKey.length() == 0) {
|
||||
return;
|
||||
}
|
||||
else if (checkType != null && (checkType.equals(Material.AIR) || checkType.equals(Material.CAVE_AIR)) && BlockTypeUtils.isAir(blockKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material checkType = net.coreprotect.utility.MaterialUtils.getType(type);
|
||||
if (checkType == null) {
|
||||
return;
|
||||
}
|
||||
else if (checkType.equals(Material.AIR) || checkType.equals(Material.CAVE_AIR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigHandler.blacklist.get(checkType.getKey().toString()) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user, blockKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -47,14 +62,14 @@ public class BlockBreakLogger {
|
||||
CacheHandler.spreadCache.remove(cacheId);
|
||||
}
|
||||
|
||||
if (checkType == Material.LECTERN) {
|
||||
if (checkType == Material.LECTERN && blockData != null) {
|
||||
blockData = blockData.replaceFirst("has_book=true", "has_book=false");
|
||||
}
|
||||
else if (checkType == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(checkType)) {
|
||||
else if (checkType != null && (checkType == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(checkType))) {
|
||||
blockData = overrideData;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location);
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location, CoreProtectPreLogEvent.Action.BLOCK_BREAK, LookupActions.BLOCK_BREAK, checkType, null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -72,10 +87,11 @@ public class BlockBreakLogger {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, meta, blockData, 0, 0);
|
||||
int internalType = blockKey.length() > 0 ? MaterialUtils.getBlockId(blockKey, true) : type;
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, LookupActions.BLOCK_BREAK, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,12 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.BlockStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class BlockPlaceLogger {
|
||||
|
||||
@@ -28,17 +31,14 @@ public class BlockPlaceLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, BlockState block, int replacedType, int replacedData, Material forceType, int forceData, boolean force, List<Object> meta, String blockData, String replaceBlockData) {
|
||||
try {
|
||||
if (user == null || ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Material type = block.getType();
|
||||
if (blockData == null && (forceType == null || (!forceType.equals(Material.WATER)) && (!forceType.equals(Material.LAVA)))) {
|
||||
blockData = block.getBlockData().getAsString();
|
||||
if (blockData.equals("minecraft:air")) {
|
||||
if (BlockTypeUtils.isAir(BlockTypeUtils.getBlockDataKey(blockData))) {
|
||||
blockData = null;
|
||||
}
|
||||
}
|
||||
String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
|
||||
int data = 0;
|
||||
if (forceType != null && force) {
|
||||
type = forceType;
|
||||
@@ -49,16 +49,32 @@ public class BlockPlaceLogger {
|
||||
data = forceData;
|
||||
}
|
||||
}
|
||||
else if (forceType != null && !type.equals(forceType)) {
|
||||
else if (forceType != null && (type == null || !type.equals(forceType))) {
|
||||
type = forceType;
|
||||
data = forceData;
|
||||
}
|
||||
if (forceType != null && type != null && blockKey.length() > 0) {
|
||||
Material blockDataType = MaterialUtils.getType(blockKey);
|
||||
if (blockDataType != null && !blockDataType.equals(type)) {
|
||||
blockKey = type.getKey().toString();
|
||||
blockData = null;
|
||||
}
|
||||
}
|
||||
if (blockKey.length() == 0) {
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
blockKey = type.getKey().toString();
|
||||
}
|
||||
else if (type != null && (type == Material.PAINTING || BukkitAdapter.ADAPTER.isItemFrame(type))) {
|
||||
blockKey = type.getKey().toString();
|
||||
}
|
||||
|
||||
if (type.equals(Material.AIR) || type.equals(Material.CAVE_AIR)) {
|
||||
if (type != null && (type.equals(Material.AIR) || type.equals(Material.CAVE_AIR)) && BlockTypeUtils.isAir(blockKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigHandler.blacklist.get(type.getKey().toString()) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user, blockKey)){
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -86,7 +102,7 @@ public class BlockPlaceLogger {
|
||||
}
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation());
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation(), CoreProtectPreLogEvent.Action.BLOCK_PLACE, LookupActions.BLOCK_PLACE, type, null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -109,15 +125,16 @@ public class BlockPlaceLogger {
|
||||
return;
|
||||
}
|
||||
|
||||
int internalType = MaterialUtils.getBlockId(type.name(), true);
|
||||
if (replacedType > 0 && MaterialUtils.getType(replacedType) != Material.AIR && MaterialUtils.getType(replacedType) != Material.CAVE_AIR) {
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, replacedType, replacedData, null, replaceBlockData, 0, 0);
|
||||
int internalType = MaterialUtils.getBlockId(blockKey, true);
|
||||
int replacedInternalType = MaterialUtils.getBlockId(replaceBlockData, MaterialUtils.getType(replacedType), true);
|
||||
if (replacedInternalType > 0 && !BlockTypeUtils.isAir(MaterialUtils.getBlockName(replacedInternalType))) {
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, replacedInternalType, replacedData, null, replaceBlockData, LookupActions.BLOCK_BREAK, 0);
|
||||
}
|
||||
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, 1, 0);
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, internalType, data, meta, blockData, LookupActions.BLOCK_PLACE, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.bukkit.Location;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.ChatStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ChatLogger {
|
||||
|
||||
@@ -17,7 +18,7 @@ public class ChatLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, long time, Location location, String user, String message) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
int x = location.getBlockX();
|
||||
@@ -28,7 +29,7 @@ public class ChatLogger {
|
||||
ChatStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.coreprotect.database.statement.CommandStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class CommandLogger {
|
||||
|
||||
@@ -22,14 +23,14 @@ public class CommandLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, long time, Location location, String user, String message) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
if (ConfigHandler.blacklist.get(((message + " ").split(" "))[0].toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(((message + " ").split(" "))[0])) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location);
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location, CoreProtectPreLogEvent.Action.PLAYER_COMMAND, -1, null, null, message);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -47,7 +48,7 @@ public class CommandLogger {
|
||||
CommandStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, message);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package net.coreprotect.database.logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.HopperTransactionUtils;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ContainerBreakLogger {
|
||||
|
||||
@@ -19,16 +21,14 @@ public class ContainerBreakLogger {
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String player, Location l, Material type, ItemStack[] oldInventory) {
|
||||
try {
|
||||
ItemUtils.mergeItems(type, oldInventory);
|
||||
ContainerLogger.logTransaction(preparedStmt, batchCount, player, type, null, oldInventory, 0, l);
|
||||
String loggingContainerId = player.toLowerCase(Locale.ROOT) + "." + l.getBlockX() + "." + l.getBlockY() + "." + l.getBlockZ();
|
||||
ContainerLogger.logTransaction(preparedStmt, batchCount, player, type, null, oldInventory, ItemTransactionActions.REMOVE, l);
|
||||
String loggingContainerId = HopperTransactionUtils.getLoggingId(player, l);
|
||||
|
||||
// If there was a pending chest transaction, it would have already been processed.
|
||||
if (ConfigHandler.forceContainer.get(loggingContainerId) != null) {
|
||||
ConfigHandler.forceContainer.remove(loggingContainerId);
|
||||
}
|
||||
Queue.removeForceContainer(loggingContainerId);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
package net.coreprotect.database.logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -22,14 +21,22 @@ import net.coreprotect.consumer.Queue;
|
||||
import net.coreprotect.database.statement.ContainerStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.thread.CacheHandler;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.HopperTransactionUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.serialize.ItemMetaHandler;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ContainerLogger extends Queue {
|
||||
|
||||
private static final int CONTAINER_DUPLICATE_THRESHOLD_DROPPER = 512;
|
||||
private static final int CONTAINER_DUPLICATE_THRESHOLD_DISPENSER = 256;
|
||||
private static final int CONTAINER_DUPLICATE_WINDOW_SECONDS = 1200;
|
||||
|
||||
private ContainerLogger() {
|
||||
throw new IllegalStateException("Database class");
|
||||
}
|
||||
@@ -46,6 +53,9 @@ public class ContainerLogger extends Queue {
|
||||
else if (type == Material.JUKEBOX || type == Material.ARMOR_STAND) {
|
||||
contents = (ItemStack[]) ((Object[]) container)[1];
|
||||
}
|
||||
else if (container instanceof ItemStack[]) {
|
||||
contents = (ItemStack[]) container;
|
||||
}
|
||||
else {
|
||||
Inventory inventory = (Inventory) container;
|
||||
if (inventory != null) {
|
||||
@@ -57,17 +67,22 @@ public class ContainerLogger extends Queue {
|
||||
return;
|
||||
}
|
||||
|
||||
String loggingContainerId = player.toLowerCase(Locale.ROOT) + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
String loggingContainerId = HopperTransactionUtils.getLoggingId(player, location);
|
||||
String transactingChestId = HopperTransactionUtils.getTransactionId(location);
|
||||
List<ItemStack[]> oldList = ConfigHandler.oldContainer.get(loggingContainerId);
|
||||
if (oldList == null || oldList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ItemStack[] oi1 = oldList.get(0);
|
||||
ItemStack[] oldInventory = ItemUtils.getContainerState(oi1);
|
||||
ItemStack[] newInventory = ItemUtils.getContainerState(contents);
|
||||
if (oldInventory == null || newInventory == null) {
|
||||
return;
|
||||
}
|
||||
boolean duplicateSuppression = Config.getConfig(location.getWorld()).DUPLICATE_SUPPRESSION;
|
||||
|
||||
// Check if this is a dispenser with no actual changes
|
||||
if ("#dispenser".equals(player) && ItemUtils.compareContainers(oldInventory, newInventory)) {
|
||||
if (duplicateSuppression && "#dispenser".equals(player) && getForceContainerSize(loggingContainerId) == 0 && ItemUtils.compareContainers(oldInventory, newInventory)) {
|
||||
// No changes detected, mark this dispenser in the dispenserNoChange map
|
||||
// Extract the location key from the loggingContainerId
|
||||
// Format: #dispenser.x.y.z
|
||||
@@ -90,12 +105,15 @@ public class ContainerLogger extends Queue {
|
||||
ConfigHandler.dispenserNoChange.computeIfAbsent(locationKey, k -> new ConcurrentHashMap<>()).put(eventKey, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
oldList.remove(0);
|
||||
ConfigHandler.oldContainer.put(loggingContainerId, oldList);
|
||||
HopperTransactionUtils.consumeSnapshot(transactingChestId, loggingContainerId);
|
||||
return;
|
||||
}
|
||||
|
||||
// If we reach here, the dispenser event resulted in changes
|
||||
// Remove any pending event for this dispenser
|
||||
if ("#dispenser".equals(player)) {
|
||||
if (duplicateSuppression && "#dispenser".equals(player)) {
|
||||
String[] parts = loggingContainerId.split("\\.");
|
||||
if (parts.length >= 4) {
|
||||
int x = Integer.parseInt(parts[1]);
|
||||
@@ -112,58 +130,28 @@ public class ContainerLogger extends Queue {
|
||||
}
|
||||
}
|
||||
|
||||
List<ItemStack[]> forceList = ConfigHandler.forceContainer.get(loggingContainerId);
|
||||
if (forceList != null) {
|
||||
int forceSize = 0;
|
||||
if (!forceList.isEmpty()) {
|
||||
newInventory = ItemUtils.getContainerState(forceList.get(0));
|
||||
forceSize = modifyForceContainer(loggingContainerId, null);
|
||||
}
|
||||
if (forceSize == 0) {
|
||||
ConfigHandler.forceContainer.remove(loggingContainerId);
|
||||
}
|
||||
ItemStack[] forceState = peekForceContainer(loggingContainerId);
|
||||
if (forceState != null) {
|
||||
newInventory = ItemUtils.getContainerState(forceState);
|
||||
}
|
||||
else {
|
||||
String transactingChestId = location.getWorld().getUID().toString() + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
if (ConfigHandler.transactingChest.get(transactingChestId) != null) {
|
||||
List<Object> list = Collections.synchronizedList(new ArrayList<>(ConfigHandler.transactingChest.get(transactingChestId)));
|
||||
if (list.size() > 0) {
|
||||
ItemStack[] newMerge = new ItemStack[newInventory.length + list.size()];
|
||||
int count = 0;
|
||||
for (int i = 0; i < newInventory.length; i++) {
|
||||
newMerge[i] = newInventory[i];
|
||||
count++;
|
||||
}
|
||||
for (Object item : list) {
|
||||
ItemStack addItem = null;
|
||||
ItemStack removeItem = null;
|
||||
if (item instanceof ItemStack) {
|
||||
addItem = (ItemStack) item;
|
||||
}
|
||||
else if (item != null) {
|
||||
addItem = ((ItemStack[]) item)[0];
|
||||
removeItem = ((ItemStack[]) item)[1];
|
||||
}
|
||||
long snapshotMark = HopperTransactionUtils.peekSnapshotMark(transactingChestId, loggingContainerId);
|
||||
newInventory = HopperTransactionUtils.applyPendingChanges(newInventory, transactingChestId, snapshotMark);
|
||||
}
|
||||
|
||||
// item was removed by hopper, add back to state
|
||||
if (addItem != null) {
|
||||
newMerge[count] = addItem;
|
||||
count++;
|
||||
}
|
||||
|
||||
// item was added by hopper, remove from state
|
||||
if (removeItem != null) {
|
||||
for (ItemStack check : newMerge) {
|
||||
if (check != null && check.isSimilar(removeItem)) {
|
||||
check.setAmount(check.getAmount() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newInventory = newMerge;
|
||||
}
|
||||
if (duplicateSuppression && shouldSuppressContainerDuplicate(player, location, oldInventory, newInventory)) {
|
||||
if (forceState != null) {
|
||||
pollForceContainer(loggingContainerId);
|
||||
}
|
||||
oldList.remove(0);
|
||||
ConfigHandler.oldContainer.put(loggingContainerId, oldList);
|
||||
HopperTransactionUtils.consumeSnapshot(transactingChestId, loggingContainerId);
|
||||
if ("#hopper".equals(player)) {
|
||||
String hopperPush = HopperTransactionUtils.getHopperPushId(location);
|
||||
ConfigHandler.hopperSuccess.remove(hopperPush);
|
||||
ConfigHandler.hopperAbort.remove(hopperPush);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (ItemStack oldi : oldInventory) {
|
||||
@@ -191,25 +179,29 @@ public class ContainerLogger extends Queue {
|
||||
ItemUtils.mergeItems(type, newInventory);
|
||||
|
||||
if (type != Material.ENDER_CHEST) {
|
||||
logTransaction(preparedStmtContainer, batchCount, player, type, faceData, oldInventory, 0, location);
|
||||
logTransaction(preparedStmtContainer, batchCount, player, type, faceData, newInventory, 1, location);
|
||||
logTransaction(preparedStmtContainer, batchCount, player, type, faceData, oldInventory, ItemTransactionActions.REMOVE, location);
|
||||
logTransaction(preparedStmtContainer, batchCount, player, type, faceData, newInventory, ItemTransactionActions.ADD, location);
|
||||
}
|
||||
else { // pass ender chest transactions to item logger
|
||||
ItemLogger.logTransaction(preparedStmtItems, batchCount, 0, player, location, oldInventory, ItemLogger.ITEM_REMOVE_ENDER);
|
||||
ItemLogger.logTransaction(preparedStmtItems, batchCount, 0, player, location, newInventory, ItemLogger.ITEM_ADD_ENDER);
|
||||
ItemLogger.logTransaction(preparedStmtItems, batchCount, 0, player, location, oldInventory, ItemTransactionActions.REMOVE_ENDER);
|
||||
ItemLogger.logTransaction(preparedStmtItems, batchCount, 0, player, location, newInventory, ItemTransactionActions.ADD_ENDER);
|
||||
}
|
||||
|
||||
if (forceState != null) {
|
||||
pollForceContainer(loggingContainerId);
|
||||
}
|
||||
oldList.remove(0);
|
||||
ConfigHandler.oldContainer.put(loggingContainerId, oldList);
|
||||
HopperTransactionUtils.consumeSnapshot(transactingChestId, loggingContainerId);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void logTransaction(PreparedStatement preparedStmt, int batchCount, String user, Material type, String faceData, ItemStack[] items, int action, Location location) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
boolean success = false;
|
||||
@@ -218,19 +210,24 @@ public class ContainerLogger extends Queue {
|
||||
if (item != null) {
|
||||
if (item.getAmount() > 0 && !BlockUtils.isAir(item.getType())) {
|
||||
// Object[] metadata = new Object[] { slot, item.getItemMeta() };
|
||||
if (ConfigHandler.isFilterBlacklisted(user, item.getType().getKey().toString())){
|
||||
continue;
|
||||
}
|
||||
|
||||
List<List<Map<String, Object>>> metadata = ItemMetaHandler.serialize(item, type, faceData, slot);
|
||||
if (metadata.size() == 0) {
|
||||
metadata = null;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location);
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location, CoreProtectPreLogEvent.Action.CONTAINER_TRANSACTION, action, item.getType(), null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int userId = UserStatement.getId(preparedStmt, event.getUser(), true);
|
||||
Location eventLocation = event.getLocation();
|
||||
@@ -250,14 +247,75 @@ public class ContainerLogger extends Queue {
|
||||
}
|
||||
|
||||
if (success && user.equals("#hopper")) {
|
||||
String hopperPush = "#hopper-push." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ();
|
||||
String hopperPush = HopperTransactionUtils.getHopperPushId(location);
|
||||
ConfigHandler.hopperSuccess.remove(hopperPush);
|
||||
ConfigHandler.hopperAbort.remove(hopperPush);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean shouldSuppressContainerDuplicate(String user, Location location, ItemStack[] oldInventory, ItemStack[] newInventory) {
|
||||
if (!"#dropper".equals(user) && !"#dispenser".equals(user)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String oldSignature = getContainerStateSignature(oldInventory);
|
||||
String newSignature = getContainerStateSignature(newInventory);
|
||||
String transitionSignature = oldSignature + ">" + newSignature;
|
||||
if ("#dispenser".equals(user)) {
|
||||
if (oldSignature.compareTo(newSignature) <= 0) {
|
||||
transitionSignature = oldSignature + "<>" + newSignature;
|
||||
}
|
||||
else {
|
||||
transitionSignature = newSignature + "<>" + oldSignature;
|
||||
}
|
||||
}
|
||||
|
||||
int threshold = getContainerDuplicateThreshold(user);
|
||||
String signature = location.getWorld().getUID().toString() + "." + location.getBlockX() + "." + location.getBlockY() + "." + location.getBlockZ() + "." + user + "." + transitionSignature;
|
||||
return CacheHandler.shouldSuppressRepeat(CacheHandler.containerDuplicateCache, signature, threshold, CONTAINER_DUPLICATE_WINDOW_SECONDS);
|
||||
}
|
||||
|
||||
private static int getContainerDuplicateThreshold(String user) {
|
||||
if ("#dispenser".equals(user)) {
|
||||
return CONTAINER_DUPLICATE_THRESHOLD_DISPENSER;
|
||||
}
|
||||
return CONTAINER_DUPLICATE_THRESHOLD_DROPPER;
|
||||
}
|
||||
|
||||
private static String getContainerStateSignature(ItemStack[] inventory) {
|
||||
if (inventory == null || inventory.length == 0) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
Map<String, Integer> itemCounts = new HashMap<>();
|
||||
for (ItemStack itemStack : inventory) {
|
||||
if (itemStack == null || itemStack.getAmount() <= 0 || BlockUtils.isAir(itemStack.getType())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ItemStack normalized = itemStack.clone();
|
||||
normalized.setAmount(1);
|
||||
String key = normalized.toString();
|
||||
itemCounts.merge(key, itemStack.getAmount(), Integer::sum);
|
||||
}
|
||||
|
||||
if (itemCounts.isEmpty()) {
|
||||
return "-";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (Map.Entry<String, Integer> entry : new TreeMap<>(itemCounts).entrySet()) {
|
||||
if (builder.length() > 0) {
|
||||
builder.append('|');
|
||||
}
|
||||
builder.append(entry.getKey()).append('*').append(entry.getValue());
|
||||
}
|
||||
|
||||
return Integer.toHexString(builder.toString().hashCode());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,11 +3,10 @@ package net.coreprotect.database.logger;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.config.Config;
|
||||
@@ -17,7 +16,9 @@ import net.coreprotect.database.statement.BlockStatement;
|
||||
import net.coreprotect.database.statement.EntityStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class EntityKillLogger {
|
||||
|
||||
@@ -25,14 +26,25 @@ public class EntityKillLogger {
|
||||
throw new IllegalStateException("Database class");
|
||||
}
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, PreparedStatement preparedStmt2, int batchCount, String user, BlockState block, List<Object> data, int type) {
|
||||
public static void log(PreparedStatement preparedStmt, PreparedStatement preparedStmt2, int batchCount, String user, Location location, List<Object> data, int type) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)){
|
||||
return;
|
||||
}
|
||||
|
||||
Location initialLocation = new Location(block.getWorld(), block.getX(), block.getY(), block.getZ());
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation);
|
||||
EntityType checkType = net.coreprotect.utility.EntityUtils.getEntityType(type);
|
||||
if (checkType == null) {
|
||||
return;
|
||||
}
|
||||
// Ignore blacklist if the entity has a custom name
|
||||
// data[4] contains custom name data
|
||||
if (ConfigHandler.isBlacklisted(user, checkType.getKey().toString()) &&
|
||||
!(data.size() > 4 && data.get(4) != null)){
|
||||
return;
|
||||
}
|
||||
|
||||
Location initialLocation = location.clone();
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation, CoreProtectPreLogEvent.Action.ENTITY_KILL, LookupActions.ENTITY_KILL, null, checkType, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -63,10 +75,10 @@ public class EntityKillLogger {
|
||||
keys.close();
|
||||
}
|
||||
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, entity_key, null, null, 3, 0);
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, entity_key, null, null, LookupActions.ENTITY_KILL, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,27 +16,29 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.ItemStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.item.ItemTransactionActions;
|
||||
import net.coreprotect.utility.BlockUtils;
|
||||
import net.coreprotect.utility.ItemUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.serialize.ItemMetaHandler;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class ItemLogger {
|
||||
|
||||
public static final int ITEM_REMOVE = 0;
|
||||
public static final int ITEM_ADD = 1;
|
||||
public static final int ITEM_DROP = 2;
|
||||
public static final int ITEM_PICKUP = 3;
|
||||
public static final int ITEM_REMOVE_ENDER = 4;
|
||||
public static final int ITEM_ADD_ENDER = 5;
|
||||
public static final int ITEM_THROW = 6;
|
||||
public static final int ITEM_SHOOT = 7;
|
||||
public static final int ITEM_BREAK = 8;
|
||||
public static final int ITEM_DESTROY = 9;
|
||||
public static final int ITEM_CREATE = 10;
|
||||
public static final int ITEM_SELL = 11;
|
||||
public static final int ITEM_BUY = 12;
|
||||
public static final int ITEM_REMOVE = ItemTransactionActions.REMOVE;
|
||||
public static final int ITEM_ADD = ItemTransactionActions.ADD;
|
||||
public static final int ITEM_DROP = ItemTransactionActions.DROP;
|
||||
public static final int ITEM_PICKUP = ItemTransactionActions.PICKUP;
|
||||
public static final int ITEM_REMOVE_ENDER = ItemTransactionActions.REMOVE_ENDER;
|
||||
public static final int ITEM_ADD_ENDER = ItemTransactionActions.ADD_ENDER;
|
||||
public static final int ITEM_THROW = ItemTransactionActions.THROW;
|
||||
public static final int ITEM_SHOOT = ItemTransactionActions.SHOOT;
|
||||
public static final int ITEM_BREAK = ItemTransactionActions.BREAK;
|
||||
public static final int ITEM_DESTROY = ItemTransactionActions.DESTROY;
|
||||
public static final int ITEM_CREATE = ItemTransactionActions.CREATE;
|
||||
public static final int ITEM_SELL = ItemTransactionActions.SELL;
|
||||
public static final int ITEM_BUY = ItemTransactionActions.BUY;
|
||||
|
||||
private ItemLogger() {
|
||||
throw new IllegalStateException("Database class");
|
||||
@@ -44,7 +46,7 @@ public class ItemLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, Location location, int offset, String user) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,7 +117,7 @@ public class ItemLogger {
|
||||
logTransaction(preparedStmt, batchCount, offset, user, location, itemBuys, ITEM_BUY);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,12 +126,16 @@ public class ItemLogger {
|
||||
for (ItemStack item : items) {
|
||||
if (item != null && item.getAmount() > 0 && !BlockUtils.isAir(item.getType())) {
|
||||
// Object[] metadata = new Object[] { slot, item.getItemMeta() };
|
||||
if (ConfigHandler.isFilterBlacklisted(user, item.getType().getKey().toString())){
|
||||
continue;
|
||||
}
|
||||
|
||||
List<List<Map<String, Object>>> data = ItemMetaHandler.serialize(item, null, null, 0);
|
||||
if (data.size() == 0) {
|
||||
data = null;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location);
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location, CoreProtectPreLogEvent.Action.ITEM_TRANSACTION, action, item.getType(), null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -137,7 +143,7 @@ public class ItemLogger {
|
||||
if (event.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
int userId = UserStatement.getId(preparedStmt, event.getUser(), true);
|
||||
Location eventLocation = event.getLocation();
|
||||
int wid = WorldUtils.getWorldId(eventLocation.getWorld().getName());
|
||||
@@ -152,7 +158,7 @@ public class ItemLogger {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package net.coreprotect.database.logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Location;
|
||||
@@ -14,8 +12,11 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.BlockStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.BlockTypeUtils;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class PlayerInteractLogger {
|
||||
|
||||
@@ -25,12 +26,28 @@ public class PlayerInteractLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, BlockState block, Material blockType) {
|
||||
try {
|
||||
int type = MaterialUtils.getBlockId(blockType.name(), true);
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null || MaterialUtils.getType(type).equals(Material.AIR) || MaterialUtils.getType(type).equals(Material.CAVE_AIR)) {
|
||||
String blockData = block.getBlockData().getAsString();
|
||||
String blockKey = BlockTypeUtils.getBlockDataKey(blockData);
|
||||
if (blockType != null && blockKey.length() > 0) {
|
||||
Material blockDataType = MaterialUtils.getType(blockKey);
|
||||
if (BlockTypeUtils.isAir(blockKey) || (blockDataType != null && !blockDataType.equals(blockType))) {
|
||||
blockKey = blockType.getKey().toString();
|
||||
blockData = null;
|
||||
}
|
||||
}
|
||||
if (blockKey.length() == 0 && blockType != null) {
|
||||
blockKey = blockType.getKey().toString();
|
||||
}
|
||||
if (blockKey.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation());
|
||||
int type = MaterialUtils.getBlockId(blockKey, true);
|
||||
if (ConfigHandler.isBlacklisted(user) || BlockTypeUtils.isAir(blockKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, block.getLocation(), CoreProtectPreLogEvent.Action.PLAYER_INTERACTION, LookupActions.INTERACTION, blockType, null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -47,10 +64,10 @@ public class PlayerInteractLogger {
|
||||
int y = eventLocation.getBlockY();
|
||||
int z = eventLocation.getBlockZ();
|
||||
int data = 0;
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, null, null, 2, 0);
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, type, data, null, blockData, LookupActions.INTERACTION, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.Locale;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.entity.EntityType;
|
||||
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.config.Config;
|
||||
@@ -13,7 +13,9 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.BlockStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.model.action.LookupActions;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class PlayerKillLogger {
|
||||
|
||||
@@ -21,9 +23,9 @@ public class PlayerKillLogger {
|
||||
throw new IllegalStateException("Database class");
|
||||
}
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, BlockState block, String player) {
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, String player) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -31,8 +33,8 @@ public class PlayerKillLogger {
|
||||
UserStatement.loadId(preparedStmt.getConnection(), player, null);
|
||||
}
|
||||
|
||||
Location initialLocation = new Location(block.getWorld(), block.getX(), block.getY(), block.getZ());
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation);
|
||||
Location initialLocation = location.clone();
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, initialLocation, CoreProtectPreLogEvent.Action.PLAYER_KILL, LookupActions.ENTITY_KILL, null, EntityType.PLAYER, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -49,10 +51,10 @@ public class PlayerKillLogger {
|
||||
int x = eventLocation.getBlockX();
|
||||
int y = eventLocation.getBlockY();
|
||||
int z = eventLocation.getBlockZ();
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, 0, playerId, null, null, 3, 0);
|
||||
BlockStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, 0, playerId, null, null, LookupActions.ENTITY_KILL, 0);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.bukkit.Location;
|
||||
import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.statement.SessionStatement;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class PlayerSessionLogger {
|
||||
|
||||
@@ -17,7 +18,7 @@ public class PlayerSessionLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, int time, int action) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
int x = location.getBlockX();
|
||||
@@ -28,7 +29,7 @@ public class PlayerSessionLogger {
|
||||
SessionStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, action);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.coreprotect.database.statement.SignStatement;
|
||||
import net.coreprotect.database.statement.UserStatement;
|
||||
import net.coreprotect.event.CoreProtectPreLogEvent;
|
||||
import net.coreprotect.utility.WorldUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class SignTextLogger {
|
||||
|
||||
@@ -22,11 +23,11 @@ public class SignTextLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, int batchCount, String user, Location location, int action, int color, int colorSecondary, int data, boolean isWaxed, boolean isFront, String line1, String line2, String line3, String line4, String line5, String line6, String line7, String line8, int timeOffset) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null) {
|
||||
if (ConfigHandler.isBlacklisted(user)) {
|
||||
return;
|
||||
}
|
||||
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location);
|
||||
CoreProtectPreLogEvent event = new CoreProtectPreLogEvent(user, location, CoreProtectPreLogEvent.Action.SIGN_TEXT, action, null, null, null);
|
||||
if (Config.getGlobal().API_ENABLED && !Bukkit.isPrimaryThread()) {
|
||||
CoreProtect.getInstance().getServer().getPluginManager().callEvent(event);
|
||||
}
|
||||
@@ -59,7 +60,7 @@ public class SignTextLogger {
|
||||
SignStatement.insert(preparedStmt, batchCount, time, userId, wid, x, y, z, action, color, colorSecondary, data, isWaxed ? 1 : 0, isFront ? 0 : 1, line1, line2, line3, line4, line5, line6, line7, line8);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.coreprotect.database.logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Skull;
|
||||
@@ -12,6 +11,7 @@ import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.SkullStatement;
|
||||
import net.coreprotect.paper.PaperAdapter;
|
||||
import net.coreprotect.utility.MaterialUtils;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class SkullBreakLogger {
|
||||
|
||||
@@ -21,7 +21,7 @@ public class SkullBreakLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, PreparedStatement preparedStmt2, int batchCount, String user, BlockState block) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null || block == null) {
|
||||
if (ConfigHandler.isBlacklisted(user) || block == null) {
|
||||
return;
|
||||
}
|
||||
int time = (int) (System.currentTimeMillis() / 1000L);
|
||||
@@ -30,9 +30,9 @@ public class SkullBreakLogger {
|
||||
String skullOwner = "";
|
||||
String skullSkin = null;
|
||||
int skullKey = 0;
|
||||
if (skull.hasOwner()) {
|
||||
skullOwner = PaperAdapter.ADAPTER.getSkullOwner(skull);
|
||||
skullSkin = PaperAdapter.ADAPTER.getSkullSkin(skull);
|
||||
skullOwner = PaperAdapter.ADAPTER.getSkullOwner(skull);
|
||||
skullSkin = PaperAdapter.ADAPTER.getSkullSkin(skull);
|
||||
if ((skullOwner != null && skullOwner.length() > 0) || (skullSkin != null && skullSkin.length() > 0)) {
|
||||
ResultSet resultSet = SkullStatement.insert(preparedStmt2, time, skullOwner, skullSkin);
|
||||
if (Database.hasReturningKeys()) {
|
||||
resultSet.next();
|
||||
@@ -50,7 +50,7 @@ public class SkullBreakLogger {
|
||||
BlockBreakLogger.log(preparedStmt, batchCount, user, block.getLocation(), type, skullKey, null, block.getBlockData().getAsString(), null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package net.coreprotect.database.logger;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.BlockState;
|
||||
@@ -12,6 +11,7 @@ import net.coreprotect.config.ConfigHandler;
|
||||
import net.coreprotect.database.Database;
|
||||
import net.coreprotect.database.statement.SkullStatement;
|
||||
import net.coreprotect.paper.PaperAdapter;
|
||||
import net.coreprotect.utility.ErrorReporter;
|
||||
|
||||
public class SkullPlaceLogger {
|
||||
|
||||
@@ -21,7 +21,7 @@ public class SkullPlaceLogger {
|
||||
|
||||
public static void log(PreparedStatement preparedStmt, PreparedStatement preparedStmt2, int batchCount, String user, BlockState block, int replaceType, int replaceData) {
|
||||
try {
|
||||
if (ConfigHandler.blacklist.get(user.toLowerCase(Locale.ROOT)) != null || block == null) {
|
||||
if (ConfigHandler.isBlacklisted(user) || block == null) {
|
||||
return;
|
||||
}
|
||||
int time = (int) (System.currentTimeMillis() / 1000L);
|
||||
@@ -32,9 +32,9 @@ public class SkullPlaceLogger {
|
||||
Skull skull = (Skull) block;
|
||||
String skullOwner = "";
|
||||
String skullSkin = null;
|
||||
if (skull.hasOwner()) {
|
||||
skullOwner = PaperAdapter.ADAPTER.getSkullOwner(skull);
|
||||
skullSkin = PaperAdapter.ADAPTER.getSkullSkin(skull);
|
||||
skullOwner = PaperAdapter.ADAPTER.getSkullOwner(skull);
|
||||
skullSkin = PaperAdapter.ADAPTER.getSkullSkin(skull);
|
||||
if ((skullOwner != null && skullOwner.length() > 0) || (skullSkin != null && skullSkin.length() > 0)) {
|
||||
ResultSet resultSet = SkullStatement.insert(preparedStmt2, time, skullOwner, skullSkin);
|
||||
if (Database.hasReturningKeys()) {
|
||||
resultSet.next();
|
||||
@@ -53,7 +53,7 @@ public class SkullPlaceLogger {
|
||||
BlockPlaceLogger.log(preparedStmt, batchCount, user, block, replaceType, replaceData, type, skullKey, true, null, null, null);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loaded 100 of 242 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user