Basic world backup command.

This commit is contained in:
Logan Gorence 2021-12-20 18:01:54 +00:00
parent f36f996315
commit 42f5f33149
No known key found for this signature in database
GPG Key ID: 9743CEF10935949A
4 changed files with 146 additions and 2 deletions

View File

@ -1,18 +1,38 @@
package cloud.kubelet.foundation;
import cloud.kubelet.foundation.command.BackupCommand;
import io.papermc.paper.event.player.ChatEvent;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import net.kyori.adventure.text.Component;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
public final class Foundation extends JavaPlugin implements Listener {
public static final boolean BACKUP_ENABLED = true;
private static final String BACKUPS_DIRECTORY = "backups";
@Override
public void onEnable() {
Path dataPath = getDataFolder().toPath();
Path backupPath = dataPath.resolve(BACKUPS_DIRECTORY);
// Create Foundation plugin directories.
dataPath.toFile().mkdir();
backupPath.toFile().mkdir();
// Register this as an event listener.
getServer().getPluginManager().registerEvents(this, this);
getDataFolder().mkdir();
// Set up commands.
Objects.requireNonNull(getCommand("fbackup")).setExecutor(new BackupCommand(backupPath));
final var log = getSLF4JLogger();
log.info("Features:");
Util.printFeatureStatus(log, "Backup: ", BACKUP_ENABLED);
}
@Override

View File

@ -0,0 +1,15 @@
package cloud.kubelet.foundation;
import java.io.IOException;
import java.util.List;
import org.slf4j.Logger;
public class Util {
public static int runProcess(List<String> command) throws IOException, InterruptedException {
return new ProcessBuilder(command).start().waitFor();
}
public static void printFeatureStatus(Logger logger, String feature, boolean state) {
logger.info("{}: {}", feature, state ? "Enabled" : "Disabled");
}
}

View File

@ -0,0 +1,105 @@
package cloud.kubelet.foundation.command;
import cloud.kubelet.foundation.Foundation;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextColor;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
public class BackupCommand implements CommandExecutor {
private static final AtomicBoolean RUNNING = new AtomicBoolean();
private final Path backupPath;
public BackupCommand(Path backupPath) {
this.backupPath = backupPath;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args) {
if (!Foundation.BACKUP_ENABLED) {
sender.sendMessage(
Component
.text("Backup is not enabled.")
.color(TextColor.fromHexString("#FF0000"))
);
return true;
}
if (RUNNING.get()) {
sender.sendMessage(
Component
.text("Backup is already running.")
.color(TextColor.fromHexString("#FF0000"))
);
} else {
try {
runBackup(sender);
} catch (Exception e) {
sender.sendMessage(String.format("Failed to backup: %s", e.getMessage()));
}
}
return true;
}
private void runBackup(CommandSender sender) throws IOException {
RUNNING.set(true);
final var backupFile = backupPath.resolve(
String.format("backup-%s.zip", Instant.now().toString())).toFile();
final var zipFileStream = new FileOutputStream(backupFile);
try (zipFileStream; var zipStream = new ZipOutputStream(
new BufferedOutputStream(zipFileStream))) {
final var worlds = sender.getServer().getWorlds();
for (World world : worlds) {
final var name = world.getName();
final var worldPath = world.getWorldFolder().toPath().toString();
sender.sendMessage(String.format("%s: %s", name, worldPath));
world.save();
world.setAutoSave(false);
try {
final var paths = Files.walk(Paths.get(worldPath))
.filter(Files::isRegularFile)
.toList();
for (Path path : paths) {
try (InputStream fileStream = new FileInputStream(path.toFile())) {
final var entry = new ZipEntry(path.toString());
zipStream.putNextEntry(entry);
int n;
byte[] buffer = new byte[1024];
while ((n = fileStream.read(buffer)) > -1) {
zipStream.write(buffer, 0, n);
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
world.setAutoSave(true);
}
} finally {
RUNNING.set(false);
}
}
}

View File

@ -6,4 +6,8 @@ prefix: Foundation
load: STARTUP
authors:
- kubelet
commands: {}
commands:
fbackup:
description: Foundation Backup
usage: /fbackup
permission: foundation.backup