mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 05:30:55 +00:00
Basic world backup command.
This commit is contained in:
parent
f36f996315
commit
42f5f33149
@ -1,18 +1,38 @@
|
|||||||
package cloud.kubelet.foundation;
|
package cloud.kubelet.foundation;
|
||||||
|
|
||||||
|
import cloud.kubelet.foundation.command.BackupCommand;
|
||||||
import io.papermc.paper.event.player.ChatEvent;
|
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 net.kyori.adventure.text.Component;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
public final class Foundation extends JavaPlugin implements Listener {
|
public final class Foundation extends JavaPlugin implements Listener {
|
||||||
|
public static final boolean BACKUP_ENABLED = true;
|
||||||
|
private static final String BACKUPS_DIRECTORY = "backups";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
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);
|
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
|
@Override
|
||||||
|
15
src/main/java/cloud/kubelet/foundation/Util.java
Normal file
15
src/main/java/cloud/kubelet/foundation/Util.java
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,4 +6,8 @@ prefix: Foundation
|
|||||||
load: STARTUP
|
load: STARTUP
|
||||||
authors:
|
authors:
|
||||||
- kubelet
|
- kubelet
|
||||||
commands: {}
|
commands:
|
||||||
|
fbackup:
|
||||||
|
description: Foundation Backup
|
||||||
|
usage: /fbackup
|
||||||
|
permission: foundation.backup
|
||||||
|
Loading…
Reference in New Issue
Block a user