/* * PlotSquared, a land and world management plugin for Minecraft. * Copyright (C) IntellectualSites * 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 . */ 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.Permissions; 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 ", 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 ") ); return true; } @Override public CompletableFuture execute( PlotPlayer player, String[] args, RunnableVal3 confirm, RunnableVal2 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 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> backupList = backupProfile.listBackups(); if (backupList.isDone()) { final List 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 confirm, final RunnableVal2 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()) && !Permissions .hasPermission(player, 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 confirm, final RunnableVal2 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()) && !Permissions .hasPermission(player, 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 confirm, final RunnableVal2 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()) && !Permissions .hasPermission(player, 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")); } }) ); } } } }); } } } }