348 lines
17 KiB
Java
348 lines
17 KiB
Java
/*
|
|
* PlotSquared, a land and world management plugin for Minecraft.
|
|
* Copyright (C) IntellectualSites <https://intellectualsites.com>
|
|
* Copyright (C) IntellectualSites team and contributors
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
package com.plotsquared.core.command;
|
|
|
|
import com.google.inject.Inject;
|
|
import com.plotsquared.core.backup.BackupManager;
|
|
import com.plotsquared.core.backup.BackupProfile;
|
|
import com.plotsquared.core.backup.NullBackupProfile;
|
|
import com.plotsquared.core.backup.PlayerBackupProfile;
|
|
import com.plotsquared.core.configuration.caption.TranslatableCaption;
|
|
import com.plotsquared.core.permissions.Permission;
|
|
import com.plotsquared.core.player.PlotPlayer;
|
|
import com.plotsquared.core.plot.Plot;
|
|
import com.plotsquared.core.util.task.RunnableVal2;
|
|
import com.plotsquared.core.util.task.RunnableVal3;
|
|
import net.kyori.adventure.text.minimessage.Template;
|
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
|
|
|
import java.nio.file.Files;
|
|
import java.time.Instant;
|
|
import java.time.ZoneId;
|
|
import java.time.ZonedDateTime;
|
|
import java.time.format.DateTimeFormatter;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Objects;
|
|
import java.util.concurrent.CompletableFuture;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.IntStream;
|
|
import java.util.stream.Stream;
|
|
|
|
@CommandDeclaration(command = "backup",
|
|
usage = "/plot backup <save | list | load>",
|
|
category = CommandCategory.SETTINGS,
|
|
requiredType = RequiredType.PLAYER,
|
|
permission = "plots.backup")
|
|
public final class Backup extends Command {
|
|
|
|
private final BackupManager backupManager;
|
|
|
|
@Inject
|
|
public Backup(final @NonNull BackupManager backupManager) {
|
|
super(MainCommand.getInstance(), true);
|
|
this.backupManager = backupManager;
|
|
}
|
|
|
|
private static boolean sendMessage(PlotPlayer<?> player) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "/plot backup <save | list | load>")
|
|
);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public CompletableFuture<Boolean> execute(
|
|
PlotPlayer<?> player, String[] args,
|
|
RunnableVal3<Command, Runnable, Runnable> confirm,
|
|
RunnableVal2<Command, CommandResult> whenDone
|
|
) throws CommandException {
|
|
if (args.length == 0 || !Arrays.asList("save", "list", "load")
|
|
.contains(args[0].toLowerCase(Locale.ENGLISH))) {
|
|
return CompletableFuture.completedFuture(sendMessage(player));
|
|
}
|
|
return super.execute(player, args, confirm, whenDone);
|
|
}
|
|
|
|
@Override
|
|
public Collection<Command> tab(PlotPlayer<?> player, String[] args, boolean space) {
|
|
if (args.length == 1) {
|
|
return Stream.of("save", "list", "load")
|
|
.filter(value -> value.startsWith(args[0].toLowerCase(Locale.ENGLISH)))
|
|
.map(value -> new Command(null, false, value, "", RequiredType.NONE, null) {
|
|
}).collect(Collectors.toList());
|
|
} else if (args[0].equalsIgnoreCase("load")) {
|
|
|
|
final Plot plot = player.getCurrentPlot();
|
|
if (plot != null) {
|
|
final BackupProfile backupProfile = Objects.requireNonNull(this.backupManager.getProfile(plot));
|
|
if (backupProfile instanceof PlayerBackupProfile) {
|
|
final CompletableFuture<List<com.plotsquared.core.backup.Backup>> backupList =
|
|
backupProfile.listBackups();
|
|
if (backupList.isDone()) {
|
|
final List<com.plotsquared.core.backup.Backup> backups =
|
|
backupList.getNow(new ArrayList<>());
|
|
if (backups.isEmpty()) {
|
|
return new ArrayList<>();
|
|
}
|
|
return IntStream.range(1, 1 + backups.size()).mapToObj(
|
|
i -> new Command(null, false, Integer.toString(i), "",
|
|
RequiredType.NONE, null
|
|
) {
|
|
}).collect(Collectors.toList());
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return tabOf(player, args, space);
|
|
}
|
|
|
|
@CommandDeclaration(command = "save",
|
|
usage = "/plot backup save",
|
|
category = CommandCategory.SETTINGS,
|
|
requiredType = RequiredType.PLAYER,
|
|
permission = "plots.backup.save")
|
|
public void save(
|
|
final Command command, final PlotPlayer<?> player, final String[] args,
|
|
final RunnableVal3<Command, Runnable, Runnable> confirm,
|
|
final RunnableVal2<Command, CommandResult> whenDone
|
|
) {
|
|
final Plot plot = player.getCurrentPlot();
|
|
if (plot == null) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
|
|
} else if (!plot.hasOwner()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_unowned").getComponent(player))
|
|
);
|
|
} else if (plot.getVolume() > Integer.MAX_VALUE) {
|
|
player.sendMessage(TranslatableCaption.of("schematics.schematic_too_large"));
|
|
} else if (plot.isMerged()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_merged").getComponent(player))
|
|
);
|
|
} else if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN_BACKUP_OTHER)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_BACKUP_OTHER))
|
|
);
|
|
} else {
|
|
final BackupProfile backupProfile = Objects.requireNonNull(this.backupManager.getProfile(plot));
|
|
if (backupProfile instanceof NullBackupProfile) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_other").getComponent(player))
|
|
);
|
|
} else {
|
|
backupProfile.createBackup().whenComplete((backup, throwable) -> {
|
|
if (throwable != null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_save_failed"),
|
|
Template.of("reason", throwable.getMessage())
|
|
);
|
|
throwable.printStackTrace();
|
|
} else {
|
|
player.sendMessage(TranslatableCaption.of("backups.backup_save_success"));
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@CommandDeclaration(command = "list",
|
|
usage = "/plot backup list",
|
|
category = CommandCategory.SETTINGS,
|
|
requiredType = RequiredType.PLAYER,
|
|
permission = "plots.backup.list")
|
|
public void list(
|
|
final Command command, final PlotPlayer<?> player, final String[] args,
|
|
final RunnableVal3<Command, Runnable, Runnable> confirm,
|
|
final RunnableVal2<Command, CommandResult> whenDone
|
|
) {
|
|
final Plot plot = player.getCurrentPlot();
|
|
if (plot == null) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
|
|
} else if (!plot.hasOwner()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_unowned").getComponent(player))
|
|
);
|
|
} else if (plot.isMerged()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_merged").getComponent(player))
|
|
);
|
|
} else if (plot.getVolume() > Integer.MAX_VALUE) {
|
|
player.sendMessage(TranslatableCaption.of("schematics.schematic_too_large"));
|
|
} else if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN_BACKUP_OTHER)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_BACKUP_OTHER))
|
|
);
|
|
} else {
|
|
final BackupProfile backupProfile = Objects.requireNonNull(this.backupManager.getProfile(plot));
|
|
if (backupProfile instanceof NullBackupProfile) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_other").getComponent(player))
|
|
);
|
|
} else {
|
|
backupProfile.listBackups().whenComplete((backups, throwable) -> {
|
|
if (throwable != null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_list_failed"),
|
|
Template.of("reason", throwable.getMessage())
|
|
);
|
|
throwable.printStackTrace();
|
|
} else {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_list_header"),
|
|
Template.of("plot", plot.getId().toCommaSeparatedString())
|
|
);
|
|
try {
|
|
for (int i = 0; i < backups.size(); i++) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_list_entry"),
|
|
Template.of("number", Integer.toString(i + 1)),
|
|
Template.of("value", DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.ofInstant(
|
|
Instant.ofEpochMilli(backups.get(i).getCreationTime()),
|
|
ZoneId.systemDefault()
|
|
)))
|
|
);
|
|
}
|
|
} catch (final Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
@CommandDeclaration(command = "load",
|
|
usage = "/plot backup load <#>",
|
|
category = CommandCategory.SETTINGS,
|
|
requiredType = RequiredType.PLAYER,
|
|
permission = "plots.backup.load")
|
|
public void load(
|
|
final Command command, final PlotPlayer<?> player, final String[] args,
|
|
final RunnableVal3<Command, Runnable, Runnable> confirm,
|
|
final RunnableVal2<Command, CommandResult> whenDone
|
|
) {
|
|
final Plot plot = player.getCurrentPlot();
|
|
if (plot == null) {
|
|
player.sendMessage(TranslatableCaption.of("errors.not_in_plot"));
|
|
} else if (!plot.hasOwner()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_unowned").getComponent(player))
|
|
);
|
|
} else if (plot.isMerged()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_merged").getComponent(player))
|
|
);
|
|
} else if (plot.getVolume() > Integer.MAX_VALUE) {
|
|
player.sendMessage(TranslatableCaption.of("schematics.schematic_too_large"));
|
|
} else if (!plot.isOwner(player.getUUID()) && !player.hasPermission(Permission.PERMISSION_ADMIN_BACKUP_OTHER)) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("permission.no_permission"),
|
|
Template.of("node", String.valueOf(Permission.PERMISSION_ADMIN_BACKUP_OTHER))
|
|
);
|
|
} else if (args.length == 0) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("commandconfig.command_syntax"),
|
|
Template.of("value", "Usage: /plot backup save/list/load")
|
|
);
|
|
} else {
|
|
final int number;
|
|
try {
|
|
number = Integer.parseInt(args[0]);
|
|
} catch (final Exception e) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("invalid.not_a_number"),
|
|
Template.of("value", args[0])
|
|
);
|
|
return;
|
|
}
|
|
final BackupProfile backupProfile = Objects.requireNonNull(this.backupManager.getProfile(plot));
|
|
if (backupProfile instanceof NullBackupProfile) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of("plot", TranslatableCaption.of("generic.generic_other").getComponent(player))
|
|
);
|
|
} else {
|
|
backupProfile.listBackups().whenComplete((backups, throwable) -> {
|
|
if (throwable != null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_load_failure"),
|
|
Template.of("reason", throwable.getMessage())
|
|
);
|
|
throwable.printStackTrace();
|
|
} else {
|
|
if (number < 1 || number > backups.size()) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of(
|
|
"plot",
|
|
TranslatableCaption.of("generic.generic_invalid_choice").getComponent(player)
|
|
)
|
|
);
|
|
} else {
|
|
final com.plotsquared.core.backup.Backup backup =
|
|
backups.get(number - 1);
|
|
if (backup == null || backup.getFile() == null || !Files
|
|
.exists(backup.getFile())) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_impossible"),
|
|
Template.of(
|
|
"plot",
|
|
TranslatableCaption.of("generic.generic_invalid_choice").getComponent(player)
|
|
)
|
|
);
|
|
} else {
|
|
CmdConfirm.addPending(player, "/plot backup load " + number,
|
|
() -> backupProfile.restoreBackup(backup, player)
|
|
.whenComplete((n, error) -> {
|
|
if (error != null) {
|
|
player.sendMessage(
|
|
TranslatableCaption.of("backups.backup_load_failure"),
|
|
Template.of("reason", error.getMessage())
|
|
);
|
|
} else {
|
|
player.sendMessage(TranslatableCaption.of("backups.backup_load_success"));
|
|
}
|
|
})
|
|
);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|