Added ability to specify specific block types in the purge command

This commit is contained in:
Intelli 2024-05-13 16:13:55 -06:00
parent b41e40acc0
commit 5bc28b3e05
2 changed files with 127 additions and 13 deletions

View File

@ -93,7 +93,7 @@ Purge old block data. Useful for freeing up space on your HDD if you don't need
| Command | Parameters | | Command | Parameters |
| --- | --- | | --- | --- |
| /co purge | `t:<time> r:<world>` | | /co purge | `t:<time> r:<world> i:<include>` |
For example, `/co purge t:30d` will delete all data older than one month, and only keep the last 30 days of data. For example, `/co purge t:30d` will delete all data older than one month, and only keep the last 30 days of data.
@ -101,8 +101,12 @@ For example, `/co purge t:30d` will delete all data older than one month, and on
> If used from the console, only data older than 24 hours can be purged. > If used from the console, only data older than 24 hours can be purged.
**Purging Worlds** **Purging Worlds**
You can also optionally specify a world in CoreProtect v19+. You can optionally specify a world in CoreProtect v19+.
For example, `/co purge t:30d r:#world_nether` will delete all data older than one month in the Nether, without deleting data in any other worlds. For example, `/co purge t:30d r:#world_nether` will delete all data older than one month in the Nether, without removing data in any other worlds.
**Purging Blocks**
You can optionally specify block types in CoreProtect v23+.
For example, `/co purge t:30d i:stone,dirt` will delete all stone and dirt data older than one month, without removing other block data.
**MySQL Optimization** **MySQL Optimization**
In CoreProtect v2.15+, adding "#optimize" to the end of the command (e.g. `/co purge t:30d #optimize`) will also optimize your tables and reclaim disk space. In CoreProtect v2.15+, adding "#optimize" to the end of the command (e.g. `/co purge t:30d #optimize`) will also optimize your tables and reclaim disk space.

View File

