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 | ||
|
|
2979af360c | ||
|
|
0712545345 | ||
|
|
d3091f9401 | ||
|
|
de5a064c8d | ||
|
|
1f60dcc3cf | ||
|
|
5276dc57d2 | ||
|
|
49c0f16934 | ||
|
|
322c630af4 | ||
|
|
251b4c56cd | ||
|
|
9de1d16836 | ||
|
|
f5109122ac | ||
|
|
4a8dd716f4 | ||
|
|
6572946b3d | ||
|
|
51d4bf27cd | ||
|
|
d30f6cf8d5 | ||
|
|
f96556a61f | ||
|
|
813fee1017 | ||
|
|
3b58f69263 | ||
|
|
3158fe5268 | ||
|
|
150bd4b0ce | ||
|
|
5ee33c7790 | ||
|
|
d49a8bee73 | ||
|
|
abb0ece3e5 | ||
|
|
8b3e37774a | ||
|
|
6155d4e864 | ||
|
|
252de2f233 | ||
|
|
cec40e384c | ||
|
|
86d164e4b0 | ||
|
|
b3abb70744 | ||
|
|
2373a9c19f | ||
|
|
105d14f11f | ||
|
|
942430c11c | ||
|
|
dcb0864013 | ||
|
|
a4ffbb642c |
No files matched your search
+3
-1
@@ -3,6 +3,8 @@ daysUntilClose: 7
|
||||
exemptLabels:
|
||||
- 'accepted'
|
||||
- 'bug'
|
||||
- 'confirmed bug (tested)'
|
||||
- 'potential bug (needs testing)'
|
||||
- 'suggestion'
|
||||
- 'help wanted'
|
||||
staleLabel: stale
|
||||
@@ -10,4 +12,4 @@ markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
closeComment: false
|
||||
closeComment: false
|
||||
@@ -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.0</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/).*
|
||||
@@ -0,0 +1,530 @@
|
||||
# API Version 11
|
||||
|
||||
The CoreProtect API enables you to log your own block changes, perform lookups, rollbacks, restores, and more.
|
||||
|
||||
| API Details | |
|
||||
| --- | --- |
|
||||
| **API Version:** | 11 |
|
||||
| **Plugin Version:** | v23.1+ |
|
||||
| **Maven:** | [maven.playpro.com](https://maven.playpro.com) |
|
||||
|
||||
---
|
||||
|
||||
## Upgrading from API v10
|
||||
|
||||
The changes from the previous API version are as follows:
|
||||
|
||||
- The following event was extended to include Location (mutable):
|
||||
```java
|
||||
CoreProtectPreLogEvent(String user, Location location)
|
||||
```
|
||||
- The old constructor remains for backward compatibility and is deprecated:
|
||||
```java
|
||||
@Deprecated
|
||||
CoreProtectPreLogEvent(String user)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Started
|
||||
|
||||
Ensure you're using CoreProtect 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:
|
||||
|
||||
```java
|
||||
import net.coreprotect.CoreProtect;
|
||||
import net.coreprotect.CoreProtectAPI;
|
||||
|
||||
private CoreProtectAPI getCoreProtect() {
|
||||
Plugin plugin = getServer().getPluginManager().getPlugin("CoreProtect");
|
||||
|
||||
// Check that CoreProtect is loaded
|
||||
if (plugin == null || !(plugin instanceof CoreProtect)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check that the API is enabled
|
||||
CoreProtectAPI CoreProtect = ((CoreProtect) plugin).getAPI();
|
||||
if (CoreProtect.isEnabled() == false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check that a compatible version of the API is loaded
|
||||
if (CoreProtect.APIVersion() < 11) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return CoreProtect;
|
||||
}
|
||||
```
|
||||
|
||||
With this code, you can then access the API with a call like the following:
|
||||
|
||||
```java
|
||||
CoreProtectAPI api = getCoreProtect();
|
||||
if (api != null){ // Ensure we have access to the API
|
||||
api.testAPI(); // Will print out "[CoreProtect] API test successful." in the console.
|
||||
}
|
||||
```
|
||||
|
||||
Yay, you're now using the CoreProtect API!
|
||||
|
||||
---
|
||||
|
||||
## API Overview
|
||||
|
||||
### Available Methods
|
||||
|
||||
```java
|
||||
boolean isEnabled()
|
||||
|
||||
void testAPI()
|
||||
|
||||
List<String[]> performLookup(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> performRollback(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> performRestore(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)
|
||||
|
||||
List<String[]> blockLookup(Block block, int time)
|
||||
|
||||
List<String[]> sessionLookup(String user, int time)
|
||||
|
||||
List<String[]> queueLookup(Block block)
|
||||
|
||||
ParseResult parseResult(String[] result)
|
||||
|
||||
boolean logChat(Player player, String message)
|
||||
|
||||
boolean logCommand(Player player, String command)
|
||||
|
||||
boolean logPlacement(String user, BlockState blockState)
|
||||
|
||||
boolean logPlacement(String user, Location location, Material type, BlockData blockData)
|
||||
|
||||
boolean logRemoval(String user, BlockState blockState)
|
||||
|
||||
boolean logRemoval(String user, Location location, Material type, BlockData blockData)
|
||||
|
||||
boolean logContainerTransaction(String user, Location location)
|
||||
|
||||
boolean logInteraction(String user, Location location)
|
||||
|
||||
boolean hasPlaced(String user, Block block, int time, int offset)
|
||||
|
||||
boolean hasRemoved(String user, Block block, int time, int offset)
|
||||
|
||||
void performPurge(int time)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Available Events
|
||||
|
||||
The following events are emitted by CoreProtect.
|
||||
|
||||
#### CoreProtectPreLogEvent
|
||||
|
||||
Fired when a CoreProtect logger is about to log an action. Cancellable.
|
||||
|
||||
| Property | Description | Mutable |
|
||||
| --- | --- | --- |
|
||||
| User | The name of the user under which this action will be logged. | Yes |
|
||||
| Location | The location where the action will be logged. | Yes |
|
||||
| Cancelled | If cancelled, the action won't be logged to the database. | Yes |
|
||||
|
||||
---
|
||||
|
||||
### Method Usage
|
||||
|
||||
*Detailed method information is listed below.*
|
||||
|
||||
#### `isEnabled()`
|
||||
|
||||
Calling this will return true if the server has the CoreProtect API enabled, and false if it does not.
|
||||
|
||||
---
|
||||
|
||||
#### `testAPI()`
|
||||
|
||||
Running this will print out "[CoreProtect] API Test Successful." in the server console.
|
||||
|
||||
---
|
||||
|
||||
#### `performLookup(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)`
|
||||
|
||||
This will perform a lookup.
|
||||
|
||||
* **time:** Specify the amount of time to search back. "5" would return results from the last 5 seconds.
|
||||
* **restrict_users:** Specify any usernames to perform the lookup on. Can be set to "null" if both a radius and a location are specified.
|
||||
* **exclude_users:** Specify any usernames to exclude from the lookup. Can be set to "null".
|
||||
* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the search to. Can be set to "null".
|
||||
* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the search. Can be set to "null".
|
||||
* **action_list:** Specify a list of action types to restrict the search to. Can be set to "null"
|
||||
* **radius:** Specify a radius to restrict the search to. A location must be specified if using this. Set to "0" to disable.
|
||||
* **radius_location:** Specify a location to search around. Can be set to "null" if no radius is specified, and a user is specified.
|
||||
|
||||
---
|
||||
|
||||
#### `performRollback(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)`
|
||||
|
||||
This will perform a rollback. Method must be called async.
|
||||
|
||||
* **time:** Specify the amount of time to rollback. "5" would return results from the last 5 seconds.
|
||||
* **restrict_users:** Specify any usernames to perform the rollback on. Can be set to "null" if both a radius and a location are specified.
|
||||
* **exclude_users:** Specify any usernames to exclude from the rollback. Can be set to "null".
|
||||
* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the rollback to. Can be set to "null".
|
||||
* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the rollback. Can be set to "null".
|
||||
* **action_list:** Specify a list of action types to restrict the rollback to. Can be set to "null"
|
||||
* **radius:** Specify a radius to restrict the rollback to. A location must be specified if using this. Set to "0" to disable.
|
||||
* **radius_location:** Specify a location to rollback around. Can be set to "null" if no radius is specified, and a user is specified.
|
||||
|
||||
---
|
||||
|
||||
#### `performRestore(int time, List<String> restrict_users, List<String> exclude_users, List<Object> restrict_blocks, List<Object> exclude_blocks, List<Integer> action_list, int radius, Location radius_location)`
|
||||
|
||||
This will perform a restore.
|
||||
|
||||
* **time:** Specify the amount of time to restore. "5" would return results from the last 5 seconds.
|
||||
* **restrict_users:** Specify any usernames to perform the restore on. Can be set to "null" if both a radius and a location are specified.
|
||||
* **exclude_users:** Specify any usernames to exclude from the restore. Can be set to "null".
|
||||
* **restrict_blocks:** Specify a list of EntityType's or Material's to restrict the restore to. Can be set to "null".
|
||||
* **exclude_blocks:** Specify a list of EntityType's or Material's to exclude from the restore. Can be set to "null".
|
||||
* **action_list:** Specify a list of action types to restrict the restore to. Can be set to "null"
|
||||
* **radius:** Specify a radius to restrict the restore to. A location must be specified if using this. Set to "0" to disable.
|
||||
* **radius_location:** Specify a location to restore around. Can be set to "null" if no radius is specified, and a user is specified.
|
||||
|
||||
---
|
||||
|
||||
#### `blockLookup(Block block, int time)`
|
||||
|
||||
This will perform a full lookup on a single block.
|
||||
|
||||
* **block:** The block to perform the lookup on.
|
||||
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
|
||||
|
||||
---
|
||||
|
||||
#### `queueLookup(Block block)`
|
||||
|
||||
This will search the consumer queue for changes on a block not yet saved in the database.
|
||||
|
||||
* **block:** The block to perform the lookup on.
|
||||
|
||||
---
|
||||
|
||||
#### `sessionLookup(String user, int time)`
|
||||
|
||||
This will perform a session lookup on a single player.
|
||||
|
||||
* **user:** The username to perform the lookup on.
|
||||
* **time:** Specify the amount of time to lookup. "5" would return results from the last 5 seconds.
|
||||
|
||||
---
|
||||
|
||||
#### `ParseResult parseResult(String[] result)`
|
||||
|
||||
This will parse results from a lookup. You'll then be able to view the following:
|
||||
|
||||
* **getX():** Get the X coordinate of the block.
|
||||
* **getY():** Get the Y coordinate of the block.
|
||||
* **getZ():** Get the Z coordinate of the block.
|
||||
* **getType():** Get the Material of the block.
|
||||
* **getBlockData():** Get the BlockData of the block.
|
||||
* **getPlayer():** Get the username as a string.
|
||||
* **getTimestamp():** Get the time of the action.
|
||||
* **getActionId():** Get the action ID. (0=removed, 1=placed, 2=interaction)
|
||||
* **getActionString():** Get the action as a string. (Removal, Placement, Interaction)
|
||||
* **isRolledBack():** If the block is currently rolled back or not.
|
||||
* **worldName():** The name of the world the block is located in.
|
||||
|
||||
---
|
||||
|
||||
#### `logPlacement(String user, BlockState blockState)`
|
||||
|
||||
This will log a block as being placed. *(Thread safe)*
|
||||
|
||||
* **user:** Specify the username to log as having placed the block.
|
||||
* **blockState:** Specify the BlockState of the block you're logging.
|
||||
|
||||
---
|
||||
|
||||
#### `logPlacement(String user, Location location, Material type, BlockData blockData)`
|
||||
|
||||
This will log a block as being placed.
|
||||
|
||||
* **user:** Specify the username to log as having placed the block.
|
||||
* **location:** Specify the location of the block you're logging.
|
||||
* **type:** Specify the Material of the block you're logging.
|
||||
* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null".
|
||||
|
||||
---
|
||||
|
||||
#### `logRemoval(String user, BlockState blockState)`
|
||||
|
||||
This will log a block as being removed/broken. *(Thread safe)*
|
||||
|
||||
* **user:** Specify the username to log as having removed the block.
|
||||
* **blockState:** Specify the BlockState of the block you're logging.
|
||||
|
||||
---
|
||||
|
||||
#### `logRemoval(String user, Location location, Material type, BlockData blockData)`
|
||||
|
||||
This will log a block as being removed/broken, and will log the block's inventory (if applicable).
|
||||
|
||||
* **user:** Specify the username to log as having removed the block.
|
||||
* **location:** Specify the location of the block you're logging.
|
||||
* **type:** Specify the Material of the block you're logging.
|
||||
* **blockData:** Specify the BlockData of the block you're logging. Can be set to "null".
|
||||
|
||||
---
|
||||
|
||||
#### `logContainerTransaction(String user, Location location)`
|
||||
|
||||
This will log any transactions made to a block's inventory immediately after calling the method.
|
||||
|
||||
* **user:** Specify the username to log as having added/removed the items.
|
||||
* **location:** Specify the location of the block inventory you're logging.
|
||||
|
||||
---
|
||||
|
||||
#### `logInteraction(String user, Location location)`
|
||||
|
||||
This will log a block as having been interacted with.
|
||||
|
||||
* **user:** Specify the username to log as having caused the interaction.
|
||||
* **location:** Specify the location of the interaction you're logging.
|
||||
|
||||
---
|
||||
|
||||
#### `hasPlaced(String user, Block block, int time, int offset)`
|
||||
|
||||
This will return true if a user has already placed a block at the location within the specified time limit.
|
||||
|
||||
* **user:** The username you're checking to see if they've placed a block already.
|
||||
* **block:** The block you're checking.
|
||||
* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks.
|
||||
* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0 = no offset)
|
||||
|
||||
---
|
||||
|
||||
#### `hasRemoved(String user, Block block, int time, int offset)`
|
||||
|
||||
This will return true if a user has already removed a block at the location within the specified time limit.
|
||||
|
||||
* **user:** The username you're checking to see if they've removed a block already.
|
||||
* **block:** The block you're checking.
|
||||
* **time:** How far back to check. "5" would only check through the last 5 seconds of logged blocks.
|
||||
* **offset:** A time offset. "2" would ignore the last 2 seconds of most recently ignored data. (0 = no offset)
|
||||
|
||||
---
|
||||
|
||||
#### `performPurge(int time)`
|
||||
|
||||
This will perform a purge on the CoreProtect database.
|
||||
|
||||
* **time:** Purge any data earlier than this. "120" would purge any data older than 120 seconds (2 minutes).
|
||||
|
||||
---
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
- Get the last 60 seconds of block data for the user "Notch".
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<String[]> lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, null, null, 0, null);
|
||||
if (lookup != null){
|
||||
for (String[] result : lookup){
|
||||
ParseResult parseResult = CoreProtect.parseResult(result);
|
||||
int x = parseResult.getX();
|
||||
int y = parseResult.getY();
|
||||
int z = parseResult.getZ();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Get the last 60 seconds of block data for the user "Notch", excluding dirt and grass blocks.
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<Object> exclude = Arrays.asList(Material.DIRT, Material.GRASS);
|
||||
List<String[]> lookup = CoreProtect.performLookup(60, Arrays.asList("Notch"), null, null, exclude, null, 0, null);
|
||||
if (lookup != null){
|
||||
for (String[] value : lookup){
|
||||
ParseResult result = CoreProtect.parseResult(value);
|
||||
int x = result.getX();
|
||||
int y = result.getY();
|
||||
int z = result.getZ();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Get the last 60 seconds of block data within 5 blocks of a location.
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<String[]> lookup = CoreProtect.performLookup(60, null, null, null, null, null, 5, location);
|
||||
if (lookup != null){
|
||||
for (String[] value : lookup){
|
||||
ParseResult result = CoreProtect.parseResult(value);
|
||||
int x = result.getX();
|
||||
int y = result.getY();
|
||||
int z = result.getZ();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Rollbacks / restores use the same code structure as the above examples. For example:
|
||||
```java
|
||||
class BasicThread implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<String[]> lookup = CoreProtect.performRollback(60, Arrays.asList("Notch"), null, null, null, null, 0, null);
|
||||
if (lookup != null){
|
||||
for (String[] value : lookup){
|
||||
ParseResult result = CoreProtect.parseResult(value);
|
||||
int x = result.getX();
|
||||
int y = result.getY();
|
||||
int z = result.getZ();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Runnable runnable = new BasicThread();
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.start();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Check if the user "Notch" has already placed a block at a location within the last 60 seconds.
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
boolean hasPlaced = CoreProtect.hasPlaced("Notch", block, 60, 0);
|
||||
|
||||
// Search queue for pending changes
|
||||
if (!hasPlaced){
|
||||
List<String[]> lookup = CoreProtect.queueLookup(block);
|
||||
for (String[] result : lookup){
|
||||
ParseResult parseResult = CoreProtect.parseResult(result);
|
||||
if (parseResult.getActionId()==1 && parseResult.getPlayer().equals("Notch")){
|
||||
hasPlaced = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Get the last 60 seconds of block data for a specific block.
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<String[]> lookup = CoreProtect.blockLookup(block, 60);
|
||||
if (lookup != null){
|
||||
for (String[] result : lookup){
|
||||
ParseResult parseResult = CoreProtect.parseResult(result);
|
||||
int x = parseResult.getX();
|
||||
int y = parseResult.getY();
|
||||
int z = parseResult.getZ();
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Get the last 1 day of session data for the user "Notch".
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
List<String[]> lookup = CoreProtect.sessionLookup("Notch", (24 * 60 * 60));
|
||||
if (lookup != null){
|
||||
for (String[] result : lookup){
|
||||
ParseResult parseResult = CoreProtect.parseResult(result);
|
||||
int x = parseResult.getX();
|
||||
int y = parseResult.getY();
|
||||
int z = parseResult.getZ();
|
||||
int action = parseResult.getActionId(); // 0 = logout, 1 = login
|
||||
// ...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Log the placement of a block at a location by the user "Notch".
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
boolean success = CoreProtect.logPlacement("Notch", block.getLocation(), block.getType(), block.getData());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Log adding/remove items in a chest (or some other block inventory).
|
||||
```java
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
boolean success = CoreProtect.logContainerTransaction("Notch", inventory.getLocation());
|
||||
// modify your container contents immediately after (e.g. [i]inventory.addItem(itemStack);[/i])
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
- Perform a multi-threaded placement check to see if the user "Notch" has already placed a block at a location within the last 60 seconds. This ignores the most recent 1 second of logged data, to account for the fact that that new block data may have already been logged, depending on your code.
|
||||
```java
|
||||
final Block block = null; //Should be an actual block
|
||||
class BasicThread implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
CoreProtectAPI CoreProtect = getCoreProtect();
|
||||
if (CoreProtect != null){ // Ensure we have access to the API
|
||||
boolean hasPlaced = CoreProtect.hasPlaced("Notch", block, 60, 1);
|
||||
}
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
Runnable runnable = new BasicThread();
|
||||
Thread thread = new Thread(runnable);
|
||||
thread.start();
|
||||
```
|
||||
|
||||
---
|
||||
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
|
||||
@@ -16,6 +16,7 @@ ___
|
||||
| [/co reload](#co-reload) | Reload the configuration file |
|
||||
| [/co status](#co-status) | View the plugin status |
|
||||
| [/co consumer](#co-consumer) | Toggle consumer processing |
|
||||
| [/co migrate-db](#co-migrate-db) | Migrate between SQLite and MySQL |
|
||||
|
||||
### Alias Commands
|
||||
|
||||
@@ -128,6 +129,19 @@ ___
|
||||
Console command to pause or resume consumer queue processing.
|
||||
___
|
||||
|
||||
### /co migrate-db
|
||||
Migrate your CoreProtect database between SQLite and MySQL. Console-only command.
|
||||
|
||||
| Command | Parameters |
|
||||
| --- | --- |
|
||||
| /co migrate-db | `<sqlite|mysql>` |
|
||||
|
||||
> **Note:** This feature is exclusive to CoreProtect 23.0+ Patreon builds for Patron supporters.
|
||||
|
||||
For complete migration instructions, safety guidelines, and troubleshooting information, see the [Database Migration documentation](/database-migration/).
|
||||
|
||||
___
|
||||
|
||||
|
||||
## Parameter Details
|
||||
|
||||
|
||||
+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.*
|
||||
@@ -0,0 +1,145 @@
|
||||
# Database Migration (SQLite ↔ MySQL)
|
||||
|
||||
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](http://patreon.com/coreprotect) for Patron supporters.
|
||||
|
||||
## Overview
|
||||
|
||||
The `/co migrate-db` command allows you to seamlessly transfer all your CoreProtect data from SQLite to MySQL or vice versa. This is particularly useful when:
|
||||
|
||||
* Starting with SQLite and wanting to upgrade to MySQL for better performance
|
||||
* Moving from MySQL back to SQLite for simpler server setups
|
||||
* Transferring data between different server configurations
|
||||
|
||||
## Command Usage
|
||||
|
||||
| Command | Parameters | Description |
|
||||
| --- | --- | --- |
|
||||
| `/co migrate-db` | `<sqlite|mysql>` | Migrate to the specified database type |
|
||||
|
||||
**Examples:**
|
||||
|
||||
* `/co migrate-db mysql` - Migrate from SQLite to MySQL
|
||||
* `/co migrate-db sqlite` - Migrate from MySQL to SQLite
|
||||
|
||||
> **Console Only:** This command can only be executed from the server console, not from in-game.
|
||||
|
||||
---
|
||||
|
||||
## Migration Process
|
||||
|
||||
### Step 1: Preparation
|
||||
|
||||
**Before starting the migration:**
|
||||
|
||||
1. Ensure your server is running with your current CoreProtect database
|
||||
2. Configure your new database in `config.yml` (ensure `use-mysql` is updated correctly)
|
||||
3. **Important:** Do NOT restart your server or use `/co reload` after modifying the config
|
||||
|
||||
### Step 2: Execute Migration
|
||||
|
||||
#### 1. **Run the migration command from your server console:**
|
||||
```
|
||||
co migrate-db <mysql|sqlite>
|
||||
```
|
||||
|
||||
#### 2. **Monitor the progress:**
|
||||
* The migration will display detailed progress information
|
||||
* Large databases may take considerable time to complete
|
||||
* Progress bars and speed indicators will show current status
|
||||
|
||||
#### 3. **Do not interrupt the process:**
|
||||
* Avoid restarting your server during migration
|
||||
* Let the process complete naturally
|
||||
|
||||
### Step 3: Post-Migration
|
||||
|
||||
**After successful completion:**
|
||||
|
||||
1. **Automatic switchover:** CoreProtect will automatically begin using the new database
|
||||
2. **Verify configuration:** Ensure `use-mysql` is set correctly in your `config.yml` as per step 1
|
||||
3. **Test functionality:** Perform basic CoreProtect operations to verify everything works
|
||||
4. **Clean up:** Once satisfied, you may manually delete your old database files
|
||||
|
||||
---
|
||||
|
||||
## Important Considerations
|
||||
|
||||
### Migration Safety
|
||||
|
||||
* **Non-destructive process:** The migration does not modify or delete your existing database
|
||||
* **Interrupted migration:** If something goes wrong, simply delete the new database and continue using the old one
|
||||
* **Data verification:** The process includes automatic verification to ensure data integrity
|
||||
|
||||
### Performance & Requirements
|
||||
|
||||
* **Processing time:** Large databases with millions of records may take hours to migrate
|
||||
* **Resource usage:** The migration process is resource-intensive and may impact server performance
|
||||
* **Parallel processing:** SQLite to MySQL migrations use optimized parallel processing for better speed
|
||||
|
||||
### Restrictions & Limitations
|
||||
|
||||
* **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](http://patreon.com/coreprotect)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Migration won't start:**
|
||||
|
||||
* 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
|
||||
|
||||
**Migration interrupted:**
|
||||
|
||||
* Manually delete/wipe the target database
|
||||
* Verify server stability before restarting migration
|
||||
* Consider migrating during low-activity periods
|
||||
|
||||
**Performance issues:**
|
||||
|
||||
* Monitor server resources during migration
|
||||
* Consider temporarily reducing server activity
|
||||
* Large tables may cause temporary slowdowns
|
||||
|
||||
**Data verification failures:**
|
||||
|
||||
* Check database connectivity and permissions
|
||||
* Review server logs for specific error messages
|
||||
* Ensure sufficient disk space on target database
|
||||
|
||||
### Getting Help
|
||||
|
||||
If you encounter issues with database migration:
|
||||
|
||||
1. Check server logs for detailed error messages
|
||||
2. Verify database permissions and connectivity
|
||||
3. Ensure adequate system resources (RAM, CPU, disk space)
|
||||
4. Contact support through the CoreProtect Discord with specific error details
|
||||
|
||||
---
|
||||
|
||||
## Technical Details
|
||||
|
||||
The migration process includes several advanced features:
|
||||
|
||||
* Batch processing with dynamic sizing based on performance
|
||||
* Automatic retry mechanisms for temporary failures
|
||||
* Data integrity verification comparing source and target records
|
||||
* Progress tracking with estimated completion times
|
||||
* Graceful error handling with detailed logging
|
||||
|
||||
The migration handles all CoreProtect data types including:
|
||||
|
||||
* Block changes and rollbacks
|
||||
* Container transactions
|
||||
* Player interactions and sessions
|
||||
* Chat messages and commands
|
||||
* User data and statistics
|
||||
* All metadata and configuration data
|
||||
@@ -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.
|
||||
@@ -18,6 +20,12 @@ A list of all language codes that can be used with CoreProtect.
|
||||
[**CoreProtect API Documentation**](/api/)
|
||||
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.
|
||||
|
||||
|
||||
@@ -9,37 +9,113 @@ These plugins/tools are maintained by third parties, and may have issues outside
|
||||
## Plugins
|
||||
|
||||
* **WorldEdit**
|
||||
Use WorldEdit selections as a radius, and log your WorldEdit changes.
|
||||
Use WorldEdit selections as a radius, and log your WorldEdit changes.
|
||||
[https://dev.bukkit.org/projects/worldedit](https://dev.bukkit.org/projects/worldedit)
|
||||
|
||||
|
||||
* **CoreProtect-Anti-Xray**
|
||||
Displays how many ores a player has destroyed in a specific time span.
|
||||
Displays how many ores a player has destroyed in a specific time span.
|
||||
[https://dev.bukkit.org/bukkit-plugins/coreprotect-anti-xray/](https://dev.bukkit.org/bukkit-plugins/coreprotect-anti-xray/)
|
||||
|
||||
|
||||
* **CoreProtect TNT**
|
||||
The CoreProtect TNT extension adds logging for TNT and creeper explosion sources.
|
||||
The CoreProtect TNT extension adds logging for TNT and creeper explosion sources.
|
||||
[https://www.spigotmc.org/resources/coreprotect-tnt-log-tnt-creeper-explode-source.69609/](https://www.spigotmc.org/resources/coreprotect-tnt-log-tnt-creeper-explode-source.69609/)
|
||||
|
||||
|
||||
* **CoreProtect Time-Lapse**
|
||||
CPTL is an add-on tool for CoreProtect used to create a time-lapse from historical data.
|
||||
CPTL is an add-on tool for CoreProtect used to create a time-lapse from historical data.
|
||||
[https://modrinth.com/plugin/cptl](https://modrinth.com/plugin/cptl)
|
||||
|
||||
|
||||
* **LightUp**
|
||||
Conveniently place temporary lighting with rollback safety via CoreProtect integration.
|
||||
[https://modrinth.com/plugin/lightup](https://modrinth.com/plugin/lightup)
|
||||
|
||||
|
||||
* **Lumen**
|
||||
Custom (virtual) lighting with undo/redo and built-in CoreProtect & FAWE integration.
|
||||
[https://modrinth.com/plugin/lumen](https://modrinth.com/plugin/lumen)
|
||||
|
||||
|
||||
* **FRTrustSystem**
|
||||
Simple trust/friends system that uses the CoreProtect API to determine block ownership for protections/notifications.
|
||||
[https://modrinth.com/plugin/frtrustsystem](https://modrinth.com/plugin/frtrustsystem)
|
||||
|
||||
|
||||
* **Movecraft-CoreProtect**
|
||||
Logs Movecraft “craft” movement into CoreProtect for auditing/rollback.
|
||||
[https://hangar.papermc.io/Airship-Pirates/Movecraft-CoreProtect](https://hangar.papermc.io/Airship-Pirates/Movecraft-CoreProtect)
|
||||
|
||||
|
||||
* **M0-CoreCord**
|
||||
Discord bridge for CoreProtect lookups and alerts (SQLite/MySQL supported).
|
||||
[https://www.spigotmc.org/resources/m0-corecord-1-13-1-21-8.91863/](https://www.spigotmc.org/resources/m0-corecord-1-13-1-21-8.91863/)
|
||||
|
||||
|
||||
* **XRayHunter**
|
||||
Hunt potential xrayers by analyzing ore-mining stats pulled from CoreProtect data.
|
||||
[https://modrinth.com/plugin/xrayhunter](https://modrinth.com/plugin/xrayhunter)
|
||||
|
||||
|
||||
* **ShadowTrace (Server Plugin)**
|
||||
Backend for the ShadowTrace client mod; queries CoreProtect to visualize players’ mined blocks in-game.
|
||||
[https://modrinth.com/plugin/shadowtraceplugin](https://modrinth.com/plugin/shadowtraceplugin)
|
||||
|
||||
|
||||
* **WildInspect**
|
||||
Custom inspect-mode powered by CoreProtect (with history/claim limits and more).
|
||||
[https://www.spigotmc.org/resources/%E2%9A%A1%EF%B8%8F-wildinspect-%E2%9A%A1%EF%B8%8F-coreprotect-addon-history-limits-claim-limits-%E2%9A%A1%EF%B8%8F-1-21-5-support.87405/](https://www.spigotmc.org/resources/%E2%9A%A1%EF%B8%8F-wildinspect-%E2%9A%A1%EF%B8%8F-coreprotect-addon-history-limits-claim-limits-%E2%9A%A1%EF%B8%8F-1-21-5-support.87405/)
|
||||
|
||||
|
||||
* **ExplosionProtector**
|
||||
Uses the CoreProtect API to prevent explosions from destroying player-placed blocks.
|
||||
[https://www.spigotmc.org/resources/explosionprotector.124838/](https://www.spigotmc.org/resources/explosionprotector.124838/)
|
||||
|
||||
|
||||
* **Axiom Paper Plugin**
|
||||
Server component for the Axiom editor; includes CoreProtect integration to log Axiom edits.
|
||||
[https://modrinth.com/plugin/axiom-paper-plugin](https://modrinth.com/plugin/axiom-paper-plugin)
|
||||
|
||||
|
||||
* **BlocksHub**
|
||||
Bridge API used by world-editing plugins (e.g., AWE/FAWE) to send edits to loggers like CoreProtect.
|
||||
[https://www.spigotmc.org/resources/blockshub.331/](https://www.spigotmc.org/resources/blockshub.331/)
|
||||
|
||||
|
||||
* **SpitSTIK**
|
||||
Fun projectile plugin with CoreProtect integration for item-frame logging.
|
||||
[https://modrinth.com/plugin/spitstik](https://modrinth.com/plugin/spitstik)
|
||||
|
||||
|
||||
* **XRay Informer**
|
||||
Ore-ratio checker that supports CoreProtect. *(last known MC: 1.12)*
|
||||
[https://dev.bukkit.org/projects/xray-informer](https://dev.bukkit.org/projects/xray-informer)
|
||||
|
||||
|
||||
* **DesirePaths**
|
||||
Logs automatically generated paths into CoreProtect for moderation/rollback.
|
||||
[https://www.spigotmc.org/resources/desirepaths-dynamic-player-made-trails.109043/](https://www.spigotmc.org/resources/desirepaths-dynamic-player-made-trails.109043/)
|
||||
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
* **CoreProtect Lookup Web Interface**
|
||||
Search through your CoreProtect history with an easy-to-use interface.
|
||||
Search through your CoreProtect history with an easy-to-use web UI.
|
||||
[https://www.spigotmc.org/resources/coreprotect-lookup-web-interface.28033/](https://www.spigotmc.org/resources/coreprotect-lookup-web-interface.28033/)
|
||||
|
||||
|
||||
* **Watson**
|
||||
Watson is a client side Minecraft mod that displays CoreProtect logs in 3D.
|
||||
Client-side mod that displays CoreProtect logs in 3D (optional server helper plugin available).
|
||||
[https://github.com/vacla/Watson](https://github.com/vacla/Watson)
|
||||
|
||||
|
||||
* **ShadowTrace (Client Mod)**
|
||||
Client-side visualizer to view mined-block locations supplied by the ShadowTrace server plugin via CoreProtect.
|
||||
[https://modrinth.com/mod/shadowtrace](https://modrinth.com/mod/shadowtrace)
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
|
||||
+54
-47
@@ -6,25 +6,26 @@ AMOUNT_CHUNK: "{0} {Chunk|Chunks}"
|
||||
AMOUNT_ENTITY: "{0} {Entität|Entitäten}"
|
||||
AMOUNT_ITEM: "{0} {Item|Items}"
|
||||
API_TEST: "API-Test erfolgreich."
|
||||
CACHE_ERROR: "WARNUNG: Fehler beim Validieren {0} Zwischenspeicher."
|
||||
CACHE_RELOAD: "Erzwingen des Nachladens von {kartierung|welt} Caches aus der Datenbank."
|
||||
CACHE_ERROR: "WARNUNG: Fehler beim Überprüfen des {0}-Zwischenspeichers."
|
||||
CACHE_RELOAD: "Erzwingen des Nachladens von {Kartierungs|Welt}caches aus der Datenbank."
|
||||
CHECK_CONFIG: "Bitte überprüfe die config.yml"
|
||||
COMMAND_CONSOLE: "Bitte führen Sie den Befehl von der Konsole aus."
|
||||
COMMAND_NOT_FOUND: "Befehl \"{0}\" nicht gefunden."
|
||||
COMMAND_THROTTLED: "Bitte warten Sie einen Moment und versuchen Sie es erneut."
|
||||
CONSUMER_ERROR: "Verbraucherwarteschlange wird bereits verarbeitet {angehalten|fortgesetzt}."
|
||||
CONSUMER_TOGGLED: "Die Verarbeitung der Verbraucherwarteschlange wurde durchgeführt {angehalten|fortgesetzt}."
|
||||
CONSUMER_ERROR: "Die Verarbeitung der Verbraucherwarteschlange wurde bereits {angehalten|fortgesetzt}."
|
||||
CONSUMER_TOGGLED: "Die Verarbeitung der Verbraucherwarteschlange wurde {angehalten|fortgesetzt}."
|
||||
CONTAINER_HEADER: "Containertransaktionen"
|
||||
CPU_CORES: "CPU-Kerne."
|
||||
DATABASE_BUSY: "Datenbank beschäftigt. Bitte versuchen Sie es später erneut."
|
||||
DATABASE_INDEX_ERROR: "Datenbankindizes können nicht validiert werden."
|
||||
DATABASE_INDEX_ERROR: "Datenbankindizes können nicht geprüft werden."
|
||||
DATABASE_LOCKED_1: "Datenbank gesperrt. Warte bis zu 15 Sekunden..."
|
||||
DATABASE_LOCKED_2: "Datenbank wird bereits verwendet. Bitte versuche es später erneut."
|
||||
DATABASE_LOCKED_3: "Um die Datenbanksperre zu deaktivieren, setzen Sie \"database-lock: false\"."
|
||||
DATABASE_LOCKED_4: "Das Deaktivieren der Datenbanksperre kann zu Datenbeschädigungen führen."
|
||||
DATABASE_LOCKED_4: "Deaktivieren der Datenbanksperre kann zu Datenbeschädigungen führen."
|
||||
DATABASE_UNREACHABLE: "Datenbank ist nicht erreichbar. Daten verwerfen und herunterfahren."
|
||||
DEVELOPMENT_BRANCH: "Entwicklungszweig erkannt, Patch-Skripte werden übersprungen."
|
||||
DIRT_BLOCK: "Platziere einen Schmutzblock unter dir."
|
||||
DISABLE_SUCCESS: "Erfolg! Deaktiviert {0}"
|
||||
DIRT_BLOCK: "Ein temporärer Sicherheitsblock wurde unter ihnen platziert."
|
||||
DISABLE_SUCCESS: "{0} erfolgreich deaktiviert!"
|
||||
ENABLE_FAILED: "{0} war nicht in der Lage zu starten."
|
||||
ENABLE_SUCCESS: "{0} ist jetzt aktiviert!"
|
||||
ENJOY_COREPROTECT: "Dir gefällt {0}? Tritt unserem Discord bei!"
|
||||
@@ -32,11 +33,11 @@ FINISHING_CONVERSION: "Abschluss der Datenkonvertierung. Bitte warten..."
|
||||
FINISHING_LOGGING: "Abschluss der Datenprotokollierung. Bitte warten..."
|
||||
FIRST_VERSION: "Anfangs-DB: {0}"
|
||||
GLOBAL_LOOKUP: "Geben Sie keinen Radius an, um eine globale Suche durchzuführen."
|
||||
GLOBAL_ROLLBACK: "Benutze \"{0}\" um einen globalen {Rollback|Restore}"
|
||||
GLOBAL_ROLLBACK: "Benutze \"{0}\" für einen globalen {Rollback|Restore}"
|
||||
HELP_ACTION_1: "Beschränken Sie die Suche auf eine Aktion."
|
||||
HELP_ACTION_2: "Beispiele: [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: "Zusätzliche Informationen anzeigen."
|
||||
HELP_EXCLUDE_1: "Blöcke/Benutzer ausschließen."
|
||||
HELP_EXCLUDE_1: "Bestimmte Blöcke/Benutzer ausschließen."
|
||||
HELP_EXCLUDE_2: "Beispiele: [e:stone], [e:Notch], [e:stone,Notch]"
|
||||
HELP_HEADER: "{0} Hilfe"
|
||||
HELP_INCLUDE_1: "Fügen Sie Blöcke/Entitäten ein."
|
||||
@@ -73,19 +74,19 @@ HELP_ROLLBACK_COMMAND: "Rollback-Blockdaten."
|
||||
HELP_STATUS: "Sehen Sie sich den Plugin-Status an."
|
||||
HELP_STATUS_COMMAND: "Zeigt den Plugin-Status an."
|
||||
HELP_TELEPORT: "Teleportieren."
|
||||
HELP_TIME_1: "Geben Sie die Uhrzeit an."
|
||||
HELP_TIME_1: "Geben Sie einen Zeitraum an."
|
||||
HELP_TIME_2: "Beispiele: [t:2w,5d,7h,2m,10s], [t:5d2h], [t:2.50h]"
|
||||
HELP_USER_1: "Geben Sie die Benutzer an."
|
||||
HELP_USER_1: "Geben Sie den/die Benutzer an."
|
||||
HELP_USER_2: "Beispiele: [u:Notch], [u:Notch,#enderman]"
|
||||
INCOMPATIBLE_ACTION: "\"{0}\" kann mit dieser Aktion nicht verwendet werden."
|
||||
INSPECTOR_ERROR: "Inspektor bereits {aktiviert|deaktiviert}."
|
||||
INSPECTOR_TOGGLED: "Inspektor jetzt {aktiviert|deaktiviert}."
|
||||
INTEGRATION_ERROR: "Unfähig zu {initialisieren|deaktivieren} {0} Protokollierung."
|
||||
INTEGRATION_SUCCESS: "{0} erfolgreich anmelden {initialisiert|deaktiviert}."
|
||||
INTEGRATION_VERSION: "Ungültig {0} Version gefunden."
|
||||
INTEGRATION_ERROR: "Unfähig, {0} Protokollierung zu {initialisieren|deaktivieren}."
|
||||
INTEGRATION_SUCCESS: "{0} Protokollierung erfolgreich {initialisiert|deaktiviert}."
|
||||
INTEGRATION_VERSION: "Ungültige {0} Version gefunden."
|
||||
INTERACTIONS_HEADER: "Spielerinteraktionen"
|
||||
INVALID_ACTION: "Das ist keine gültige Aktion."
|
||||
INVALID_BRANCH_1: "Ungültige Plugin-Version (Verzweigung wurde nicht gesetzt)."
|
||||
INVALID_BRANCH_1: "Ungültige Plugin-Version (Branch wurde nicht gesetzt)."
|
||||
INVALID_BRANCH_2: "Um fortzufahren, setzen Sie den Projektzweig auf \"Entwicklung\"."
|
||||
INVALID_BRANCH_3: "Das Ausführen von Entwicklungscode kann zu Datenbeschädigungen führen."
|
||||
INVALID_CONTAINER: "Bitte überprüfen Sie zuerst einen gültigen Behälter."
|
||||
@@ -102,7 +103,7 @@ LINK_DOWNLOAD: "Herunterladen: {0}"
|
||||
LINK_PATREON: "Patreon: {0}"
|
||||
LINK_WIKI_BLOCK: "Blocknamen: {0}"
|
||||
LINK_WIKI_ENTITY: "Entitätsnamen: {0}"
|
||||
LOGGING_ITEMS: "{0} Elemente, die noch zu loggen sind. Warten Sie mal..."
|
||||
LOGGING_ITEMS: "{0} Elemente, die noch zu loggen sind. Bitte warten..."
|
||||
LOGGING_TIME_LIMIT: "Zeitlimit für die Protokollierung erreicht. Daten verwerfen und herunterfahren."
|
||||
LOOKUP_BLOCK: "{0} {platziert|entfernt} {1}."
|
||||
LOOKUP_CONTAINER: "{0} {hinzugefügt|entfernt} {1} {2}."
|
||||
@@ -113,58 +114,62 @@ LOOKUP_LOGIN: "{0} {ein|aus}geloggt."
|
||||
LOOKUP_PAGE: "Seite {0}"
|
||||
LOOKUP_PROJECTILE: "{0} {geworfen|geschossen} {1} {2}."
|
||||
LOOKUP_ROWS_FOUND: "{0} {Reihe|Reihen} gefunden."
|
||||
LOOKUP_SEARCHING: "Suche nachschlagen. Warten Sie mal..."
|
||||
LOOKUP_SEARCHING: "Suchen. Bitte warten..."
|
||||
LOOKUP_STORAGE: "{0} {hinterlegt|abgehoben} {1} {2}."
|
||||
LOOKUP_TIME: "vor {0}"
|
||||
LOOKUP_USERNAME: "{0} Eingeloggt als {1}."
|
||||
MAXIMUM_RADIUS: "Das Maximum {Nachschlagen|Rollback|Wiederherstellen} Radius ist {0}."
|
||||
LOOKUP_USERNAME: "{0} eingeloggt als {1}."
|
||||
MAXIMUM_RADIUS: "Der maximale {Nachschlag|Rollback|Restore} Radius ist {0}."
|
||||
MISSING_ACTION_USER: "Um diese Aktion zu verwenden, geben Sie bitte einen Benutzer an."
|
||||
MISSING_LOOKUP_TIME: "Bitte geben Sie die Zeit an, um {Nachschlagen|Rollback|Wiederherstellen}."
|
||||
MISSING_LOOKUP_USER: "Bitte geben Sie einen Benutzer an oder {Block|Radius}."
|
||||
MISSING_LOOKUP_TIME: "Bitte geben Sie den Zeitraum an, um {Nachzuschlagen|ein Rollback auszuführen|einen Restore auszuführen}."
|
||||
MISSING_LOOKUP_USER: "Bitte geben Sie einen Benutzer oder {Block|Radius} an."
|
||||
MISSING_PARAMETERS: "Bitte verwenden Sie \"{0}\"."
|
||||
MISSING_ROLLBACK_RADIUS: "Sie haben nicht angegeben a {Zurücksetzen|Wiederherstellen} Radius."
|
||||
MISSING_ROLLBACK_USER: "Sie haben nicht angegeben a {Zurücksetzen|Wiederherstellen} Benutzer."
|
||||
MYSQL_UNAVAILABLE: "Verbindung zu nicht möglich MySQL Server."
|
||||
NO_DATA: "Keine Daten gefunden bei {0}."
|
||||
MISSING_ROLLBACK_RADIUS: "Sie haben keinen {Rollback|Restore} Radius angegeben."
|
||||
MISSING_ROLLBACK_USER: "Sie haben keinen {Rollback|Restore} Benutzer angegeben."
|
||||
MYSQL_UNAVAILABLE: "Verbindung zu MySQL Server nicht möglich."
|
||||
NETWORK_CONNECTION: "Verbindung von {0} {erfolgreich|fehlgeschlagen}. Nutze {1} {2}."
|
||||
NETWORK_TEST: "Netzwerktestdaten wurden erfolgreich gesendet."
|
||||
NO_DATA: "Keine Daten bei {0} gefunden."
|
||||
NO_DATA_LOCATION: "Keine {Daten|Transaktionen|Interaktionen|Nachrichten} gefunden."
|
||||
NO_PERMISSION: "Du hast keine Erlaubnis das zu tun."
|
||||
NO_RESULTS: "Keine Ergebnisse gefunden."
|
||||
NO_RESULTS_PAGE: "Keine {Ergebnisse|Daten} für diese Seite gefunden."
|
||||
NO_ROLLBACK: "Nein {ausstehend|zurück} Rollback/Wiederherstellung gefunden."
|
||||
PATCH_INTERRUPTED: "Upgrade unterbrochen. Werde es beim Neustart nochmal versuchen."
|
||||
PATCH_OUTDATED_1: "Datenbanken, die älter als sind, können nicht aktualisiert werden {0}."
|
||||
PATCH_OUTDATED_2: "Bitte aktualisieren Sie mit einer unterstützten Version von CoreProtect."
|
||||
PATCH_PROCESSING: "Verarbeitung neuer Daten. Warten Sie mal..."
|
||||
PATCH_SKIP_UPDATE: "Überspringen {Tabelle|Index} {Aktualisieren|Erstellen|Entfernen} auf {0}."
|
||||
PATCH_STARTED: "Performing {0} Aktualisierung. Warten Sie mal..."
|
||||
NO_ROLLBACK: "Kein(en) {ausstehende(s|n)|vorherige(s|n)} Rollback/Restore gefunden."
|
||||
PATCH_INTERRUPTED: "Upgrade unterbrochen. Wird bei einem Neustart erneut versucht."
|
||||
PATCH_OUTDATED_1: "Datenbanken, die älter als {0} sind, können nicht aktualisiert werden."
|
||||
PATCH_OUTDATED_2: "Bitte updaten Sie mit einer unterstützten Version von CoreProtect."
|
||||
PATCH_PROCESSING: "Neue Daten werden verarbeitet. Bitte warten..."
|
||||
PATCH_SKIP_UPDATE: "Überspringe {Tabellen|Index}{aktualisierung|erstellung|entfernung} bei {0}."
|
||||
PATCH_STARTED: "Führe {0} Upgrade durch. Bitte warten..."
|
||||
PATCH_SUCCESS: "Erfolgreich aktualisiert auf {0}."
|
||||
PATCH_UPGRADING: "Datenbank-Upgrade im Gange. Warten Sie mal..."
|
||||
PATCH_UPGRADING: "Datenbank-Upgrade im Gange. Bitte warten..."
|
||||
PLEASE_SELECT: "Bitte auswählen: \"{0}\" oder \"{1}\"."
|
||||
PREVIEW_CANCELLED: "Vorschau abgebrochen."
|
||||
PREVIEW_CANCELLING: "Vorschau abbrechen..."
|
||||
PREVIEW_IN_GAME: "Sie können Rollbacks nur im Spiel in der Vorschau anzeigen."
|
||||
PREVIEW_TRANSACTION: "Sie können keine Vorschau anzeigen {Behälter|Inventar} Transaktionen."
|
||||
PREVIEW_IN_GAME: "Sie können Rollbacks nur im Spiel als Vorschau anzeigen."
|
||||
PREVIEW_TRANSACTION: "Sie können keine {Behälter|Inventar}-Transaktionen als Vorschau anzeigen."
|
||||
PRIMARY_THREAD_ERROR: "Diese API-Methode kann nicht im Haupt-Thread verwendet werden."
|
||||
PURGE_ABORTED: "Bereinigung fehlgeschlagen. Die Datenbank ist möglicherweise beschädigt."
|
||||
PURGE_ERROR: "Kann nicht verarbeitet werden {0} Daten!"
|
||||
PURGE_ERROR: "{0} Daten können nicht verarbeitet werden!"
|
||||
PURGE_FAILED: "Bereinigung fehlgeschlagen. Bitte versuchen Sie es später erneut."
|
||||
PURGE_IN_PROGRESS: "Bereinigung läuft. Bitte versuchen Sie es später erneut."
|
||||
PURGE_MINIMUM_TIME: "Sie können nur Daten löschen, die älter sind als {0} {Tage|Stunden}."
|
||||
PURGE_MINIMUM_TIME: "Sie können nur Daten löschen, die älter als {0} {Tage|Stunden} sind."
|
||||
PURGE_NOTICE_1: "Bitte beachten Sie, dass dies einige Zeit dauern kann."
|
||||
PURGE_NOTICE_2: "Starten Sie Ihren Server nicht neu, bis dies abgeschlossen ist."
|
||||
PURGE_OPTIMIZING: "Optimierung der Datenbank. Warten Sie mal..."
|
||||
PURGE_PROCESSING: "wird bearbeitet {0} Daten..."
|
||||
PURGE_OPTIMIZING: "Optimierung der Datenbank. Bitte warten..."
|
||||
PURGE_PROCESSING: "{0} Daten werden verarbeitet..."
|
||||
PURGE_REPAIRING: "Versuch einer Reparatur. Dies könnte eine Weile dauern..."
|
||||
PURGE_ROWS: "{0} {Reihe|Reihen} von Daten gelöscht."
|
||||
PURGE_STARTED: "Datenbereinigung gestartet am \"{0}\"."
|
||||
PURGE_SUCCESS: "Datenbereinigung erfolgreich."
|
||||
RAM_STATS: "{0}GB / {1}GB RAM"
|
||||
RELOAD_STARTED: "Konfiguration wird neu geladen - bitte warten."
|
||||
RELOAD_SUCCESS: "Konfiguration erfolgreich neu geladen."
|
||||
ROLLBACK_ABORTED: "Rollback oder Wiederherstellung abgebrochen."
|
||||
ROLLBACK_ABORTED: "Rollback oder Restore abgebrochen."
|
||||
ROLLBACK_CHUNKS_FOUND: "{0} {bearbeiteter|bearbeitete} {Chunk|Chunks} gefunden."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "{0}/{1} {Chunk|Chunks} bearbeitet."
|
||||
ROLLBACK_COMPLETED: "{Rollback|Wiederherstellen|Vorschau} abgeschlossen für \"{0}\"."
|
||||
ROLLBACK_EXCLUDED_USERS: "Ausgeschlossen {Benutzer|Benutzer}: \"{0}\"."
|
||||
ROLLBACK_INCLUDE: "{Eingeschlossen|Ausgeschlossen} {Block|Entität|Ziel} {Typ|Typen}: \"{0}\"."
|
||||
ROLLBACK_COMPLETED: "{Rollback|Restore|Vorschau} für \"{0}\" abgeschlossen."
|
||||
ROLLBACK_EXCLUDED_USERS: "{Ausgeschlossener Benutzer|Ausgeschlossene Benutzer}: \"{0}\"."
|
||||
ROLLBACK_INCLUDE: "{Block|Entität|Ziel} {Typ|Typen} {einbezogen|ausgeschlossen}: \"{0}\"."
|
||||
ROLLBACK_IN_PROGRESS: "Ein Rollback/Restore ist bereits im Gange."
|
||||
ROLLBACK_LENGTH: "Zeit beansprucht: {0} {Sekunde|Sekunden}."
|
||||
ROLLBACK_MODIFIED: "{Modifiziert|Modifiziert} {0}."
|
||||
@@ -173,11 +178,12 @@ ROLLBACK_SELECTION: "Radius eingestellt auf \"{0}\"."
|
||||
ROLLBACK_STARTED: "{Rollback|Restore|Vorschau} gestartet für \"{0}\"."
|
||||
ROLLBACK_TIME: "Zeitspanne: {0}."
|
||||
ROLLBACK_WORLD_ACTION: "Beschränkt auf {Welt|Aktion} \"{0}\"."
|
||||
SIGN_HEADER: "Nachrichten signieren"
|
||||
SIGN_HEADER: "Schildnachrichten"
|
||||
STATUS_CONSUMER: "Warteschleife: {0} {Datensatz|Datensätze}"
|
||||
STATUS_DATABASE: "Datenbank: {0}."
|
||||
STATUS_INTEGRATION: "{0}: Integration {aktiviert|deaktiviert}."
|
||||
STATUS_LICENSE: "Lizenz: {0}"
|
||||
STATUS_SYSTEM: "System: {0}"
|
||||
STATUS_VERSION: "Version: {0}"
|
||||
TELEPORTED: "Teleportiert nach {0}."
|
||||
TELEPORTED_SAFETY: "Hab dich in Sicherheit teleportiert."
|
||||
@@ -186,16 +192,17 @@ TIME_DAYS: "{0} {Tag|Tage}"
|
||||
TIME_HOURS: "{0} {Stunde|Stunden}"
|
||||
TIME_MINUTES: "{0} {Minute|Minuten}"
|
||||
TIME_SECONDS: "{0} {Sekunde|Sekunden}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {Woche|Wochen}"
|
||||
UPDATE_ERROR: "Beim Suchen nach Updates ist ein Fehler aufgetreten."
|
||||
UPDATE_HEADER: "{0} Aktualisieren"
|
||||
UPDATE_NOTICE: "Beachten: {0} ist nun verfügbar."
|
||||
UPDATE_NOTICE: "Hinweis: {0} ist nun verfügbar."
|
||||
UPGRADE_IN_PROGRESS: "Upgrade läuft. Bitte versuchen Sie es später erneut."
|
||||
USER_NOT_FOUND: "Benutzer \"{0}\" nicht gefunden."
|
||||
USER_OFFLINE: "Der Benutzer \"{0}\" ist nicht online."
|
||||
USING_MYSQL: "Verwenden von MySQL zur Datenspeicherung."
|
||||
USING_SQLITE: "Verwenden von SQLite zur Datenspeicherung."
|
||||
VALID_DONATION_KEY: "Gültiger Spendenschlüssel."
|
||||
VERSION_NOTICE: "Ausführung {0} ist nun verfügbar."
|
||||
VERSION_NOTICE: "Version {0} ist nun verfügbar."
|
||||
VERSION_REQUIRED: "{0} {1} oder höher erforderlich."
|
||||
WORLD_NOT_FOUND: "Welt \"{0}\" nicht gefunden."
|
||||
@@ -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}."
|
||||
@@ -194,6 +202,7 @@ TIME_HOURS: "{0} {hour|hours}"
|
||||
TIME_MINUTES: "{0} {minute|minutes}"
|
||||
TIME_MONTHS: "{0} {month|months}"
|
||||
TIME_SECONDS: "{0} {second|seconds}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {week|weeks}"
|
||||
TIME_YEARS: "{0} {year|years}"
|
||||
UPDATE_ERROR: "An error occurred while checking for updates."
|
||||
|
||||
@@ -192,6 +192,7 @@ TIME_DAYS: "{0} {día|días}"
|
||||
TIME_HOURS: "{0} {hora|horas}"
|
||||
TIME_MINUTES: "{0} {minuto|minutos}"
|
||||
TIME_SECONDS: "{0} {segundo|segundos}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {semana|semanas}"
|
||||
UPDATE_ERROR: "Un error ocurrió mientras se revisaban las actualizaciones."
|
||||
UPDATE_HEADER: "Actualización {0}"
|
||||
|
||||
@@ -186,6 +186,7 @@ TIME_DAYS: "{0} {jour|jours}"
|
||||
TIME_HOURS: "{0} {heure|heures}"
|
||||
TIME_MINUTES: "{0} {minute|minutes}"
|
||||
TIME_SECONDS: "{0} {seconde|secondes}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {semaine|semaines}"
|
||||
UPDATE_ERROR: "Une erreur s'est produite lors de la recherche de mises à jour."
|
||||
UPDATE_HEADER: "{0} Mettre à jour"
|
||||
|
||||
+193
-182
@@ -1,201 +1,212 @@
|
||||
# CoreProtect Language File (ja)
|
||||
|
||||
ACTION_NOT_SUPPORTED: "そのアクションはサポートされていません。"
|
||||
AMOUNT_BLOCK: "{0} {ブロック|ブロック}"
|
||||
AMOUNT_CHUNK: "{0} {チャンク|チャンク}"
|
||||
AMOUNT_ENTITY: "{0} {エンティティ|エンティティ}"
|
||||
AMOUNT_ITEM: "{0} {item|items}"
|
||||
API_TEST: "APIテストが成功しました。"
|
||||
CACHE_ERROR: "警告:検証中にエラーが発生しました {0}"
|
||||
CACHE_RELOAD: "{マッピング|世界} のリロードを強制する(データベースからのキャッシュ)"
|
||||
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: "コンテナトランザクション"
|
||||
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: "初期DB:{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]"
|
||||
COMMAND_CONSOLE: "コンソールからコマンドを実行してください"
|
||||
COMMAND_NOT_FOUND: "{0} は不明なコマンドです"
|
||||
COMMAND_THROTTLED: "しばらく待ってから、もう一度お試しください"
|
||||
CONSUMER_ERROR: "コンシューマーキューの処理は既に{一時停止|再開}されています"
|
||||
CONSUMER_TOGGLED: "コンシューマーキューの処理が{一時停止|再開}されました"
|
||||
CONTAINER_HEADER: "コンテナのトランザクション"
|
||||
CPU_CORES: "CPUコア"
|
||||
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} を無効化しました"
|
||||
DONATION_KEY_REQUIRED: "このコマンドには有効な寄付キーが必要です。"
|
||||
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}\" は、1か月より古いすべてのデータを削除し、過去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} バージョンが見つかりました。"
|
||||
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}\" は、1か月より古い全てのデータを削除し、過去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: "有効なワールドを指定してください。"
|
||||
INVALID_ACTION: "それは有効なアクションではありません"
|
||||
INVALID_BRANCH_1: "プラグインのバージョンが無効です(ブランチが設定されていません)"
|
||||
INVALID_BRANCH_2: "続行するには、プロジェクトブランチを \"development\" に設定してください"
|
||||
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} ログに記録されます {in|out}。"
|
||||
LOOKUP_PAGE: "ページ {0}"
|
||||
LOOKUP_PROJECTILE: "{0} {投げた|ショット} {1} {2}。"
|
||||
LOOKUP_ROWS_FOUND: "{0} {行|行} 見つかりました。"
|
||||
LOOKUP_SEARCHING: "ルックアップ検索。お待ちください..."
|
||||
LOOKUP_STORAGE: "{0} {預け入れ|撤回} {1} {2}。"
|
||||
LOOKUP_TIME: "{0} 前に"
|
||||
LOOKUP_USERNAME: "{1}が{0}としてログイン"
|
||||
MAXIMUM_RADIUS: "最大 {ルックアップ|ロールバック|復元} 半径は {0}。"
|
||||
MISSING_ACTION_USER: "そのアクションを使用するには、ユーザーを指定してください。"
|
||||
MISSING_LOOKUP_TIME: "時間を指定してください({ルックアップ|ロールバック|復元})"
|
||||
MISSING_LOOKUP_USER: "ユーザーを指定するか、 {ブロック|半径}を指定してください。"
|
||||
MISSING_PARAMETERS: "\"{0}\"のパラメーターは存在していません。"
|
||||
MISSING_ROLLBACK_RADIUS: "指定しませんでした {ロールバック|復元} 半径。"
|
||||
MISSING_ROLLBACK_USER: "指定しませんでした {ロールバック|復元} ユーザー。"
|
||||
MYSQL_UNAVAILABLE: "接続できません MySQL サーバ。"
|
||||
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: "プレビューがキャンセルされました。"
|
||||
LOGGING_ITEMS: "ログに記録すべきアイテムが{0}個残っています。しばらくお待ちください..."
|
||||
LOGGING_TIME_LIMIT: "記録制限時間に達しました。データを破棄してシャットダウンします"
|
||||
LOOKUP_BLOCK: "{0}が{1}を{設置した|破壊した}"
|
||||
LOOKUP_CONTAINER: "{0}が{2}個の{1}を{追加した|取り出した}"
|
||||
LOOKUP_HEADER: "{0} の検索結果"
|
||||
LOOKUP_INTERACTION: "{0}が{1}を{クリックした|殺害した}"
|
||||
LOOKUP_ITEM: "{0}が{2}個の{1}を{拾った|落とした}"
|
||||
LOOKUP_LOGIN: "{0}の{ログイン|ログアウト}がログに記録されます"
|
||||
LOOKUP_PAGE: "{0} ページ目"
|
||||
LOOKUP_PROJECTILE: "{0}が{2}個の{1}を{投げた|撃った}"
|
||||
LOOKUP_ROWS_FOUND: "{0}行見つかりました"
|
||||
LOOKUP_SEARCHING: "検索中。しばらくお待ちください..."
|
||||
LOOKUP_STORAGE: "{0}が{2}個の{1}を{預け入れた|引き出した}"
|
||||
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: "プレビューできません {コンテナ|在庫} トランザクション。"
|
||||
PURGE_ABORTED: "パージに失敗しました。データベースが破損している可能性があります。"
|
||||
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_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: "データの分離に成功しました。"
|
||||
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} {item|items} 順番待ち。"
|
||||
STATUS_DATABASE: "データベース: 使用する {0}"
|
||||
PURGE_ROWS: "{0}行のデータが削除されました"
|
||||
PURGE_STARTED: "データの削除は\"{0}\"で開始されました"
|
||||
PURGE_SUCCESS: "データのパージに成功しました"
|
||||
RAM_STATS: "{0}GB / {1}GB RAM"
|
||||
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: "更新の確認中にエラーが発生しました。"
|
||||
TELEPORTED: "{0} にテレポートしました"
|
||||
TELEPORTED_SAFETY: "あなたを安全な場所にテレポートさせました"
|
||||
TELEPORT_PLAYERS: "テレポートコマンドはプレイヤーのみが使用できます"
|
||||
TIME_DAYS: "{0}{日|日間}"
|
||||
TIME_HOURS: "{0}{時|時間}"
|
||||
TIME_MINUTES: "{0}{分|分間}"
|
||||
TIME_MONTHS: "{0}{ヶ月|ヶ月間}"
|
||||
TIME_SECONDS: "{0}{秒|秒間}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0}{週|週間}"
|
||||
TIME_YEARS: "{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}\" は見つかりませんでした。"
|
||||
UPDATE_NOTICE: "お知らせ: {0} が利用可能です"
|
||||
UPGRADE_IN_PROGRESS: "アップグレードが進行中です。しばらくしてからもう一度やり直してください"
|
||||
USER_NOT_FOUND: "ユーザー \"{0}\" が見つかりません"
|
||||
USER_OFFLINE: "ユーザー \"{0}\" はオンラインではありません"
|
||||
USING_MYSQL: "MySQL データストレージを使用します"
|
||||
USING_SQLITE: "SQLite データストレージを使用します"
|
||||
VALID_DONATION_KEY: "有効な寄付キーです"
|
||||
VERSION_INCOMPATIBLE: "{0} {1} はサポートされていません"
|
||||
VERSION_NOTICE: "バージョン {0} が利用可能です"
|
||||
VERSION_REQUIRED: "{0} {1} 以上が必要です"
|
||||
WORLD_NOT_FOUND: "ワールド \"{0}\" は見つかりませんでした"
|
||||
+77
-71
@@ -1,35 +1,37 @@
|
||||
# CoreProtect Language File (ko)
|
||||
|
||||
ACTION_NOT_SUPPORTED: "해당 명령어는 해당 작업을 지원하지 않습니다."
|
||||
AMOUNT_BLOCK: "{0} {블록|블록}"
|
||||
AMOUNT_CHUNK: "{0} {청크|청크}"
|
||||
AMOUNT_ENTITY: "{0} {엔티티|엔티티}"
|
||||
AMOUNT_ITEM: "{0} {항목|항목}"
|
||||
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: "콘솔에서 명령어를 실행하세요."
|
||||
CHECK_CONFIG: "config.yml을 확인해주세요"
|
||||
COMMAND_CONSOLE: "이 명령어는 콘솔에서만 실행할 수 있습니다."
|
||||
COMMAND_NOT_FOUND: "\"{0}\" 명령어를 찾을 수 없습니다."
|
||||
COMMAND_THROTTLED: "잠시 기다렸다가 다시 시도하십시오."
|
||||
CONSUMER_ERROR: "소비자 대기열 처리가 이미 {일시 중지|재개}되있습니다!"
|
||||
CONSUMER_TOGGLED: "소비자 대기열 처리가 {일시 중지|재개}되었습니다."
|
||||
COMMAND_THROTTLED: "잠시 기다렸다가 다시 시도하세요."
|
||||
CONSUMER_ERROR: "데이터베이스 처리가 이미 {일시정지|재개}되어 있습니다!"
|
||||
CONSUMER_TOGGLED: "데이터베이스 처리가 {일시정지|재개}되었습니다."
|
||||
CONTAINER_HEADER: "컨테이너 기록"
|
||||
DATABASE_BUSY: "데이터베이스가 사용 중입니다. 나중에 다시 시도하십시오."
|
||||
CPU_CORES: "CPU 코어"
|
||||
DATABASE_BUSY: "데이터베이스가 사용 중입니다. 나중에 다시 시도하세요."
|
||||
DATABASE_INDEX_ERROR: "데이터베이스 인덱스의 유효성을 검사할 수 없습니다."
|
||||
DATABASE_LOCKED_1: "데이터베이스가 잠겼습니다. 최대 15초 대기 중..."
|
||||
DATABASE_LOCKED_2: "데이터베이스가 이미 사용 중입니다. 다시 시도하십시오."
|
||||
DATABASE_LOCKED_3: "데이터베이스 잠금을 비활성화하려면 \"database-lock: false\"로 설정하세요."
|
||||
DATABASE_LOCKED_4: "데이터베이스 잠금을 비활성화하면 데이터가 손상될 수 있습니다."
|
||||
DATABASE_LOCKED_2: "데이터베이스가 이미 사용 중입니다. 다시 시도하세요."
|
||||
DATABASE_LOCKED_3: "데이터베이스 잠금을 해제하려면 \"database-lock: false\"로 설정하세요."
|
||||
DATABASE_LOCKED_4: "데이터베이스 잠금을 비활성화하면 데이터가 손상될 수도 있습니다."
|
||||
DATABASE_UNREACHABLE: "데이터베이스에 연결할 수 없습니다. 데이터를 삭제하고 종료합니다."
|
||||
DEVELOPMENT_BRANCH: "개발 브랜치가 감지되어 패치 스크립트를 건너뜁니다."
|
||||
DIRT_BLOCK: "당신 아래에 흙 블록을 설치했습니다."
|
||||
DIRT_BLOCK: "당신 아래에 임시 안전 블록을 설치했습니다."
|
||||
DISABLE_SUCCESS: "성공! {0} 비활성화됨"
|
||||
DONATION_KEY_REQUIRED: "해당 명령어를 사용하려면 유효한 후원 키가 필요합니다."
|
||||
ENABLE_FAILED: "{0}을(를) 시작할 수 없습니다."
|
||||
ENABLE_SUCCESS: "{0}이(가) 성공적으로 활성화되었습니다!"
|
||||
ENJOY_COREPROTECT: "{0}을(를) 사용중이신가요? Discord 서버에 참여해보세요!"
|
||||
ENJOY_COREPROTECT: "{0}을(를) 잘 사용하고 계신가요? 그렇다면 저희의 Discord 서버에 참여하세요!"
|
||||
FINISHING_CONVERSION: "데이터 변환을 완료하는 중입니다. 잠시 기다려 주세요..."
|
||||
FINISHING_LOGGING: "데이터 로깅을 완료하는 중입니다. 잠시 기다려 주십시오..."
|
||||
FINISHING_LOGGING: "데이터 로깅을 완료하는 중입니다. 잠시 기다려 주세요..."
|
||||
FIRST_VERSION: "초기 DB: {0}"
|
||||
GLOBAL_LOOKUP: "전체 조회를 수행하려면 반경을 지정하지 마세요."
|
||||
GLOBAL_ROLLBACK: "전역 {롤백|복원}을 수행하려면 \"{0}\"을(를) 사용하세요."
|
||||
@@ -42,43 +44,43 @@ 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_2: "블록을 마우스 왼쪽 버튼으로 클릭하면 누가 그 블록을 설치했는지 확인할 수 있습니다."
|
||||
HELP_INSPECT_3: "블록을 마우스 오른쪽 버튼으로 클릭하면 인접한 블록이 부서졌는지 확인할 수 있습니다."
|
||||
HELP_INSPECT_4: "블록을 배치하여 해당 위치에서 어떤 블록이 부서졌는지 확인할 수 있습니다."
|
||||
HELP_INSPECT_5: "누가 설치했는지 확인하려면 액체(등)에 블록을 배치하세요."
|
||||
HELP_INSPECT_6: "문, 상자 등을 마우스 오른쪽 버튼으로 클릭하면 누가 마지막으로 사용했는지 확인할 수 있습니다."
|
||||
HELP_INSPECT_7: "팁: 더 빠른 액세스를 위해 \"/co i\"명령어를 사용할 수 있습니다."
|
||||
HELP_INSPECT_7: "팁: 더 빠른 사용을 위해 \"/co i\"명령어를 사용할 수 있습니다."
|
||||
HELP_INSPECT_COMMAND: "블록 로그 조사를 켜거나 끕니다."
|
||||
HELP_LIST: "모든 명령어 목록을 표시합니다."
|
||||
HELP_LOOKUP_1: "명령어 단축키."
|
||||
HELP_LOOKUP_1: "단축 명령어."
|
||||
HELP_LOOKUP_2: "로그를 보려면 블록을 검사한 후 사용하세요."
|
||||
HELP_LOOKUP_COMMAND: "고급 블록 데이터 조회."
|
||||
HELP_NO_INFO: "\"{0}\" 명령어에 대한 정보를 찾을 수 없습니다."
|
||||
HELP_NO_INFO: "\"{0}\" 명령어에 대한 정보가 없습니다."
|
||||
HELP_PARAMETER: "자세한 매개변수 정보는 \"{0}\"을 참조하세요."
|
||||
HELP_PARAMS_1: "{조회|롤백|복원}을(를) 수행하세요."
|
||||
HELP_PARAMS_2: "{조회|롤백|복원}할 사용자를 지정하세요."
|
||||
HELP_PARAMS_3: "{조회|롤백|복원}에 걸리는 시간을 지정하세요."
|
||||
HELP_PARAMS_4: "{조회|롤백|복원}을(를) 제한할 반경 영역을 지정하세요."
|
||||
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_RADIUS_1: "반경을 지정합니다."
|
||||
HELP_RADIUS_2: "예: [r:10] (10블록 이내에서만 변경합니다.)"
|
||||
HELP_RELOAD_COMMAND: "구성 파일을 다시 로드합니다."
|
||||
HELP_RESTORE_COMMAND: "블록 데이터를 복원합니다."
|
||||
HELP_ROLLBACK_COMMAND: "블록 데이터를 롤백합니다."
|
||||
HELP_STATUS: "플러그인 상태 및 버전 정보를 확인하세요."
|
||||
HELP_STATUS: "플러그인 상태 및 버전 정보를 확인합니다."
|
||||
HELP_STATUS_COMMAND: "플러그인 상태를 표시합니다."
|
||||
HELP_TELEPORT: "특정 위치로 순간이동합니다."
|
||||
HELP_TIME_1: "조회 시간을 지정하세요."
|
||||
HELP_TIME_1: "조회 시간을 지정합니다."
|
||||
HELP_TIME_2: "예: [t:2w,5d,7h,2m,10s], [t:5d2h], [t:2.50h]"
|
||||
HELP_USER_1: "조회할 사용자를 지정하세요."
|
||||
HELP_USER_1: "조회할 사용자를 지정합니다."
|
||||
HELP_USER_2: "예: [u:notch], [u:notch,#enderman]"
|
||||
INCOMPATIBLE_ACTION: "\"{0}\"은(는) 해당 작업과 함께 사용할 수 없습니다."
|
||||
INSPECTOR_ERROR: "로그 조사가 이미 {활성화|비활성화}되있습니다!"
|
||||
INSPECTOR_ERROR: "로그 조사가 이미 {활성화|비활성화}되어 있습니다!"
|
||||
INSPECTOR_TOGGLED: "로그 조사가 {활성화|비활성화}되었습니다."
|
||||
INTEGRATION_ERROR: "{0} 로깅을 {초기화|비활성화}할 수 없습니다."
|
||||
INTEGRATION_SUCCESS: "{0} 로깅이 성공적으로 {초기화|비활성화}되었습니다."
|
||||
@@ -87,13 +89,13 @@ INTERACTIONS_HEADER: "플레이어 상호작용"
|
||||
INVALID_ACTION: "유효하지 않은 작업입니다."
|
||||
INVALID_BRANCH_1: "잘못된 플러그인 버전(브랜치가 설정되지 않음)."
|
||||
INVALID_BRANCH_2: "계속하려면 프로젝트 브랜치를 \"development\"로 설정하세요."
|
||||
INVALID_BRANCH_3: "개발 코드를 실행하면 데이터 손상이 발생할 수 있습니다."
|
||||
INVALID_BRANCH_3: "개발중인 코드를 실행하면 데이터 손상이 발생할 수도 있습니다."
|
||||
INVALID_CONTAINER: "먼저 유효한 컨테이너를 검사하세요."
|
||||
INVALID_DONATION_KEY: "잘못된 후원 키입니다."
|
||||
INVALID_INCLUDE: "\"{0}\"은(는) 잘못된 블록/엔티티 이름입니다."
|
||||
INVALID_INCLUDE_COMBO: "잘못된 블록/엔티티 조합입니다."
|
||||
INVALID_RADIUS: "유효한 반경을 입력하세요."
|
||||
INVALID_SELECTION: "{0} 선택을 찾을 수 없습니다."
|
||||
INVALID_SELECTION: "{0} 선택된 항목을 찾을 수 없습니다."
|
||||
INVALID_USERNAME: "\"{0}\"은(는) 잘못된 사용자 이름입니다."
|
||||
INVALID_WORLD: "유효한 월드를 지정하세요."
|
||||
LATEST_VERSION: "최신 버전: {0}"
|
||||
@@ -103,29 +105,29 @@ 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}이(가) {2}에서 {1}을(를) {추가|제거}했습니다."
|
||||
LOGGING_TIME_LIMIT: "로깅 시간 제한에 도달했습니다. 데이터를 삭제하고 종료합니다."
|
||||
LOOKUP_BLOCK: "{0}이(가) {1}을(를) {설치|파괴}함"
|
||||
LOOKUP_CONTAINER: "{0}이(가) {2}에서 {1}을(를) {추가|제거}함"
|
||||
LOOKUP_HEADER: "{0} 조회 결과"
|
||||
LOOKUP_INTERACTION: "{0}이(가) {1}을(를) {클릭|처치}했습니다."
|
||||
LOOKUP_ITEM: "{0}이(가) {2}에서 {1}을(를) {획득|드롭}했습니다."
|
||||
LOOKUP_LOGIN: "{0}이(가) {로그인|로그아웃}했습니다."
|
||||
LOOKUP_INTERACTION: "{0}이(가) {1}을(를) {클릭함|죽임}
|
||||
LOOKUP_ITEM: "{0}이(가) {2}에서 {1}을(를) {획득|드롭}함"
|
||||
LOOKUP_LOGIN: "{0}이(가) {로그인|로그아웃}함"
|
||||
LOOKUP_PAGE: "페이지 {0}"
|
||||
LOOKUP_PROJECTILE: "{0}이(가) {2}에서 {1}을(를) {던졌|발사했}습니다.."
|
||||
LOOKUP_PROJECTILE: "{0}이(가) {2}에서 {1}을(를) {던짐|발사함}"
|
||||
LOOKUP_ROWS_FOUND: "{0} {열|열}이 발견되었습니다."
|
||||
LOOKUP_SEARCHING: "조회 중입니다. 잠시만 기다려 주세요..."
|
||||
LOOKUP_STORAGE: "{0}이(가) {2}에서 {1}을(를) {추가|제거}했습니다."
|
||||
LOOKUP_STORAGE: "{0}이(가) {2}에서 {1}을(를) {추가|제거}함"
|
||||
LOOKUP_TIME: "{0} 전"
|
||||
LOOKUP_USERNAME: "{0}이(가) {1}으로 로그인했습니다."
|
||||
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: "{롤백|복원} 사용자를 지정하지 않았습니다."
|
||||
MISSING_ROLLBACK_RADIUS: "{롤백|복원}할 반경을 지정하지 않았습니다."
|
||||
MISSING_ROLLBACK_USER: "{롤백|복원}할 사용자를 지정하지 않았습니다."
|
||||
MYSQL_UNAVAILABLE: "MySQL 서버에 연결할 수 없습니다."
|
||||
NETWORK_CONNECTION: "{0} 연결 {성공|실패}. {1} {2} 사용 중."
|
||||
NETWORK_CONNECTION: "{0} 연결 {성공|실패}. {1} {2} 사용 중"
|
||||
NETWORK_TEST: "네트워크 테스트 데이터가 성공적으로 전송되었습니다."
|
||||
NO_DATA: "{0}에서 데이터를 찾을 수 없습니다."
|
||||
NO_DATA_LOCATION: "해당 위치에서 {데이터|거래|상호작용|메시지}(을)를 찾을 수 없습니다."
|
||||
@@ -133,7 +135,7 @@ NO_PERMISSION: "해당 작업을 수행할 권한이 없습니다."
|
||||
NO_RESULTS: "결과를 찾을 수 없습니다."
|
||||
NO_RESULTS_PAGE: "해당 페이지에 대한 {결과|데이터}를 찾을 수 없습니다."
|
||||
NO_ROLLBACK: "{보류 중인|이전} 롤백/복원을 찾을 수 없습니다."
|
||||
PATCH_INTERRUPTED: "업그레이드가 중단되었습니다. 다시 시작할 때 재시도합니다."
|
||||
PATCH_INTERRUPTED: "업그레이드가 중단되었습니다. 서버를 재시작하면 재시도합니다."
|
||||
PATCH_OUTDATED_1: "{0}보다 오래된 데이터베이스를 업그레이드할 수 없습니다."
|
||||
PATCH_OUTDATED_2: "지원되는 CoreProtect 버전으로 업그레이드하세요."
|
||||
PATCH_PROCESSING: "새 데이터를 처리 중입니다. 잠시 기다려 주세요..."
|
||||
@@ -141,45 +143,48 @@ PATCH_SKIP_UPDATE: "{0}에서 {테이블|인덱스} {업데이트|생성|제거}
|
||||
PATCH_STARTED: "{0} 업그레이드를 수행 중입니다. 잠시 기다려 주세요..."
|
||||
PATCH_SUCCESS: "{0}으로 성공적으로 업그레이드되었습니다."
|
||||
PATCH_UPGRADING: "데이터베이스 업그레이드가 진행 중입니다. 잠시 기다려 주세요..."
|
||||
PLEASE_SELECT: "다음을 선택하세요: \"{0}\" 또는 \"{1}\"."
|
||||
PLEASE_SELECT: "\"{0}\" 또는 \"{1}\" 중 하나를 선택하세요."
|
||||
PREVIEW_CANCELLED: "미리보기가 취소되었습니다."
|
||||
PREVIEW_CANCELLING: "미리보기 취소 중..."
|
||||
PREVIEW_IN_GAME: "롤백을 미리보려면 게임 내에서만 가능합니다."
|
||||
PREVIEW_TRANSACTION: "{컨테이너|인벤토리} 기록을 미리볼 수 없습니다."
|
||||
PURGE_ABORTED: "삭제 실패. 데이터베이스가 손상되었을 수 있습니다."
|
||||
PREVIEW_IN_GAME: "게임 내에서만 롤백 미리보기가 가능합니다."
|
||||
PREVIEW_TRANSACTION: "{컨테이너|인벤토리} 기록은 미리보기할 수 없습니다."
|
||||
PRIMARY_THREAD_ERROR: "기본 스레드에서는 API 메소드를 사용할 수 없습니다."
|
||||
PURGE_ABORTED: "삭제에 실패하였습니다. 데이터베이스가 손상되었을 수도 있습니다."
|
||||
PURGE_ERROR: "{0} 데이터를 처리할 수 없습니다!"
|
||||
PURGE_FAILED: "삭제 실패. 나중에 다시 시도하세요."
|
||||
PURGE_FAILED: "삭제에 실패하였습니다. 나중에 다시 시도하세요."
|
||||
PURGE_IN_PROGRESS: "삭제가 진행 중입니다. 나중에 다시 시도하세요."
|
||||
PURGE_MINIMUM_TIME: "{0} {일|시간}보다 오래된 데이터만 삭제할 수 있습니다."
|
||||
PURGE_NOTICE_1: "이 작업은 시간이 걸릴 수 있습니다."
|
||||
PURGE_NOTICE_2: "완료될 때까지 서버를 재시작하지 마세요."
|
||||
PURGE_OPTIMIZING: "데이터베이스 최적화 중입니다. 잠시 기다려 주세요..."
|
||||
PURGE_OPTIMIZING: "데이터베이스를 최적화 중입니다. 잠시 기다려 주세요..."
|
||||
PURGE_PROCESSING: "{0} 데이터를 처리 중입니다..."
|
||||
PURGE_REPAIRING: "복구 시도 중입니다. 시간이 걸릴 수 있습니다..."
|
||||
PURGE_ROWS: "{0} {열|열}의 데이터가 삭제되었습니다."
|
||||
PURGE_STARTED: "\"{0}\"에서 데이터 삭제가 시작되었습니다."
|
||||
PURGE_STARTED: "\"{0}\"에서 데이터 삭제 시작됨"
|
||||
PURGE_SUCCESS: "데이터 삭제가 성공적으로 완료되었습니다."
|
||||
RAM_STATS: "램: {0}GB / {1}GB"
|
||||
RELOAD_STARTED: "구성 리로드 중 - 잠시 기다려 주세요."
|
||||
RELOAD_SUCCESS: "구성이 성공적으로 리로드되었습니다."
|
||||
ROLLBACK_ABORTED: "롤백 또는 복원이 중단되었습니다."
|
||||
ROLLBACK_CHUNKS_FOUND: "{0} {청크|청크}를 수정할 준비가 되었습니다."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "{1} 중 {0} {청크|청크}를 수정했습니다."
|
||||
ROLLBACK_CHUNKS_FOUND: "수정할 {청크|청크} {0}개를 찾았습니다."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "{1}개 중 {0}개의 {청크|청크} 수정됨"
|
||||
ROLLBACK_COMPLETED: "\"{0}\"에 대한 {롤백이|복원이|미리보기가} 완료되었습니다."
|
||||
ROLLBACK_EXCLUDED_USERS: "제외된 {사용자|사용자}: \"{0}\"."
|
||||
ROLLBACK_INCLUDE: "{포함된|제외된} {블록|엔티티|대상} {타입|타입}: \"{0}\"."
|
||||
ROLLBACK_EXCLUDED_USERS: "제외된 {사용자|사용자}: \"{0}\""
|
||||
ROLLBACK_INCLUDE: "{포함된|제외된} {블록|엔티티|대상} {타입|타입}: \"{0}\""
|
||||
ROLLBACK_IN_PROGRESS: "롤백/복원이 이미 진행 중입니다."
|
||||
ROLLBACK_LENGTH: "소요 시간: {0} {초|초}."
|
||||
ROLLBACK_MODIFIED: "{0}이(가) {수정됨|수정 중}."
|
||||
ROLLBACK_RADIUS: "반경: {0} {블록|블록}."
|
||||
ROLLBACK_LENGTH: "소요 시간: {0} {초|초}"
|
||||
ROLLBACK_MODIFIED: "{0}이(가) {수정됨|수정 중}"
|
||||
ROLLBACK_RADIUS: "반경: {0} {블록|블록}"
|
||||
ROLLBACK_SELECTION: "반경이 \"{0}\"로 설정되었습니다."
|
||||
ROLLBACK_STARTED: "\"{0}\"에서 {롤백이|복원이|미리보기가} 시작되었습니다."
|
||||
ROLLBACK_TIME: "시간 범위: {0}."
|
||||
ROLLBACK_WORLD_ACTION: "{월드|작업} \"{0}\"으로 제한됨."
|
||||
ROLLBACK_TIME: "시간 범위: {0}"
|
||||
ROLLBACK_WORLD_ACTION: "{월드|작업} \"{0}\"으로 제한됨"
|
||||
SIGN_HEADER: "표지판 메시지"
|
||||
STATUS_CONSUMER: "소비자: 대기 중인 {0} {항목|항목들}."
|
||||
STATUS_DATABASE: "데이터베이스: {0} 사용 중."
|
||||
STATUS_INTEGRATION: "{0}: 통합 {활성화됨|비활성화됨}."
|
||||
STATUS_CONSUMER: "데이터베이스 처리: 대기 중인 {항목|항목} {0}개"
|
||||
STATUS_DATABASE: "데이터베이스: {0} 사용 중"
|
||||
STATUS_INTEGRATION: "{0}: 통합 {활성화됨|비활성화됨}"
|
||||
STATUS_LICENSE: "라이선스: {0}"
|
||||
STATUS_SYSTEM: "시스템: {0}"
|
||||
STATUS_VERSION: "버전: {0}"
|
||||
TELEPORTED: "{0}(으)로 텔레포트되었습니다."
|
||||
TELEPORTED_SAFETY: "안전하게 텔레포트되었습니다."
|
||||
@@ -188,16 +193,17 @@ TIME_DAYS: "{0} {일|일}"
|
||||
TIME_HOURS: "{0} {시간|시간}"
|
||||
TIME_MINUTES: "{0} {분|분}"
|
||||
TIME_SECONDS: "{0} {초|초}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {주|주}"
|
||||
UPDATE_ERROR: "업데이트 확인 중 오류가 발생했습니다."
|
||||
UPDATE_HEADER: "{0} 업데이트"
|
||||
UPDATE_NOTICE: "알림: {0}이(가) 이제 사용할 수 있습니다."
|
||||
UPDATE_NOTICE: "알림: {0}을(를) 사용할 수 있습니다."
|
||||
UPGRADE_IN_PROGRESS: "업그레이드가 진행 중입니다. 나중에 다시 시도하세요."
|
||||
USER_NOT_FOUND: "사용자 \"{0}\"을(를) 찾을 수 없습니다."
|
||||
USER_OFFLINE: "사용자 \"{0}\"이(가) 온라인 상태가 아닙니다."
|
||||
USER_OFFLINE: "사용자 \"{0}\"은(는) 온라인 상태가 아닙니다."
|
||||
USING_MYSQL: "데이터 저장에 MySQL을 사용 중입니다."
|
||||
USING_SQLITE: "데이터 저장에 SQLite를 사용 중입니다."
|
||||
VALID_DONATION_KEY: "유효한 후원 키입니다."
|
||||
VERSION_NOTICE: "버전 {0}(를) 이제 사용할 수 있습니다."
|
||||
VERSION_NOTICE: "버전 {0}(를) 사용할 수 있습니다."
|
||||
VERSION_REQUIRED: "{0} {1} 이상이 필요합니다."
|
||||
WORLD_NOT_FOUND: " \"{0}\"을(를) 찾을 수 없습니다."
|
||||
WORLD_NOT_FOUND: " \"{0}\"을(를) 찾을 수 없습니다."
|
||||
+114
-103
@@ -1,20 +1,21 @@
|
||||
# CoreProtect Language File (pl)
|
||||
|
||||
ACTION_NOT_SUPPORTED: "To działanie nie jest obsługiwane."
|
||||
ACTION_NOT_SUPPORTED: "Ta akcja nie jest obsługiwana."
|
||||
AMOUNT_BLOCK: "{0} {blok|bloki}"
|
||||
AMOUNT_CHUNK: "{0} {kawałek|kawałki}"
|
||||
AMOUNT_ENTITY: "{0} {jednostka|jednostki}"
|
||||
AMOUNT_CHUNK: "{0} {chunk|chunków}"
|
||||
AMOUNT_ENTITY: "{0} {byt|bytów}"
|
||||
AMOUNT_ITEM: "{0} {przedmiot|przedmioty}"
|
||||
API_TEST: "Test interfejsu API pomyślny."
|
||||
CACHE_ERROR: "OSTRZEŻENIE: Błąd podczas walidacji {0} Pamięć podręczna."
|
||||
CACHE_RELOAD: "Wymuszanie przeładowania {mapowanie|świat} pamięci podręczne z bazy danych."
|
||||
CHECK_CONFIG: "Sprawdź plik config.yml"
|
||||
COMMAND_CONSOLE: "Uruchom polecenie z konsoli."
|
||||
COMMAND_NOT_FOUND: "Komenda \"{0}\" nie znaleziono."
|
||||
COMMAND_NOT_FOUND: "Nie znaleziono komendy \"{0}\"."
|
||||
COMMAND_THROTTLED: "Poczekaj chwilę i spróbuj ponownie."
|
||||
CONSUMER_ERROR: "Przetwarzanie kolejki klientów już {wstrzymane|wznowione}."
|
||||
CONSUMER_ERROR: "Przetwarzanie kolejki klientów jest już {wstrzymane|wznowione}."
|
||||
CONSUMER_TOGGLED: "Przetwarzanie kolejki klientów zostało {wstrzymane|wznowione}."
|
||||
CONTAINER_HEADER: "Transakcje kontenerowe"
|
||||
CPU_CORES: "Rdzenie CPU."
|
||||
DATABASE_BUSY: "Baza danych zajęta. Spróbuj ponownie później."
|
||||
DATABASE_INDEX_ERROR: "Nie można zweryfikować indeksów bazy danych."
|
||||
DATABASE_LOCKED_1: "Baza danych zablokowana. Czekam do 15 sekund..."
|
||||
@@ -23,179 +24,189 @@ DATABASE_LOCKED_3: "Aby wyłączyć blokowanie bazy danych, ustaw \"database-loc
|
||||
DATABASE_LOCKED_4: "Wyłączenie blokowania bazy danych może spowodować uszkodzenie danych."
|
||||
DATABASE_UNREACHABLE: "Baza danych jest niedostępna. Odrzucanie danych i zamykanie."
|
||||
DEVELOPMENT_BRANCH: "Wykryto gałąź deweloperską, pomijam skrypty poprawek."
|
||||
DIRT_BLOCK: "Umieściłem pod tobą blok brudu."
|
||||
DISABLE_SUCCESS: "Sukces! Niepełnosprawny {0}"
|
||||
ENABLE_FAILED: "{0} nie mógł rozpocząć."
|
||||
DIRT_BLOCK: "Umieściłem pod Tobą tymczasowy blok bezpieczeństwa."
|
||||
DONATION_KEY_REQUIRED: "Dla tej komendy wymagany jest prawidłowy klucz darowizny."
|
||||
DISABLE_SUCCESS: "Sukces! Wyłączono {0}"
|
||||
ENABLE_FAILED: "{0} nie mógł wystartować."
|
||||
ENABLE_SUCCESS: "{0} jest teraz włączony!"
|
||||
ENJOY_COREPROTECT: "Cieszyć się {0}? Dołączć do naszego Discord!"
|
||||
FINISHING_CONVERSION: "Zakończenie konwersji danych. Proszę czekać..."
|
||||
FINISHING_LOGGING: "Zakończenie rejestracji danych. Proszę czekać..."
|
||||
ENJOY_COREPROTECT: "Podoba Ci się {0}? Dołącz do naszego Discorda!"
|
||||
FINISHING_CONVERSION: "Kończenie konwersji danych. Proszę czekać..."
|
||||
FINISHING_LOGGING: "Kończenie rejestracji danych. Proszę czekać..."
|
||||
FIRST_VERSION: "Początkowa baza danych: {0}"
|
||||
GLOBAL_LOOKUP: "Nie określaj promienia, aby wykonać globalne wyszukiwanie."
|
||||
GLOBAL_ROLLBACK: "Posługiwać się \"{0}\" zrobić globalny {wycofywanie|przywracanie}"
|
||||
HELP_ACTION_1: "Ogranicz wyszukiwanie do akcji."
|
||||
GLOBAL_ROLLBACK: "Użyj \"{0}\", aby zrobić globalne {wycofywanie|przywracanie}"
|
||||
HELP_ACTION_1: "Ogranicz wyszukiwanie do konkretnej akcji."
|
||||
HELP_ACTION_2: "Przykłady: [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: "Wyświetl dodatkowe informacje."
|
||||
HELP_EXCLUDE_1: "Wyklucz bloki/użytkowników."
|
||||
HELP_EXCLUDE_2: "Przykłady: [e:stone], [e:Notch], [e:stone,Notch]"
|
||||
HELP_HEADER: "{0} Wsparcie"
|
||||
HELP_HEADER: "{0} Pomoc"
|
||||
HELP_INCLUDE_1: "Uwzględnij bloki/elementy."
|
||||
HELP_INCLUDE_2: "Przykłady: [i:stone], [i:zombie], [i:stone,wood,bedrock]"
|
||||
HELP_INSPECT_1: "Po włączeniu inspektora możesz:"
|
||||
HELP_INSPECT_2: "Kliknij lewym przyciskiem myszy, aby zobaczyć miejsce docelowe."
|
||||
HELP_INSPECT_3: "Kliknij prawym przyciskiem myszy, aby zobaczyć sąsiednie usunięcia."
|
||||
HELP_INSPECT_4: "Umieść blok, aby zobaczyć usunięcie."
|
||||
HELP_INSPECT_5: "Umieść blok w płynie, aby zobaczyć umieszczenie."
|
||||
HELP_INSPECT_6: "Kliknij prawym przyciskiem myszy, aby zobaczyć transakcje w skrzyniach."
|
||||
HELP_INSPECT_7: "Wskazówka: możesz użyć tylko „/co i”."
|
||||
HELP_INSPECT_2: "Kliknij lewym przyciskiem myszy, aby zobaczyć kto postawił ten blok."
|
||||
HELP_INSPECT_3: "Kliknij prawym przyciskiem myszy, aby zobaczyć jaki sąsiedni blok został usunięty."
|
||||
HELP_INSPECT_4: "Umieść blok, aby zobaczyć jaki blok został usunięty w tym miejscu."
|
||||
HELP_INSPECT_5: "Umieść blok w płynie, aby zobaczyć kto go postawił."
|
||||
HELP_INSPECT_6: "Kliknij prawym przyciskiem myszy na drzwi, skrzynię, itp., aby zobaczyć, kto ostatnio z nich korzystał."
|
||||
HELP_INSPECT_7: "Wskazówka: możesz użyć po prostu \"/co i\"."
|
||||
HELP_INSPECT_COMMAND: "Przełącza inspektora bloków."
|
||||
HELP_LIST: "Wyświetla listę wszystkich poleceń."
|
||||
HELP_LOOKUP_1: "Skrót poleceń."
|
||||
HELP_LOOKUP_2: "Zobacz dodatkowe strony."
|
||||
HELP_LOOKUP_COMMAND: "Dane bloku wyszukiwania."
|
||||
HELP_NO_INFO: "Informacje do polecenia \"{0}\" nie znaleziono."
|
||||
HELP_PARAMETER: "Proszę zobaczyć \"{0}\" , aby uzyskać szczegółowe informacje o parametrach."
|
||||
HELP_PARAMS_1: "Wykonaj {wyszukiwanie|przywracanie|przywracanie}."
|
||||
HELP_PARAMS_2: "Określ użytkowników do {wyszukiwanie|przywracanie|przywracanie}."
|
||||
HELP_PARAMS_3: "Określ czas, aby {wyszukiwanie|przywracanie|przywracanie}."
|
||||
HELP_PARAMS_4: "Ogranicz {wyszukiwanie|wycofywanie|przywracanie} do promienia."
|
||||
HELP_PARAMS_5: "Ogranicz {wyszukiwanie|wycofywanie|przywracanie} do działania."
|
||||
HELP_PARAMS_6: "Uwzględnij bloki/elementy w {wyszukiwanie|przywracanie|przywracanie}."
|
||||
HELP_PARAMS_7: "Wyklucz bloki/użytkowników z {wyszukiwanie|przywracanie|przywracanie}."
|
||||
HELP_PURGE_1: "Usuń stare dane."
|
||||
HELP_NO_INFO: "Nie znaleziono informacji dla polecenia \"{0}\"."
|
||||
HELP_PARAMETER: "Proszę zobaczyć \"{0}\", aby uzyskać szczegółowe informacje o parametrach."
|
||||
HELP_PARAMS_1: "Wykonaj {wyszukiwanie|wycofywanie|przywracanie}."
|
||||
HELP_PARAMS_2: "Określ użytkowników do {wyszukiwania|wycofywania|przywracania}."
|
||||
HELP_PARAMS_3: "Określ czas do {wyszukiwania|wycofywania|przywracania}."
|
||||
HELP_PARAMS_4: "Ogranicz promień {wyszukiwania|wycofywania|przywracania}."
|
||||
HELP_PARAMS_5: "Ogranicz akcję {wyszukiwania|wycofywania|przywracania}."
|
||||
HELP_PARAMS_6: "Uwzględnij bloki/byty w {wyszukiwaniu|wycofywaniu|przywracaniu}."
|
||||
HELP_PARAMS_7: "Wyklucz bloki/użytkowników z {wyszukiwania|wycofywania|przywracania}."
|
||||
HELP_PURGE_1: "Usuń dane starsze od określonego czasu."
|
||||
HELP_PURGE_2: "Na przykład, \"{0}” usunie wszystkie dane starsze niż jeden miesiąc i zachowa tylko dane z ostatnich 30 dni."
|
||||
HELP_PURGE_COMMAND: "Usuń stare dane bloku."
|
||||
HELP_RADIUS_1: "Określ obszar promienia."
|
||||
HELP_RADIUS_1: "Określ promień obszaru."
|
||||
HELP_RADIUS_2: "Przykłady: [r:10] (Dokonuj zmian tylko w promieniu 10 bloków od Ciebie)"
|
||||
HELP_RELOAD_COMMAND: "Ponownie ładuje plik konfiguracyjny."
|
||||
HELP_RESTORE_COMMAND: "Przywróć dane bloku."
|
||||
HELP_ROLLBACK_COMMAND: "Wycofaj dane bloku."
|
||||
HELP_STATUS: "Wyświetl stan wtyczki."
|
||||
HELP_STATUS_COMMAND: "Wyświetla stan wtyczki."
|
||||
HELP_STATUS: "Wyświetl stan i wersję pluginu."
|
||||
HELP_STATUS_COMMAND: "Wyświetla stan pluginu."
|
||||
HELP_TELEPORT: "Teleport."
|
||||
HELP_TIME_1: "Określ czas."
|
||||
HELP_TIME_2: "Przykłady: [t:2w,5d,7h,2m,10s], [t:5d2h], [t:2.50h]"
|
||||
HELP_USER_1: "Określ użytkowników."
|
||||
HELP_USER_2: "Przykłady: [u:Notch], [u:Notch,#enderman]"
|
||||
INCOMPATIBLE_ACTION: "\"{0}nie można użyć z tą akcją."
|
||||
INSPECTOR_ERROR: "Inspektor już {włączone|wyłączone}."
|
||||
INSPECTOR_TOGGLED: "Inspektor teraz {włączone|wyłączone}."
|
||||
INTEGRATION_ERROR: "Niezdolny do {inicjalizuj|wyłącz} {0} Logowanie."
|
||||
INTEGRATION_SUCCESS: "{0} logowanie pomyślnie {zainicjowane|wyłączone}."
|
||||
INTEGRATION_VERSION: "Nieważny {0} znaleziono wersję."
|
||||
INCOMPATIBLE_ACTION: "\"{0}\" nie może być użyte z tą akcją."
|
||||
INSPECTOR_ERROR: "Inspektor jest już {włączony|wyłączony}."
|
||||
INSPECTOR_TOGGLED: "{Włączono|Wyłączono} inspektor."
|
||||
INTEGRATION_ERROR: "Nie można {zainicjalizować|wyłączyć} logowania {0}."
|
||||
INTEGRATION_SUCCESS: "Logowanie {0} pomyślnie {zainicjowane|wyłączone}."
|
||||
INTEGRATION_VERSION: "Znaleziono nieprawidłową wersję {0}."
|
||||
INTERACTIONS_HEADER: "Interakcje graczy"
|
||||
INVALID_ACTION: "To nie jest prawidłowe działanie."
|
||||
INVALID_BRANCH_1: "Nieprawidłowa wersja wtyczki (nie ustawiono gałęzi)."
|
||||
INVALID_ACTION: "To nie jest prawidłowa akcja."
|
||||
INVALID_BRANCH_1: "Nieprawidłowa wersja pluginu (nie ustawiono gałęzi)."
|
||||
INVALID_BRANCH_2: "Aby kontynuować, ustaw gałąź projektu na \"development\"."
|
||||
INVALID_BRANCH_3: "Uruchomienie kodu programistycznego może spowodować uszkodzenie danych."
|
||||
INVALID_CONTAINER: "Proszę najpierw sprawdzić prawidłowy pojemnik."
|
||||
INVALID_DONATION_KEY: "Nieprawidłowy klucz darowizny."
|
||||
INVALID_INCLUDE: "\"{0}„ to nieprawidłowa wartość."
|
||||
INVALID_INCLUDE: "\"{0}\" to nieprawidłowa nazwa bloku/bytu."
|
||||
INVALID_INCLUDE_COMBO: "To jest nieprawidłowa kombinacja typów."
|
||||
INVALID_RADIUS: "Podaj poprawny promień."
|
||||
INVALID_SELECTION: "{0} nie znaleziono wyboru."
|
||||
INVALID_USERNAME: "\"{0}„ to nieprawidłowa nazwa użytkownika."
|
||||
INVALID_USERNAME: "\"{0}\" to nieprawidłowa nazwa użytkownika."
|
||||
INVALID_WORLD: "Podaj poprawny świat."
|
||||
LATEST_VERSION: "Najnowsza wersja: {0}"
|
||||
LINK_DISCORD: "Discord: {0}"
|
||||
LINK_DOWNLOAD: "Ściągnij: {0}"
|
||||
LINK_DOWNLOAD: "Pobierz: {0}"
|
||||
LINK_PATREON: "Patreon: {0}"
|
||||
LINK_WIKI_BLOCK: "Nazwy bloków: {0}"
|
||||
LINK_WIKI_ENTITY: "Nazwy podmiotów: {0}"
|
||||
LOGGING_ITEMS: "{0} elementy pozostawione do zarejestrowania. Proszę czekać..."
|
||||
LINK_WIKI_ENTITY: "Nazwy bytów: {0}"
|
||||
LOGGING_ITEMS: "Pozostało {0} elementów do logowania. Proszę czekać..."
|
||||
LOGGING_TIME_LIMIT: "Osiągnięto limit czasu logowania. Odrzucanie danych i zamykanie."
|
||||
LOOKUP_BLOCK: "{0} {umieszczony|złamany} {1}."
|
||||
LOOKUP_CONTAINER: "{0} {dodano|usunięto} {1} {2}."
|
||||
LOOKUP_HEADER: "{0} Wyniki"
|
||||
LOOKUP_INTERACTION: "{0} {kliknięty|zabity} {1}."
|
||||
LOOKUP_ITEM: "{0} {odebrany|upuszczony} {1} {2}."
|
||||
LOOKUP_LOGIN: "{0} zalogowany {w|na zewnątrz}."
|
||||
LOOKUP_BLOCK: "{0} {postawił|zniszczył} {1}."
|
||||
LOOKUP_CONTAINER: "{0} {dodał|usunął} {1} {2}."
|
||||
LOOKUP_HEADER: "{0} Wyników Wyszukiwania"
|
||||
LOOKUP_INTERACTION: "{0} {kliknął|zabił} {1}."
|
||||
LOOKUP_ITEM: "{0} {podniósł|upuścił} {1} {2}."
|
||||
LOOKUP_LOGIN: "{0} się {zalogował|wylogował}."
|
||||
LOOKUP_PAGE: "Strona {0}"
|
||||
LOOKUP_PROJECTILE: "{0} {rzucił|strzał} {1} {2}."
|
||||
LOOKUP_ROWS_FOUND: "{0} {wiersz|wiersze} znaleziony."
|
||||
LOOKUP_PROJECTILE: "{0} {rzucił|strzelił} {1} {2}."
|
||||
LOOKUP_ROWS_FOUND: "Znaleziono {0} {wiersz|wierszy}."
|
||||
LOOKUP_SEARCHING: "Wyszukiwanie wyszukiwania. Proszę czekać..."
|
||||
LOOKUP_STORAGE: "{0} {zdeponowane|wycofane} {1} {2}."
|
||||
LOOKUP_STORAGE: "{0} {zdeponował|wyciągnął} {1} {2}."
|
||||
LOOKUP_TIME: "{0} temu"
|
||||
LOOKUP_USERNAME: "{0} zalogowany jako {1}."
|
||||
MAXIMUM_RADIUS: "Maksymalny {wyszukiwanie|wycofywanie|przywracanie} promień to {0}."
|
||||
MAXIMUM_RADIUS: "Maksymalny promień {wyszukiwania|wycofywania|przywracania} to {0}."
|
||||
MISSING_ACTION_USER: "Aby skorzystać z tej akcji, określ użytkownika."
|
||||
MISSING_LOOKUP_TIME: "Proszę określić czas na {wyszukiwanie|przywracanie|przywracanie}."
|
||||
MISSING_LOOKUP_TIME: "Proszę określić czas {wyszukiwania|wycofywania|przywracania}."
|
||||
MISSING_LOOKUP_USER: "Podaj użytkownika lub {blok|promień}."
|
||||
MISSING_PARAMETERS: "Proszę użyć \"{0}”."
|
||||
MISSING_ROLLBACK_RADIUS: "Nie podałeś {wycofywanie|przywracanie} promień."
|
||||
MISSING_ROLLBACK_USER: "Nie podałeś {wycofywanie|przywracanie} użytkownik."
|
||||
MYSQL_UNAVAILABLE: "Nie można się połączyć z MySQL serwer."
|
||||
MISSING_PARAMETERS: "Proszę użyć \"{0}\"."
|
||||
MISSING_ROLLBACK_RADIUS: "Nie podałeś promienia {wycofywania|przywracania}."
|
||||
MISSING_ROLLBACK_USER: "Nie podałeś użytkownika {wycofywania|przywracania}."
|
||||
MYSQL_UNAVAILABLE: "Nie można się połączyć z serwerem MySQL."
|
||||
NETWORK_CONNECTION: "Połączenie przez {0} {pomyślne|nieudane}. Używam {1} {2}."
|
||||
NETWORK_TEST: "Pomyślnie wysłano dane testu sieci."
|
||||
NO_DATA: "Nie znaleziono danych w {0}."
|
||||
NO_DATA_LOCATION: "Nie {dane|transakcje|interakcje|wiadomości} znaleziony."
|
||||
NO_DATA_LOCATION: "Nie znaleziono {danych|transakcji|interakcji|wiadomości} w tym miejscu."
|
||||
NO_PERMISSION: "Nie masz na to pozwolenia."
|
||||
NO_RESULTS: "Nie znaleziono wyników."
|
||||
NO_RESULTS_PAGE: "Nie {wyniki|dane} znalezione dla tej strony."
|
||||
NO_ROLLBACK: "Nie {oczekujące|poprzednie} znaleziono wycofywanie/przywracanie."
|
||||
PATCH_INTERRUPTED: "Aktualizacja przerwana. Spróbuje ponownie po ponownym uruchomieniu."
|
||||
NO_RESULTS_PAGE: "Nie znaleziono {wyników|danych} dla tej strony."
|
||||
NO_ROLLBACK: "Nie znaleziono {oczekujących|poprzednich} wycofywań/przywracań."
|
||||
PATCH_INTERRUPTED: "Aktualizacja przerwana. Spróbuję ponownie przy restarcie."
|
||||
PATCH_OUTDATED_1: "Nie można zaktualizować baz danych starszych niż {0}."
|
||||
PATCH_OUTDATED_2: "Uaktualnij do obsługiwanej wersji CoreProtect."
|
||||
PATCH_PROCESSING: "Przetwarzanie nowych danych. Proszę czekać..."
|
||||
PATCH_SKIP_UPDATE: "Skaczący {tabela|indeks} {aktualizacja|tworzenie|usuwanie} na {0}."
|
||||
PATCH_STARTED: "Działający {0} Aktualizacja. Proszę czekać..."
|
||||
PATCH_SKIP_UPDATE: "Pomijam {tabeli|indeksu} {aktualizację|tworzenie|usuwanie} na {0}."
|
||||
PATCH_STARTED: "Przeprowadzam aktualizację do {0}. Proszę czekać..."
|
||||
PATCH_SUCCESS: "Pomyślnie uaktualniono do {0}."
|
||||
PATCH_UPGRADING: "Trwa aktualizacja bazy danych. Proszę czekać..."
|
||||
PLEASE_SELECT: "Proszę wybrać: \"{0}\" lub \"{1}”."
|
||||
PLEASE_SELECT: "Proszę wybrać: \"{0}\" lub \"{1}\"."
|
||||
PREVIEW_CANCELLED: "Podgląd anulowany."
|
||||
PREVIEW_CANCELLING: "Anulowanie podglądu..."
|
||||
PREVIEW_IN_GAME: "Możesz tylko podglądać wycofania w grze."
|
||||
PREVIEW_TRANSACTION: "Nie możesz wyświetlić podglądu {kontener|inwentarz} transakcje."
|
||||
PREVIEW_TRANSACTION: "Nie możesz wyświetlić podglądu transakcji {kontenera|ekwipunku}."
|
||||
PRIMARY_THREAD_ERROR: "Ta metoda API nie może być używana w głównym wątku."
|
||||
PURGE_ABORTED: "Czyszczenie nie powiodło się. Baza danych może być uszkodzona."
|
||||
PURGE_ERROR: "Nie można przetworzyć {0} dane!"
|
||||
PURGE_ERROR: "Nie można przetworzyć danych {0}!"
|
||||
PURGE_FAILED: "Czyszczenie nie powiodło się. Spróbuj ponownie później."
|
||||
PURGE_IN_PROGRESS: "Trwa czyszczenie. Spróbuj ponownie później."
|
||||
PURGE_MINIMUM_TIME: "Możesz usunąć tylko dane starsze niż {0} {dni|godziny}."
|
||||
PURGE_NOTICE_1: "Pamiętaj, że może to zająć trochę czasu."
|
||||
PURGE_NOTICE_2: "Nie uruchamiaj ponownie serwera przed zakończeniem."
|
||||
PURGE_MINIMUM_TIME: "Możesz usunąć tylko dane starsze niż {0} {dni|godzin}."
|
||||
PURGE_NOTICE_1: "Uwaga, może to zająć trochę czasu."
|
||||
PURGE_NOTICE_2: "Nie restartuj serwera przed zakończeniem."
|
||||
PURGE_OPTIMIZING: "Optymalizacja bazy danych. Proszę czekać..."
|
||||
PURGE_PROCESSING: "Przetwarzanie {0} dane..."
|
||||
PURGE_PROCESSING: "Przetwarzanie danych {0}..."
|
||||
PURGE_REPAIRING: "Próba naprawy. To może zająć troche czasu..."
|
||||
PURGE_ROWS: "{0} {wiersz|wiersze} usuniętych danych."
|
||||
PURGE_STARTED: "Usuwanie danych rozpoczęte w dniu „{0}”."
|
||||
PURGE_SUCCESS: "Udało się czyszczenie danych."
|
||||
PURGE_ROWS: "Usunięto {0} {wiersz|wierszy} danych."
|
||||
PURGE_STARTED: "Usuwanie danych rozpoczęte na \"{0}\"."
|
||||
PURGE_SUCCESS: "Czyszczenie danych zakończono pomyślnie."
|
||||
RAM_STATS: "{0}GB / {1}GB RAM"
|
||||
RELOAD_STARTED: "Ponowne ładowanie konfiguracji - proszę czekać."
|
||||
RELOAD_SUCCESS: "Pomyślnie wczytano konfigurację."
|
||||
ROLLBACK_ABORTED: "Wycofanie lub przywracanie zostało przerwane."
|
||||
ROLLBACK_CHUNKS_FOUND: "Znaleziony {0} {kawałek|kawałki} modyfikować."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "Zmodyfikowane {0}/{1} {kawałek|kawałki}."
|
||||
ROLLBACK_COMPLETED: "{Wycofanie|Przywróć|Podgląd} ukończone dla „{0}”."
|
||||
ROLLBACK_EXCLUDED_USERS: "Wyłączony {użytkownik|użytkownicy}: \"{0}”."
|
||||
ROLLBACK_INCLUDE: "{Zawarte|Wykluczone} {blok|jednostka|cel} {typ|typy}: \"{0}”."
|
||||
ROLLBACK_IN_PROGRESS: "Trwa wycofywanie/przywracanie."
|
||||
ROLLBACK_LENGTH: "Zajęty czas: {0} {sekunda|sekundy}."
|
||||
ROLLBACK_CHUNKS_FOUND: "Znaleziono {0} {chunk|chunków} do zmodyfikowania."
|
||||
ROLLBACK_CHUNKS_MODIFIED: "Zmodyfikowano {0}/{1} {chunk|chunków}."
|
||||
ROLLBACK_COMPLETED: "{Wycofywanie|Przywrócenie|Podgląd} ukończone dla \"{0}\"."
|
||||
ROLLBACK_EXCLUDED_USERS: "{Wykluczony użytkownik|Wykluczeni użytkownicy}: \"{0}\"."
|
||||
ROLLBACK_INCLUDE: "{Zawarte|Wykluczone} {bloku|bytu|celu} {typ|typy}: \"{0}\"."
|
||||
ROLLBACK_IN_PROGRESS: "Już trwa wycofywanie/przywracanie."
|
||||
ROLLBACK_LENGTH: "Zajęty czas: {0} {sekunda|sekund}."
|
||||
ROLLBACK_MODIFIED: "{Zmodyfikowane|Modyfikowanie} {0}."
|
||||
ROLLBACK_RADIUS: "Promień: {0} {blok|bloki}."
|
||||
ROLLBACK_SELECTION: "Promień ustawiony na „{0}”."
|
||||
ROLLBACK_STARTED: "{Wycofanie|Przywróć|Podgląd} zaczęło się \"{0}”."
|
||||
ROLLBACK_RADIUS: "Promień: {0} {blok|bloków}."
|
||||
ROLLBACK_SELECTION: "Promień ustawiony na \"{0}\"."
|
||||
ROLLBACK_STARTED: "{Wycofywanie|Przywrócenie|Podgląd} zaczęło się na \"{0}\"."
|
||||
ROLLBACK_TIME: "Zakres czasu: {0}."
|
||||
ROLLBACK_WORLD_ACTION: "Ograniczony do {świat|działanie} \"{0}”."
|
||||
SIGN_HEADER: "Podpisz wiadomości"
|
||||
STATUS_CONSUMER: "Konsument: {0} {przedmiot|przedmioty} w kolejce."
|
||||
STATUS_DATABASE: "Baza danych: Korzystanie {0}."
|
||||
STATUS_INTEGRATION: "{0}: Integracja {włączone|wyłączone}."
|
||||
ROLLBACK_WORLD_ACTION: "Ograniczony do {świata|akcji} \"{0}\"."
|
||||
SIGN_HEADER: "Wiadomości Tabliczki"
|
||||
STATUS_CONSUMER: "Konsument: {0} {przedmiot|przedmiotów} w kolejce."
|
||||
STATUS_DATABASE: "Baza danych: Używa {0}."
|
||||
STATUS_INTEGRATION: "{0}: Integracja {włączona|wyłączona}."
|
||||
STATUS_LICENSE: "Licencja: {0}"
|
||||
STATUS_SYSTEM: "System: {0}"
|
||||
STATUS_VERSION: "Wersja: {0}"
|
||||
TELEPORTED: "Teleportowany do {0}."
|
||||
TELEPORTED_SAFETY: "Teleportowano cię w bezpieczne miejsce."
|
||||
TELEPORTED_SAFETY: "Teleportowano Cię w bezpieczne miejsce."
|
||||
TELEPORT_PLAYERS: "Polecenie Teleport może być używane tylko przez graczy."
|
||||
TIME_DAYS: "{0} {dzień|dni}"
|
||||
TIME_HOURS: "{0} {godzina|godziny}"
|
||||
TIME_MINUTES: "{0} {minuta|minuty}"
|
||||
TIME_SECONDS: "{0} {sekunda|sekundy}"
|
||||
TIME_WEEKS: "{0} {tydzień|tygodnie}"
|
||||
TIME_HOURS: "{0} {godzina|godzin(y)}"
|
||||
TIME_MINUTES: "{0} {minuta|minut(y)}"
|
||||
TIME_MONTHS: "{0} {miesiąc|miesięcy}"
|
||||
TIME_SECONDS: "{0} {sekunda|sekund(y)}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {tydzień|tygodni(e)}"
|
||||
TIME_YEARS: "{0} {rok|lat(a)}"
|
||||
UPDATE_ERROR: "Wystąpił błąd podczas sprawdzania aktualizacji."
|
||||
UPDATE_HEADER: "{0} Aktualizacja"
|
||||
UPDATE_HEADER: "Aktualizacja {0}"
|
||||
UPDATE_NOTICE: "Ogłoszenie: {0} jest teraz dostępne."
|
||||
UPGRADE_IN_PROGRESS: "Trwa aktualizacja. Spróbuj ponownie później."
|
||||
USER_NOT_FOUND: "Użytkownik \"{0}\" nie znaleziono."
|
||||
USER_NOT_FOUND: "Nie znaleziono użytkownika \"{0}\"."
|
||||
USER_OFFLINE: "Użytkownik \"{0}\" nie jest online."
|
||||
USING_MYSQL: "Za pomocą MySQL do przechowywania danych."
|
||||
USING_SQLITE: "Za pomocą SQLite do przechowywania danych."
|
||||
USING_MYSQL: "MySQL używany do przechowywania danych."
|
||||
USING_SQLITE: "SQLite używany do przechowywania danych."
|
||||
VALID_DONATION_KEY: "Ważny klucz darowizny."
|
||||
VERSION_NOTICE: "Wersja {0} jest teraz dostępne."
|
||||
VERSION_INCOMPATIBLE: "{0} {1} nie jest wspierany."
|
||||
VERSION_NOTICE: "Wersja {0} jest teraz dostępna."
|
||||
VERSION_REQUIRED: "{0} {1} lub wyższy jest wymagany."
|
||||
WORLD_NOT_FOUND: "Świat \"{0}\" nie znaleziono."
|
||||
WORLD_NOT_FOUND: "Nie znaleziono świata \"{0}\"."
|
||||
+7
-6
@@ -46,7 +46,7 @@ HELP_INSPECT_2: "Щелкните левой кнопкой мыши по бло
|
||||
HELP_INSPECT_3: "Щелкните блок правой кнопкой мыши, чтобы увидеть, какой соседний блок был сломан.."
|
||||
HELP_INSPECT_4: "Поместите блок, чтобы увидеть, какой блок был сломан в этом месте."
|
||||
HELP_INSPECT_5: "Поместите блок в жидкость (и т.п.), чтобы увидеть, кто его поместил."
|
||||
HELP_INSPECT_6: "Щелкните правой кнопкой мыши дверь, сундук и т. Д., Чтобы узнать, кто последний использовал их."
|
||||
HELP_INSPECT_6: "Щелкните правой кнопкой мыши дверь, сундук и т.д., чтобы узнать, кто последний использовал их."
|
||||
HELP_INSPECT_7: "Подсказка: Вы можете использовать «/co i» для быстрого переключения режима инспектора."
|
||||
HELP_INSPECT_COMMAND: "Включает или выключает режим инспектора блоков."
|
||||
HELP_LIST: "Отображает список всех команд."
|
||||
@@ -139,7 +139,7 @@ PATCH_SKIP_UPDATE: "{Пропущена таблица|Пропущен инде
|
||||
PATCH_STARTED: "Выполняется обновление {0}. Пожалуйста, подождите..."
|
||||
PATCH_SUCCESS: "Успешно обновлен до {0}."
|
||||
PATCH_UPGRADING: "Выполняется обновление базы данных. Пожалуйста, подождите..."
|
||||
PLEASE_SELECT: "Пожалуйта выберете: «{0}» или «{1}»."
|
||||
PLEASE_SELECT: "Пожалуйста выберите: «{0}» или «{1}»."
|
||||
PREVIEW_CANCELLED: "Предварительный просмотр отменен."
|
||||
PREVIEW_CANCELLING: "Отмена предварительного просмотра..."
|
||||
PREVIEW_IN_GAME: "Предварительный просмотр откатов доступен только в игре."
|
||||
@@ -180,22 +180,23 @@ STATUS_INTEGRATION: "{0}: Интеграция {включена|отключе
|
||||
STATUS_LICENSE: "Лицензия: {0}"
|
||||
STATUS_VERSION: "Версия: {0}"
|
||||
TELEPORTED: "Телепортирование в {0}."
|
||||
TELEPORTED_SAFETY: "Телепортирование вас в безопасное место."
|
||||
TELEPORT_PLAYERS: "Команду телепортации могут использовать только игроки.."
|
||||
TELEPORTED_SAFETY: "Телепортируем вас в безопасное место."
|
||||
TELEPORT_PLAYERS: "Команду телепортации могут использовать только игроки."
|
||||
TIME_DAYS: "{0} {дня|дней}"
|
||||
TIME_HOURS: "{0} {час|часов}"
|
||||
TIME_MINUTES: "{0} {минута|минут}"
|
||||
TIME_SECONDS: "{0} {секунда|секунд}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {неделя|недель}"
|
||||
UPDATE_ERROR: "Произошла ошибка при проверке обновлений."
|
||||
UPDATE_HEADER: "{0} Обновление"
|
||||
UPDATE_NOTICE: "Примечание: теперь доступен {0}."
|
||||
UPGRADE_IN_PROGRESS: "Выполняется обновление. Пожалуйста, повторите попытку позже."
|
||||
USER_NOT_FOUND: "Пользователь «{0}» не найден."
|
||||
USER_OFFLINE: "Пользователь \"{0}\" нет в сети."
|
||||
USER_OFFLINE: "Пользователь \"{0}\" не в сети."
|
||||
USING_MYSQL: "Для хранения данных используется MySQL."
|
||||
USING_SQLITE: "Для хранения данных используется SQLite."
|
||||
VALID_DONATION_KEY: "Действующий ключ пожертвования."
|
||||
VERSION_NOTICE: "Версия {0} уже доступна!"
|
||||
VERSION_REQUIRED: "{0} {1} или выше требуется."
|
||||
WORLD_NOT_FOUND: "Мир «{0}» не найден."
|
||||
WORLD_NOT_FOUND: "Мир «{0}» не найден."
|
||||
@@ -186,6 +186,7 @@ TIME_DAYS: "{0} {gün|gün}"
|
||||
TIME_HOURS: "{0} {saat|saat}"
|
||||
TIME_MINUTES: "{0} {dakika|dakika}"
|
||||
TIME_SECONDS: "{0} {saniye|saniye}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {hafta|hafta}"
|
||||
UPDATE_ERROR: "Güncellemeler kontrol edilirken bir hata oluştu."
|
||||
UPDATE_HEADER: "{0} Güncelleme"
|
||||
|
||||
+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}\" табылмады.\""
|
||||
@@ -186,6 +186,7 @@ TIME_DAYS: "{0} {день|дні}"
|
||||
TIME_HOURS: "{0} {година|години}"
|
||||
TIME_MINUTES: "{0} {хвилина|хвилини}"
|
||||
TIME_SECONDS: "{0} {секунда|секунди}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {тиждень|тиждень}"
|
||||
UPDATE_ERROR: "Під час перевірки оновлень сталася помилка."
|
||||
UPDATE_HEADER: "{0} Оновлення"
|
||||
|
||||
@@ -186,6 +186,7 @@ TIME_DAYS: "{0} {ngày|ngày}"
|
||||
TIME_HOURS: "{0} {giờ|giờ}"
|
||||
TIME_MINUTES: "{0} {phút|phút}"
|
||||
TIME_SECONDS: "{0} {giây|giây}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {tuần|tuần}"
|
||||
UPDATE_ERROR: "Đã xảy ra lỗi khi kiểm tra các bản cập nhật."
|
||||
UPDATE_HEADER: "{0} Cập nhật"
|
||||
|
||||
+130
-119
@@ -1,202 +1,213 @@
|
||||
# CoreProtect Language File (zh-CN)
|
||||
# Origin: Intelli, Translator: DreamVoid, StarWishsama, YuanYuanOwO
|
||||
# Origin: Intelli, Translator: DreamVoid, StarWishsama, YuanYuanOwO, Halogly
|
||||
|
||||
ACTION_NOT_SUPPORTED: "该命令不支持该操作。"
|
||||
ACTION_NOT_SUPPORTED: "此命令不支持该操作。"
|
||||
AMOUNT_BLOCK: "{0}个{方块|方块}"
|
||||
AMOUNT_CHUNK: "{0}个{区块|区块}"
|
||||
AMOUNT_ENTITY: "{0}个{实体|实体}"
|
||||
AMOUNT_ITEM: "{0}个{物品|物品}"
|
||||
API_TEST: "API 测试成功。"
|
||||
CACHE_ERROR: "警告: 验证缓存 {0} 时出错。"
|
||||
CACHE_RELOAD: "正在强制从数据库中重新加载{映射|世界}的缓存。"
|
||||
CACHE_ERROR: "警告:验证缓存 {0} 时出错。"
|
||||
CACHE_RELOAD: "正在强制从数据库中重新加载{映射|世界}缓存。"
|
||||
CHECK_CONFIG: "请检查 config.yml 文件"
|
||||
COMMAND_CONSOLE: "请在控制台中运行此命令。"
|
||||
COMMAND_NOT_FOUND: "找不到命令 \"{0}\""
|
||||
COMMAND_THROTTLED: "请稍等片刻,然后重试。"
|
||||
COMMAND_NOT_FOUND: "命令 \"{0}\" 未找到。"
|
||||
COMMAND_THROTTLED: "请稍后再试。"
|
||||
CONSUMER_ERROR: "数据处理队列已经{暂停|恢复}。"
|
||||
CONSUMER_TOGGLED: "数据处理队列现已{暂停|恢复}。"
|
||||
CONSUMER_TOGGLED: "数据处理队列已{暂停|恢复}。"
|
||||
CONTAINER_HEADER: "容器物品变更记录"
|
||||
DATABASE_BUSY: "数据库繁忙,请稍后重试。"
|
||||
CPU_CORES: "CPU 核心。"
|
||||
DATABASE_BUSY: "数据库繁忙,请稍后再试。"
|
||||
DATABASE_INDEX_ERROR: "无法验证数据库索引。"
|
||||
DATABASE_LOCKED_1: "数据库已被锁定,请等待至少15秒后重试..."
|
||||
DATABASE_LOCKED_2: "数据库已在使用,请再试一次。"
|
||||
DATABASE_LOCKED_3: "禁用数据库锁定,请在配置文件中设置 \"database-lock: false\"。"
|
||||
DATABASE_LOCKED_1: "数据库已锁定,请等待约15秒后再试..."
|
||||
DATABASE_LOCKED_2: "数据库正在使用中,请稍后再试。"
|
||||
DATABASE_LOCKED_3: "要禁用数据库锁定,请在配置文件中设置 \"database-lock: false\"。"
|
||||
DATABASE_LOCKED_4: "禁用数据库锁定可能会导致数据损坏。"
|
||||
DATABASE_UNREACHABLE: "数据库无法访问。正在丢弃数据并关闭。"
|
||||
DATABASE_UNREACHABLE: "数据库连接失败,正在丢弃数据并关闭。"
|
||||
DEVELOPMENT_BRANCH: "检测到正在使用开发分支的版本,跳过使用补丁脚本。"
|
||||
DIRT_BLOCK: "已在你的下方放置了一个泥土。"
|
||||
DISABLE_SUCCESS: "禁用 {0} 成功!"
|
||||
ENABLE_FAILED: "无法启用 {0}!"
|
||||
ENABLE_SUCCESS: "{0} 已成功启用!"
|
||||
DISABLE_SUCCESS: "已成功禁用 {0}!"
|
||||
DONATION_KEY_REQUIRED: "需要有效的捐赠密钥才能执行此命令。"
|
||||
ENABLE_FAILED: "无法启用 {0}。"
|
||||
ENABLE_SUCCESS: "已成功启用 {0}!"
|
||||
ENJOY_COREPROTECT: "对 {0} 感到满意吗?请加入我们的 Discord 频道!"
|
||||
FINISHING_CONVERSION: "正在完成数据转换,请稍等..."
|
||||
FINISHING_LOGGING: "正在完成数据记录,请稍等..."
|
||||
FIRST_VERSION: "初始化数据库: {0}"
|
||||
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_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_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_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_INSPECT_7: "提示:你可以使用 \"/co i\" 进行快速查询。"
|
||||
HELP_INSPECT_COMMAND: "开启或关闭方块检查器。"
|
||||
HELP_LIST: "列出所有命令。"
|
||||
HELP_LOOKUP_1: "命令快捷方式。"
|
||||
HELP_LOOKUP_2: "在查询记录后使用以查看日志"
|
||||
HELP_LOOKUP_2: "检查方块后使用以查看日志。"
|
||||
HELP_LOOKUP_COMMAND: "高级方块数据查询。"
|
||||
HELP_NO_INFO: "命令的信息 \"{0}\" 未找到。"
|
||||
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_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] (只会影响你周围十格方块的范围)"
|
||||
HELP_RADIUS_2: "例子:[r: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: "检查器已经{启用|禁用}了。"
|
||||
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} 的版本不兼容。"
|
||||
INTEGRATION_ERROR: "无法{初始化|禁用} {0} 的日志记录。"
|
||||
INTEGRATION_SUCCESS: "已成功{初始化|禁用} {0} 的日志记录。"
|
||||
INTEGRATION_VERSION: "{0} 版本无效。"
|
||||
INTERACTIONS_HEADER: "玩家交互"
|
||||
INVALID_ACTION: "这不是有效的动作。"
|
||||
INVALID_BRANCH_1: "插件版本无效(未设置分支)。"
|
||||
INVALID_BRANCH_2: "要继续,请将项目分支设置为 \"开发\"。"
|
||||
INVALID_ACTION: "这不是一个有效的操作。"
|
||||
INVALID_BRANCH_1: "插件版本无效(尚未设置分支)。"
|
||||
INVALID_BRANCH_2: "请将项目分支设置为 \"development\" 以继续。"
|
||||
INVALID_BRANCH_3: "运行开发版本的插件可能会导致数据损坏。"
|
||||
INVALID_CONTAINER: "请检查有效的容器。"
|
||||
INVALID_CONTAINER: "请先检查一个有效的容器。"
|
||||
INVALID_DONATION_KEY: "无效的捐赠密钥。"
|
||||
INVALID_INCLUDE: "\"{0}\" 是无效的方块/实体名称。"
|
||||
INVALID_INCLUDE_COMBO: "那是无效的方块/实体组合。"
|
||||
INVALID_RADIUS: "请输入有效的半径。"
|
||||
INVALID_SELECTION: "没有找到 {0} 的选择。"
|
||||
INVALID_USERNAME: "玩家名 \"{0}\" 不存在或已离线。"
|
||||
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}。"
|
||||
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_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}."
|
||||
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_LOOKUP_TIME: "请指定要{查找|回滚|恢复}的时间。"
|
||||
MISSING_LOOKUP_USER: "请指定要查找的玩家或{方块|半径}。"
|
||||
MISSING_PARAMETERS: "请使用 \"{0}\"。"
|
||||
MISSING_ROLLBACK_RADIUS: "你没有指定{回滚|恢复}半径。"
|
||||
MISSING_ROLLBACK_USER: "你没有指定{回滚|恢复}的玩家操作。"
|
||||
MISSING_ROLLBACK_RADIUS: "你没有指定{回滚|恢复}的半径。"
|
||||
MISSING_ROLLBACK_USER: "你没有指定{回滚|恢复}的玩家。"
|
||||
MYSQL_UNAVAILABLE: "无法连接到 MySQL 服务器。"
|
||||
NO_DATA: "没有在 {0} 中找到数据"
|
||||
NO_DATA_LOCATION: "此位置找不到任何{数据|存取|交互|消息}的记录。"
|
||||
NETWORK_CONNECTION: "{0} 连接{成功|失败},正在使用 {1} {2}。"
|
||||
NETWORK_TEST: "网络测试数据已成功发送。"
|
||||
NO_DATA: "没有在 {0} 中找到数据。"
|
||||
NO_DATA_LOCATION: "此位置找不到任何{数据|存取|交互|消息}记录。"
|
||||
NO_PERMISSION: "你没有权限执行此操作。"
|
||||
NO_RESULTS: "未找到结果。"
|
||||
NO_RESULTS_PAGE: "没有在指定页面找到{结果|数据}。"
|
||||
NO_ROLLBACK: "没有找到{等待的|上一个}回滚/恢复。"
|
||||
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}\"。"
|
||||
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_FAILED: "清除失败,请稍后再试。"
|
||||
PURGE_IN_PROGRESS: "正在清除数据,请稍后再试。"
|
||||
PURGE_MINIMUM_TIME: "你只能清除早于 {0} {天|小时}的数据."
|
||||
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: "数据清除成功。"
|
||||
PURGE_NOTICE_2: "完成前请勿重新启动服务器。"
|
||||
PURGE_OPTIMIZING: "正在优化数据库,请稍候..."
|
||||
PURGE_PROCESSING: "正在处理 {0} 的数据..."
|
||||
PURGE_REPAIRING: "正在尝试修复。这可能需要一些时间..."
|
||||
PURGE_ROWS: "{0}{行|行}数据已删除。"
|
||||
PURGE_STARTED: "数据清除开始于 \"{0}\"。"
|
||||
PURGE_SUCCESS: "数据已清除。"
|
||||
RAM_STATS: "{0}GB / {1}GB 内存"
|
||||
RELOAD_STARTED: "正在重新加载配置文件 - 请稍候。"
|
||||
RELOAD_SUCCESS: "配置文件已重新加载成功。"
|
||||
RELOAD_SUCCESS: "配置文件已重新加载。"
|
||||
ROLLBACK_ABORTED: "回滚或恢复已中止。"
|
||||
ROLLBACK_CHUNKS_FOUND: "找到 {0} 个{区块|区块}需要更改。"
|
||||
ROLLBACK_CHUNKS_MODIFIED: "已修改 {0}/{1} 个{区块|区块}."
|
||||
ROLLBACK_COMPLETED: "{回滚|恢复|预览}已对以下对象完成: {0}。"
|
||||
ROLLBACK_EXCLUDED_USERS: "已排除{玩家|玩家}: \"{0}\"。"
|
||||
ROLLBACK_INCLUDE: "{包括|不包括}{方块|实体|目标}{类型|类型}: \"{0}\"。"
|
||||
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_VERSION: "版本: {0}"
|
||||
TELEPORTED: "传送到 {0}."
|
||||
TELEPORTED_SAFETY: "将你传送到安全地点。"
|
||||
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_MONTHS: "{0} {月|月}"
|
||||
TIME_SECONDS: "{0}{秒|秒}"
|
||||
TIME_UNITS: "{分钟|小时|天}"
|
||||
TIME_WEEKS: "{0}{周|周}"
|
||||
TIME_YEARS: "{0} {年|年}"
|
||||
UPDATE_ERROR: "检查更新时出错。"
|
||||
UPDATE_HEADER: "{0} 更新"
|
||||
UPDATE_NOTICE: "注意: {0} 现在可用。"
|
||||
UPDATE_NOTICE: "注意:{0} 现在可用。"
|
||||
UPGRADE_IN_PROGRESS: "正在进行升级,请稍后再试。"
|
||||
USER_NOT_FOUND: "玩家\"{0}\"未找到。"
|
||||
USER_OFFLINE: "玩家\"{0}\"不在线。"
|
||||
USER_NOT_FOUND: "玩家 \"{0}\" 未找到。"
|
||||
USER_OFFLINE: "玩家 \"{0}\" 不在线。"
|
||||
USING_MYSQL: "使用 MySQL 用于数据存储。"
|
||||
USING_SQLITE: "使用 SQLite 用于数据存储。"
|
||||
VALID_DONATION_KEY: "有效的捐赠密钥。"
|
||||
VERSION_INCOMPATIBLE: "{0} {1} 不受支持。"
|
||||
VERSION_NOTICE: "版本 {0} 现在可用。"
|
||||
VERSION_REQUIRED: "{0} 需要使用 {1} 或更高版本。"
|
||||
WORLD_NOT_FOUND: "找不到世界 \"{0}\"。"
|
||||
WORLD_NOT_FOUND: "世界 \"{0}\" 未找到。"
|
||||
@@ -193,6 +193,7 @@ TIME_DAYS: "{0} {天|天}"
|
||||
TIME_HOURS: "{0} {小時|小時}"
|
||||
TIME_MINUTES: "{0} {分鐘|分鐘}"
|
||||
TIME_SECONDS: "{0} {秒|秒}"
|
||||
TIME_UNITS: "{/m|/h|/d}"
|
||||
TIME_WEEKS: "{0} {週|週}"
|
||||
UPDATE_ERROR: "檢查更新時發生錯誤。"
|
||||
UPDATE_HEADER: "{0} 更新"
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>net.coreprotect</groupId>
|
||||
<artifactId>CoreProtect</artifactId>
|
||||
<version>23.0</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>
|
||||
@@ -113,6 +115,31 @@
|
||||
<skipTests>${skipTests}</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>3.6.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals><goal>enforce</goal></goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireNoRepositories>
|
||||
<allowedRepositories>
|
||||
<allowedRepository>central</allowedRepository>
|
||||
<allowedRepository>enginehub-repo</allowedRepository>
|
||||
<allowedRepository>spigot-repo</allowedRepository>
|
||||
<allowedRepository>paper-repo</allowedRepository>
|
||||
<allowedRepository>codemc-repo</allowedRepository>
|
||||
<allowedRepository>jitpack.io</allowedRepository>
|
||||
</allowedRepositories>
|
||||
</requireNoRepositories>
|
||||
</rules>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<profiles>
|
||||
@@ -127,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>
|
||||
@@ -152,6 +179,18 @@
|
||||
</profile>
|
||||
</profiles>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>central</id>
|
||||
<url>https://repo.maven.apache.org/maven2/</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>false</enabled></snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>enginehub-repo</id>
|
||||
<url>https://maven.enginehub.org/repo/</url>
|
||||
<releases><enabled>true</enabled></releases>
|
||||
<snapshots><enabled>true</enabled></snapshots>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
|
||||
@@ -169,71 +208,57 @@
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.intellectualsites.bom</groupId>
|
||||
<artifactId>bom-newest</artifactId> <!-- Ref: https://github.com/IntellectualSites/bom -->
|
||||
<version>1.45</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
<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.1-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.15.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fastasyncworldedit</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Bukkit</artifactId>
|
||||
<version>2.15.0</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<artifactId>FastAsyncWorldEdit-Core</artifactId>
|
||||
<groupId>*</groupId>
|
||||
<artifactId>FastAsyncWorldEdit-Core</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<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>
|
||||
@@ -245,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>
|
||||
@@ -281,26 +306,26 @@
|
||||
<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>
|
||||
</project>
|
||||
</project>
|
||||
@@ -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 = 10;
|
||||
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,14 +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;
|
||||
@@ -19,7 +28,12 @@ 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;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.MerchantRecipe;
|
||||
@@ -52,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.
|
||||
@@ -78,13 +103,21 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------- Basic data conversion methods --------------------
|
||||
public static Set<Material> EMPTY_SET = new HashSet<>(Arrays.asList());
|
||||
|
||||
@Override
|
||||
public String parseLegacyName(String name) {
|
||||
@@ -108,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+
|
||||
@@ -177,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
|
||||
@@ -216,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);
|
||||
@@ -311,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
|
||||
@@ -350,4 +446,59 @@ public class BukkitAdapter implements BukkitInterface {
|
||||
public Object getRegistryValue(String key, Object tClass) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,14 @@ package net.coreprotect.bukkit;
|
||||
|
||||
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;
|
||||
@@ -13,7 +17,12 @@ 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;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.MerchantRecipe;
|
||||
@@ -72,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
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -130,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.
|
||||
*
|
||||
@@ -139,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.
|
||||
*
|
||||
@@ -241,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+.
|
||||
@@ -400,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
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -424,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.
|
||||
*
|
||||
@@ -432,4 +523,13 @@ public interface BukkitInterface {
|
||||
* @return The parsed name
|
||||
*/
|
||||
String parseLegacyName(String name);
|
||||
|
||||
boolean isCrafter(InventoryType type);
|
||||
|
||||
boolean isCopperChest(Material material);
|
||||
|
||||
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,16 +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.
|
||||
@@ -20,7 +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.
|
||||
@@ -29,6 +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());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,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.
|
||||
*
|
||||
@@ -72,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.
|
||||
@@ -103,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.
|
||||
@@ -121,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+.
|
||||
@@ -154,4 +284,164 @@ public class Bukkit_v1_21 extends Bukkit_v1_20 implements BukkitInterface {
|
||||
wolf.setVariant(variant);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCrafter(InventoryType type) {
|
||||
return type == InventoryType.CRAFTER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCopperChest(Material material) {
|
||||
if (COPPER_CHESTS.contains(material) && material != Material.CHEST) {
|
||||
return true;
|
||||
}
|
||||
|
||||
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()) {
|
||||
Material copperChest = Material.getMaterial("COPPER_CHEST");
|
||||
if (copperChest == null) {
|
||||
COPPER_CHESTS.add(Material.CHEST);
|
||||
}
|
||||
else {
|
||||
COPPER_CHESTS.add(Material.getMaterial("COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("EXPOSED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("WEATHERED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("OXIDIZED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("WAXED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("WAXED_EXPOSED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("WAXED_WEATHERED_COPPER_CHEST"));
|
||||
COPPER_CHESTS.add(Material.getMaterial("WAXED_OXIDIZED_COPPER_CHEST"));
|
||||
}
|
||||
}
|
||||
|
||||
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<>();
|
||||
@@ -39,9 +40,13 @@ public class StatusCommand {
|
||||
String versionCheck = "";
|
||||
if (Config.getGlobal().CHECK_UPDATES) {
|
||||
String latestVersion = NetworkHandler.latestVersion();
|
||||
String latestEdgeVersion = NetworkHandler.latestEdgeVersion();
|
||||
if (latestVersion != null) {
|
||||
versionCheck = " (" + Phrase.build(Phrase.LATEST_VERSION, "v" + latestVersion) + ")";
|
||||
}
|
||||
else if (latestEdgeVersion != null && !VersionUtils.isCommunityEdition()) {
|
||||
versionCheck = " (" + Phrase.build(Phrase.LATEST_VERSION, "v" + latestEdgeVersion) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
Chat.sendMessage(player, Color.WHITE + "----- " + Color.DARK_AQUA + "CoreProtect" + (VersionUtils.isCommunityEdition() ? " " + ConfigHandler.COMMUNITY_EDITION : "") + Color.WHITE + " -----");
|
||||
@@ -100,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];
|
||||
@@ -116,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
|
||||
@@ -128,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;
|
||||
@@ -146,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/");
|
||||
@@ -169,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,19 +38,25 @@ 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 {
|
||||
|
||||
public enum CacheType {
|
||||
MATERIALS, BLOCKDATA, ART, ENTITIES, WORLDS
|
||||
}
|
||||
|
||||
public static int SERVER_VERSION = 0;
|
||||
public static final int EDITION_VERSION = 2;
|
||||
public static final String EDITION_BRANCH = VersionUtils.getBranch();
|
||||
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 LATEST_VERSION = "1.21.8";
|
||||
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";
|
||||
@@ -59,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();
|
||||
@@ -76,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<>());
|
||||
@@ -94,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<>();
|
||||
@@ -146,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,7 +289,7 @@ public class ConfigHandler extends Queue {
|
||||
Class.forName("org.sqlite.JDBC");
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -268,7 +329,7 @@ public class ConfigHandler extends Queue {
|
||||
Database.createDatabaseTables(ConfigHandler.prefix, false, null, Config.getGlobal().MYSQL, false);
|
||||
}
|
||||
|
||||
public static void loadTypes(Statement statement) {
|
||||
public static void loadMaterials(Statement statement) {
|
||||
try {
|
||||
String query = "SELECT id,material FROM " + ConfigHandler.prefix + "material_map";
|
||||
ResultSet rs = statement.executeQuery(query);
|
||||
@@ -286,9 +347,16 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
query = "SELECT id,data FROM " + ConfigHandler.prefix + "blockdata_map";
|
||||
rs = statement.executeQuery(query);
|
||||
public static void loadBlockdata(Statement statement) {
|
||||
try {
|
||||
String query = "SELECT id,data FROM " + ConfigHandler.prefix + "blockdata_map";
|
||||
ResultSet rs = statement.executeQuery(query);
|
||||
ConfigHandler.blockdata.clear();
|
||||
ConfigHandler.blockdataReversed.clear();
|
||||
blockdataId = 0;
|
||||
@@ -303,9 +371,16 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
query = "SELECT id,art FROM " + ConfigHandler.prefix + "art_map";
|
||||
rs = statement.executeQuery(query);
|
||||
public static void loadArt(Statement statement) {
|
||||
try {
|
||||
String query = "SELECT id,art FROM " + ConfigHandler.prefix + "art_map";
|
||||
ResultSet rs = statement.executeQuery(query);
|
||||
ConfigHandler.art.clear();
|
||||
ConfigHandler.artReversed.clear();
|
||||
artId = 0;
|
||||
@@ -320,9 +395,16 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
query = "SELECT id,entity FROM " + ConfigHandler.prefix + "entity_map";
|
||||
rs = statement.executeQuery(query);
|
||||
public static void loadEntities(Statement statement) {
|
||||
try {
|
||||
String query = "SELECT id,entity FROM " + ConfigHandler.prefix + "entity_map";
|
||||
ResultSet rs = statement.executeQuery(query);
|
||||
ConfigHandler.entities.clear();
|
||||
ConfigHandler.entitiesReversed.clear();
|
||||
entityId = 0;
|
||||
@@ -339,10 +421,71 @@ public class ConfigHandler extends Queue {
|
||||
rs.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void loadTypes(Statement statement) {
|
||||
loadMaterials(statement);
|
||||
loadBlockdata(statement);
|
||||
loadArt(statement);
|
||||
loadEntities(statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified method to reload cache from database when DATABASE_LOCK is false (multi-server setup)
|
||||
*
|
||||
* @param type
|
||||
* The type of cache to reload
|
||||
* @param name
|
||||
* The name to look up after reload
|
||||
* @return The ID if found after reload, or -1 if not found
|
||||
*/
|
||||
public static int reloadAndGetId(CacheType type, String name) {
|
||||
// Only reload if DATABASE_LOCK is false (multi-server setup)
|
||||
if (Config.getGlobal().DATABASE_LOCK) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(true)) {
|
||||
if (connection != null) {
|
||||
Statement statement = connection.createStatement();
|
||||
|
||||
// Reload appropriate cache based on type
|
||||
switch (type) {
|
||||
case MATERIALS:
|
||||
loadMaterials(statement);
|
||||
statement.close();
|
||||
return materials.getOrDefault(name, -1);
|
||||
case BLOCKDATA:
|
||||
loadBlockdata(statement);
|
||||
statement.close();
|
||||
return blockdata.getOrDefault(name, -1);
|
||||
case ART:
|
||||
loadArt(statement);
|
||||
statement.close();
|
||||
return art.getOrDefault(name, -1);
|
||||
case ENTITIES:
|
||||
loadEntities(statement);
|
||||
statement.close();
|
||||
return entities.getOrDefault(name, -1);
|
||||
case WORLDS:
|
||||
loadWorlds(statement);
|
||||
statement.close();
|
||||
return worlds.getOrDefault(name, -1);
|
||||
default:
|
||||
statement.close();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public static void loadWorlds(Statement statement) {
|
||||
try {
|
||||
String query = "SELECT id,world FROM " + ConfigHandler.prefix + "world";
|
||||
@@ -375,7 +518,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,7 +557,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -435,7 +578,7 @@ public class ConfigHandler extends Queue {
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
try (Connection connection = Database.getConnection(true, 0)) {
|
||||
@@ -470,7 +613,7 @@ public class ConfigHandler extends Queue {
|
||||
return validVersion && databaseLock;
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ErrorReporter.report(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -482,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);
|
||||
|
||||
Loaded 100 of 258 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user