@ -8,11 +8,16 @@ import java.sql.ResultSetMetaData;
import java.text.NumberFormat; import java.text.NumberFormat;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import net.coreprotect.bukkit.BukkitAdapter;
import net.coreprotect.config.Config; import net.coreprotect.config.Config;
import net.coreprotect.config.ConfigHandler; import net.coreprotect.config.ConfigHandler;
import net.coreprotect.consumer.Consumer; import net.coreprotect.consumer.Consumer;
@ -31,13 +36,20 @@ public class PurgeCommand extends Consumer {
int resultc = args.length; int resultc = args.length;
Location location = CommandHandler.parseLocation(player, args); Location location = CommandHandler.parseLocation(player, args);
final Integer[] argRadius = CommandHandler.parseRadius(args, player, location); final Integer[] argRadius = CommandHandler.parseRadius(args, player, location);
final List<Integer> argAction = CommandHandler.parseAction(args);
final List<Object> argBlocks = CommandHandler.parseRestricted(player, args, argAction);
final Map<Object, Boolean> argExclude = CommandHandler.parseExcluded(player, args, argAction);
final List<String> argExcludeUsers = CommandHandler.parseExcludedUsers(player, args);
final long[] argTime = CommandHandler.parseTime(args); final long[] argTime = CommandHandler.parseTime(args);
final int argWid = CommandHandler.parseWorld(args, false, false); final int argWid = CommandHandler.parseWorld(args, false, false);
final List<Integer> argAction = CommandHandler.parseAction(args);
final List<Integer> supportedActions = Arrays.asList(); final List<Integer> supportedActions = Arrays.asList();
long startTime = argTime[1] > 0 ? argTime[0] : 0; long startTime = argTime[1] > 0 ? argTime[0] : 0;
long endTime = argTime[1] > 0 ? argTime[1] : argTime[0]; long endTime = argTime[1] > 0 ? argTime[1] : argTime[0];
if (argBlocks == null || argExclude == null || argExcludeUsers == null) {
return;
}
if (ConfigHandler.converterRunning) { if (ConfigHandler.converterRunning) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.UPGRADE_IN_PROGRESS)); Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.UPGRADE_IN_PROGRESS));
return; return;
@ -67,6 +79,14 @@ public class PurgeCommand extends Consumer {
Chat.sendMessage(player, new ChatMessage(Phrase.build(Phrase.WORLD_NOT_FOUND, worldName)).build()); Chat.sendMessage(player, new ChatMessage(Phrase.build(Phrase.WORLD_NOT_FOUND, worldName)).build());
return; return;
} }
if (player instanceof Player && endTime < 2592000) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PURGE_MINIMUM_TIME, "30", Selector.FIRST)); // 30 days
return;
}
else if (endTime < 86400) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PURGE_MINIMUM_TIME, "24", Selector.SECOND)); // 24 hours
return;
}
for (int action : argAction) { for (int action : argAction) {
if (!supportedActions.contains(action)) { if (!supportedActions.contains(action)) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ACTION_NOT_SUPPORTED)); Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ACTION_NOT_SUPPORTED));
@ -74,12 +94,70 @@ public class PurgeCommand extends Consumer {
return; return;
} }
} }
if (player instanceof Player && endTime < 2592000) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PURGE_MINIMUM_TIME, "30", Selector.FIRST)); // 30 days StringBuilder restrict = new StringBuilder();
return; String includeBlock = "";
String includeEntity = "";
boolean hasBlock = false;
boolean item = false;
boolean entity = false;
int restrictCount = 0;
if (argBlocks.size() > 0) {
StringBuilder includeListMaterial = new StringBuilder();
StringBuilder includeListEntity = new StringBuilder();
for (Object restrictTarget : argBlocks) {
String targetName = "";
if (restrictTarget instanceof Material) {
targetName = ((Material) restrictTarget).name();
if (includeListMaterial.length() == 0) {
includeListMaterial = includeListMaterial.append(Util.getBlockId(targetName, false));
}
else {
includeListMaterial.append(",").append(Util.getBlockId(targetName, false));
}
/* Include legacy IDs */
int legacyId = BukkitAdapter.ADAPTER.getLegacyBlockId((Material) restrictTarget);
if (legacyId > 0) {
includeListMaterial.append(",").append(legacyId);
}
targetName = ((Material) restrictTarget).name().toLowerCase(Locale.ROOT);
item = (!item ? !(((Material) restrictTarget).isBlock()) : item);
hasBlock = true;
}
else if (restrictTarget instanceof EntityType) {
targetName = ((EntityType) restrictTarget).name();
if (includeListEntity.length() == 0) {
includeListEntity = includeListEntity.append(Util.getEntityId(targetName, false));
}
else {
includeListEntity.append(",").append(Util.getEntityId(targetName, false));
}
targetName = ((EntityType) restrictTarget).name().toLowerCase(Locale.ROOT);
entity = true;
}
if (restrictCount == 0) {
restrict = restrict.append("" + targetName + "");
}
else {
restrict.append(", ").append(targetName);
}
restrictCount++;
}
includeBlock = includeListMaterial.toString();
includeEntity = includeListEntity.toString();
} }
else if (endTime < 86400) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.PURGE_MINIMUM_TIME, "24", Selector.SECOND)); // 24 hours if (entity) {
Chat.sendMessage(player, Color.DARK_AQUA + "CoreProtect " + Color.WHITE + "- " + Phrase.build(Phrase.ACTION_NOT_SUPPORTED));
return; return;
} }
@ -90,7 +168,12 @@ public class PurgeCommand extends Consumer {
break; break;
} }
} }
final StringBuilder restrictTargets = restrict;
final String includeBlockFinal = includeBlock;
final boolean optimize = optimizeCheck; final boolean optimize = optimizeCheck;
final boolean hasBlockRestriction = hasBlock;
final int restrictCountFinal = restrictCount;
class BasicThread implements Runnable { class BasicThread implements Runnable {
@ -123,6 +206,11 @@ public class PurgeCommand extends Consumer {
else { else {
Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_STARTED, "#global")); Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_STARTED, "#global"));
} }
if (hasBlockRestriction) {
Chat.sendGlobalMessage(player, Phrase.build(Phrase.ROLLBACK_INCLUDE, restrictTargets.toString(), Selector.FIRST, Selector.FIRST, (restrictCountFinal == 1 ? Selector.FIRST : Selector.SECOND))); // include
}
Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_NOTICE_1)); Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_NOTICE_1));
Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_NOTICE_2)); Chat.sendGlobalMessage(player, Phrase.build(Phrase.PURGE_NOTICE_2));
@ -172,6 +260,7 @@ public class PurgeCommand extends Consumer {
List<String> purgeTables = Arrays.asList("sign", "container", "item", "skull", "session", "chat", "command", "entity", "block"); 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> 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 List<String> excludeTables = Arrays.asList("database_lock"); // don't insert data into these tables
for (String table : ConfigHandler.databaseTables) { for (String table : ConfigHandler.databaseTables) {
String tableName = table.replaceAll("_", " "); String tableName = table.replaceAll("_", " ");
@ -198,11 +287,16 @@ public class PurgeCommand extends Consumer {
try { try {
String timeLimit = ""; String timeLimit = "";
if (purgeTables.contains(table)) { if (purgeTables.contains(table)) {
String blockRestriction = "";
if (hasBlockRestriction && restrictTables.contains(table)) {
blockRestriction = "type IN(" + includeBlockFinal + ") AND ";
}
if (argWid > 0 && worldTables.contains(table)) { if (argWid > 0 && worldTables.contains(table)) {
timeLimit = " WHERE (wid = '" + argWid + "' AND (time >= '" + timeEnd + "' OR time < '" + timeStart + "')) OR wid != '" + argWid + "'"; timeLimit = " WHERE (" + blockRestriction + "wid = '" + argWid + "' AND (time >= '" + timeEnd + "' OR time < '" + timeStart + "')) OR (" + blockRestriction + "wid != '" + argWid + "')";
} }
else if (argWid == 0) { else if (argWid == 0) {
timeLimit = " WHERE (time >= '" + timeEnd + "' OR time < '" + timeStart + "')"; timeLimit = " WHERE " + blockRestriction + "(time >= '" + timeEnd + "' OR time < '" + timeStart + "')";
} }
} }
query = "INSERT INTO " + purgePrefix + table + " SELECT " + columns + " FROM " + ConfigHandler.prefix + table + timeLimit; query = "INSERT INTO " + purgePrefix + table + " SELECT " + columns + " FROM " + ConfigHandler.prefix + table + timeLimit;
@ -256,6 +350,14 @@ public class PurgeCommand extends Consumer {
try { try {
boolean purge = purgeTables.contains(table); boolean purge = purgeTables.contains(table);
String blockRestriction = "";
if (hasBlockRestriction && restrictTables.contains(table)) {
blockRestriction = "type IN(" + includeBlockFinal + ") AND ";
}
else if (hasBlockRestriction) {
purge = false;
}
String worldRestriction = ""; String worldRestriction = "";
if (argWid > 0 && worldTables.contains(table)) { if (argWid > 0 && worldTables.contains(table)) {
worldRestriction = " AND wid = '" + argWid + "'"; worldRestriction = " AND wid = '" + argWid + "'";
@ -265,7 +367,7 @@ public class PurgeCommand extends Consumer {
} }
if (purge) { if (purge) {
query = "DELETE FROM " + purgePrefix + table + " WHERE time < '" + timeEnd + "' AND time >= '" + timeStart + "'" + worldRestriction; query = "DELETE FROM " + purgePrefix + table + " WHERE " + blockRestriction + "time < '" + timeEnd + "' AND time >= '" + timeStart + "'" + worldRestriction;
preparedStmt = connection.prepareStatement(query); preparedStmt = connection.prepareStatement(query);
preparedStmt.execute(); preparedStmt.execute();
preparedStmt.close(); preparedStmt.close();
@ -315,6 +417,14 @@ public class PurgeCommand extends Consumer {
try { try {
boolean purge = purgeTables.contains(table); boolean purge = purgeTables.contains(table);
String blockRestriction = "";
if (hasBlockRestriction && restrictTables.contains(table)) {
blockRestriction = "type IN(" + includeBlockFinal + ") AND ";
}
else if (hasBlockRestriction) {
purge = false;
}
String worldRestriction = ""; String worldRestriction = "";
if (argWid > 0 && worldTables.contains(table)) { if (argWid > 0 && worldTables.contains(table)) {
worldRestriction = " AND wid = '" + argWid + "'"; worldRestriction = " AND wid = '" + argWid + "'";
@ -324,7 +434,7 @@ public class PurgeCommand extends Consumer {
} }
if (purge) { if (purge) {
query = "DELETE FROM " + ConfigHandler.prefix + table + " WHERE time < '" + timeEnd + "' AND time >= '" + timeStart + "'" + worldRestriction; query = "DELETE FROM " + ConfigHandler.prefix + table + " WHERE " + blockRestriction + "time < '" + timeEnd + "' AND time >= '" + timeStart + "'" + worldRestriction;
preparedStmt = connection.prepareStatement(query); preparedStmt = connection.prepareStatement(query);
preparedStmt.execute(); preparedStmt.execute();
removed = removed + preparedStmt.getUpdateCount(); removed = removed + preparedStmt.getUpdateCount();