Added BackupContext. This object gets passed instead of passing ServerCommandSource, MinecraftServer, etc... separately.
parent
51ecf54fb6
commit
fec162ae24
|
@ -24,23 +24,28 @@ import com.mojang.brigadier.context.CommandContext;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.szum123321.textile_backup.TextileBackup;
|
import net.szum123321.textile_backup.TextileBackup;
|
||||||
|
import net.szum123321.textile_backup.core.BackupContext;
|
||||||
import net.szum123321.textile_backup.core.BackupHelper;
|
import net.szum123321.textile_backup.core.BackupHelper;
|
||||||
|
|
||||||
public class StartBackupCommand {
|
public class StartBackupCommand {
|
||||||
public static LiteralArgumentBuilder<ServerCommandSource> register(){
|
public static LiteralArgumentBuilder<ServerCommandSource> register() {
|
||||||
return CommandManager.literal("start")
|
return CommandManager.literal("start")
|
||||||
.then(CommandManager.argument("comment", StringArgumentType.string())
|
.then(CommandManager.argument("comment", StringArgumentType.string())
|
||||||
.executes(StartBackupCommand::executeWithComment)
|
.executes(StartBackupCommand::executeWithComment)
|
||||||
).executes(ctx -> execute(ctx.getSource()));
|
).executes(ctx -> execute(ctx.getSource()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int executeWithComment(CommandContext<ServerCommandSource> source) {
|
private static int executeWithComment(CommandContext<ServerCommandSource> ctx) {
|
||||||
|
if(!TextileBackup.executorService.isShutdown())
|
||||||
TextileBackup.executorService.submit(
|
TextileBackup.executorService.submit(
|
||||||
BackupHelper.create(
|
BackupHelper.create(
|
||||||
source.getSource().getMinecraftServer(),
|
new BackupContext.Builder()
|
||||||
source.getSource(),
|
.setCommandSource(ctx.getSource())
|
||||||
true,
|
.setServer(ctx.getSource().getMinecraftServer())
|
||||||
StringArgumentType.getString(source, "comment").replace("#", "")
|
.setComment(StringArgumentType.getString(ctx, "comment"))
|
||||||
|
.guessInitiator()
|
||||||
|
.setSave()
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -48,12 +53,15 @@ public class StartBackupCommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int execute(ServerCommandSource source){
|
private static int execute(ServerCommandSource source){
|
||||||
|
if(!TextileBackup.executorService.isShutdown())
|
||||||
TextileBackup.executorService.submit(
|
TextileBackup.executorService.submit(
|
||||||
BackupHelper.create(
|
BackupHelper.create(
|
||||||
source.getMinecraftServer(),
|
new BackupContext.Builder()
|
||||||
source,
|
.setCommandSource(source)
|
||||||
true,
|
.setServer(source.getMinecraftServer())
|
||||||
null
|
.guessInitiator()
|
||||||
|
.setSave()
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
package net.szum123321.textile_backup.core;
|
||||||
|
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class BackupContext {
|
||||||
|
private final MinecraftServer server;
|
||||||
|
private final ServerCommandSource commandSource;
|
||||||
|
private final BackupInitiator initiator;
|
||||||
|
private final boolean save;
|
||||||
|
private final String comment;
|
||||||
|
|
||||||
|
protected BackupContext(@NotNull MinecraftServer server, ServerCommandSource commandSource, @NotNull BackupInitiator initiator, boolean save, String comment) {
|
||||||
|
this.server = server;
|
||||||
|
this.commandSource = commandSource;
|
||||||
|
this.initiator = initiator;
|
||||||
|
this.save = save;
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MinecraftServer getServer() {
|
||||||
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ServerCommandSource getCommandSource() {
|
||||||
|
return commandSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupInitiator getInitiator() {
|
||||||
|
return initiator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean startedByPlayer() {
|
||||||
|
return initiator == BackupInitiator.Player;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean shouldSave() {
|
||||||
|
return save;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private MinecraftServer server;
|
||||||
|
private ServerCommandSource commandSource;
|
||||||
|
private BackupInitiator initiator;
|
||||||
|
private boolean save;
|
||||||
|
private String comment;
|
||||||
|
|
||||||
|
private boolean guessInitiator;
|
||||||
|
|
||||||
|
public Builder() {
|
||||||
|
this.server = null;
|
||||||
|
this.commandSource = null;
|
||||||
|
this.initiator = null;
|
||||||
|
this.save = false;
|
||||||
|
this.comment = null;
|
||||||
|
|
||||||
|
guessInitiator = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setCommandSource(ServerCommandSource commandSource) {
|
||||||
|
this.commandSource = commandSource;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setServer(MinecraftServer server) {
|
||||||
|
this.server = server;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setInitiator(BackupInitiator initiator) {
|
||||||
|
this.initiator = initiator;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder guessInitiator() {
|
||||||
|
this.guessInitiator = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setSave() {
|
||||||
|
this.save = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BackupContext build() {
|
||||||
|
if(guessInitiator) {
|
||||||
|
initiator = commandSource.getEntity() == null ? BackupInitiator.ServerConsole : BackupInitiator.Player;
|
||||||
|
} else if(initiator == null) {
|
||||||
|
initiator = BackupInitiator.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(server == null)
|
||||||
|
setServer(commandSource.getMinecraftServer());
|
||||||
|
|
||||||
|
return new BackupContext(server, commandSource, initiator, save, comment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum BackupInitiator {
|
||||||
|
Player ("Player", "by: "),
|
||||||
|
ServerConsole ("Server Console", "from: "),
|
||||||
|
Timer ("Timer", "by: "),
|
||||||
|
Shutdown ("Server Shutdown", "by: "),
|
||||||
|
Null ("Null (That shouldn't have happened)", "form: ");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String prefix;
|
||||||
|
|
||||||
|
BackupInitiator(String name, String prefix) {
|
||||||
|
this.name = name;
|
||||||
|
this.prefix = prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPrefix() {
|
||||||
|
return prefix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,6 @@
|
||||||
package net.szum123321.textile_backup.core;
|
package net.szum123321.textile_backup.core;
|
||||||
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.server.MinecraftServer;
|
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.szum123321.textile_backup.TextileBackup;
|
import net.szum123321.textile_backup.TextileBackup;
|
||||||
import org.apache.commons.io.FileUtils;
|
import org.apache.commons.io.FileUtils;
|
||||||
|
@ -32,28 +31,30 @@ import java.util.Comparator;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class BackupHelper {
|
public class BackupHelper {
|
||||||
public static Runnable create(MinecraftServer server, ServerCommandSource ctx, boolean save, String comment) {
|
public static Runnable create(BackupContext ctx) {
|
||||||
LocalDateTime now = LocalDateTime.now();
|
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("Backup started by: ");
|
|
||||||
|
|
||||||
if (ctx != null)
|
builder.append("Backup started ");
|
||||||
builder.append(ctx.getName());
|
|
||||||
else
|
builder.append(ctx.getInitiator().getPrefix());
|
||||||
builder.append("SERVER");
|
|
||||||
|
if(ctx.startedByPlayer()) {
|
||||||
|
builder.append(ctx.getCommandSource().getDisplayName().getString());
|
||||||
|
} else {
|
||||||
|
builder.append(ctx.getInitiator().getName());
|
||||||
|
}
|
||||||
|
|
||||||
builder.append(" on: ");
|
builder.append(" on: ");
|
||||||
builder.append(Utilities.getDateTimeFormatter().format(now));
|
builder.append(Utilities.getDateTimeFormatter().format(LocalDateTime.now()));
|
||||||
|
|
||||||
Utilities.info(builder.toString(), null);
|
Utilities.info(builder.toString(), null);
|
||||||
|
|
||||||
Utilities.info("Saving server...", ctx);
|
if (ctx.shouldSave()) {
|
||||||
|
Utilities.info("Saving server...", ctx.getCommandSource());
|
||||||
|
ctx.getServer().save(true, true, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (save)
|
return new MakeBackupRunnable(ctx);
|
||||||
server.save(true, true, false);
|
|
||||||
|
|
||||||
return new MakeBackupRunnable(server, ctx, comment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeFileLimit(ServerCommandSource ctx, String worldName) {
|
public static void executeFileLimit(ServerCommandSource ctx, String worldName) {
|
||||||
|
@ -92,12 +93,13 @@ public class BackupHelper {
|
||||||
} else {
|
} else {
|
||||||
Utilities.sendError("Something went wrong while deleting: " + f.getName(), ctx);
|
Utilities.sendError("Something went wrong while deleting: " + f.getName(), ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextileBackup.config.maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > TextileBackup.config.maxSize) {
|
if (TextileBackup.config.maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > TextileBackup.config.maxSize) {
|
||||||
Iterator<File> it =Arrays.stream(root.listFiles())
|
Iterator<File> it = Arrays.stream(root.listFiles())
|
||||||
.filter(BackupHelper::isFileOk)
|
.filter(BackupHelper::isFileOk)
|
||||||
.filter(f -> Utilities.getFileCreationTime(f).isPresent())
|
.filter(f -> Utilities.getFileCreationTime(f).isPresent())
|
||||||
.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime(f).get()))
|
.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime(f).get()))
|
||||||
|
|
|
@ -20,7 +20,15 @@ public class BackupScheduler {
|
||||||
if(TextileBackup.config.doBackupsOnEmptyServer || server.getPlayerManager().getCurrentPlayerCount() > 0) {
|
if(TextileBackup.config.doBackupsOnEmptyServer || server.getPlayerManager().getCurrentPlayerCount() > 0) {
|
||||||
if(scheduled) {
|
if(scheduled) {
|
||||||
if(nextBackup <= now) {
|
if(nextBackup <= now) {
|
||||||
TextileBackup.executorService.submit(BackupHelper.create(server, null, true, null));
|
TextileBackup.executorService.submit(
|
||||||
|
BackupHelper.create(
|
||||||
|
new BackupContext.Builder()
|
||||||
|
.setServer(server)
|
||||||
|
.setInitiator(BackupContext.BackupInitiator.Timer)
|
||||||
|
.setSave()
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
nextBackup = now + TextileBackup.config.backupInterval;
|
nextBackup = now + TextileBackup.config.backupInterval;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +38,15 @@ public class BackupScheduler {
|
||||||
}
|
}
|
||||||
} else if(!TextileBackup.config.doBackupsOnEmptyServer && server.getPlayerManager().getCurrentPlayerCount() == 0) {
|
} else if(!TextileBackup.config.doBackupsOnEmptyServer && server.getPlayerManager().getCurrentPlayerCount() == 0) {
|
||||||
if(scheduled && nextBackup <= now) {
|
if(scheduled && nextBackup <= now) {
|
||||||
TextileBackup.executorService.submit(BackupHelper.create(server, null, true, null));
|
TextileBackup.executorService.submit(
|
||||||
|
BackupHelper.create(
|
||||||
|
new BackupContext.Builder()
|
||||||
|
.setServer(server)
|
||||||
|
.setInitiator(BackupContext.BackupInitiator.Timer)
|
||||||
|
.setSave()
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
scheduled = false;
|
scheduled = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,18 +36,18 @@ import java.time.LocalDateTime;
|
||||||
|
|
||||||
public class MakeBackupRunnable implements Runnable {
|
public class MakeBackupRunnable implements Runnable {
|
||||||
private final MinecraftServer server;
|
private final MinecraftServer server;
|
||||||
private final ServerCommandSource ctx;
|
private final ServerCommandSource commandSource;
|
||||||
private final String comment;
|
private final String comment;
|
||||||
|
|
||||||
public MakeBackupRunnable(MinecraftServer server, ServerCommandSource ctx, String comment){
|
public MakeBackupRunnable(BackupContext context){
|
||||||
this.server = server;
|
this.server = context.getServer();
|
||||||
this.ctx = ctx;
|
this.commandSource = context.getCommandSource();
|
||||||
this.comment = comment;
|
this.comment = context.getComment();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Utilities.info("Starting backup", ctx);
|
Utilities.info("Starting backup", commandSource);
|
||||||
|
|
||||||
File world = ((MinecraftServerSessionAccessor)server)
|
File world = ((MinecraftServerSessionAccessor)server)
|
||||||
.getSession()
|
.getSession()
|
||||||
|
@ -70,7 +70,7 @@ public class MakeBackupRunnable implements Runnable {
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
TextileBackup.LOGGER.error("An exception occurred when trying to create new backup file!", e);
|
TextileBackup.LOGGER.error("An exception occurred when trying to create new backup file!", e);
|
||||||
|
|
||||||
Utilities.sendError("An exception occurred when trying to create new backup file!", ctx);
|
Utilities.sendError("An exception occurred when trying to create new backup file!", commandSource);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -83,36 +83,36 @@ public class MakeBackupRunnable implements Runnable {
|
||||||
coreCount = Math.min(TextileBackup.config.compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
|
coreCount = Math.min(TextileBackup.config.compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
|
||||||
}
|
}
|
||||||
|
|
||||||
TextileBackup.LOGGER.trace("Running compression on {} threads", coreCount);
|
TextileBackup.LOGGER.trace("Running compression on {} threads. Available cores = {}", coreCount, Runtime.getRuntime().availableProcessors());
|
||||||
|
|
||||||
switch (TextileBackup.config.format) {
|
switch (TextileBackup.config.format) {
|
||||||
case ZIP:
|
case ZIP:
|
||||||
ParallelZipCompressor.createArchive(world, outFile, ctx, coreCount);
|
ParallelZipCompressor.createArchive(world, outFile, commandSource, coreCount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BZIP2:
|
case BZIP2:
|
||||||
ParallelBZip2Compressor.createArchive(world, outFile, ctx, coreCount);
|
ParallelBZip2Compressor.createArchive(world, outFile, commandSource, coreCount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GZIP:
|
case GZIP:
|
||||||
ParallelGzipCompressor.createArchive(world, outFile, ctx, coreCount);
|
ParallelGzipCompressor.createArchive(world, outFile, commandSource, coreCount);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LZMA:
|
case LZMA:
|
||||||
LZMACompressor.createArchive(world, outFile, ctx); // Always single-threaded ):
|
LZMACompressor.createArchive(world, outFile, commandSource); // Always single-threaded ):
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
TextileBackup.LOGGER.warn("Specified compressor ({}) is not supported! Zip will be used instead!", TextileBackup.config.format);
|
TextileBackup.LOGGER.warn("Specified compressor ({}) is not supported! Zip will be used instead!", TextileBackup.config.format);
|
||||||
|
Utilities.sendError("Error! No correct compression format specified! Using default compressor!", commandSource);
|
||||||
|
|
||||||
Utilities.sendError("Error! No correct compression format specified! using default compressor!", ctx);
|
ParallelZipCompressor.createArchive(world, outFile, commandSource, coreCount);
|
||||||
ParallelZipCompressor.createArchive(world, outFile, ctx, coreCount);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
BackupHelper.executeFileLimit(ctx, Utilities.getLevelName(server));
|
BackupHelper.executeFileLimit(commandSource, Utilities.getLevelName(server));
|
||||||
|
|
||||||
Utilities.info("Done!", ctx);
|
Utilities.info("Done!", commandSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFileName(){
|
private String getFileName(){
|
||||||
|
|
|
@ -20,6 +20,7 @@ package net.szum123321.textile_backup.mixin;
|
||||||
|
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.server.MinecraftServer;
|
||||||
import net.szum123321.textile_backup.TextileBackup;
|
import net.szum123321.textile_backup.TextileBackup;
|
||||||
|
import net.szum123321.textile_backup.core.BackupContext;
|
||||||
import net.szum123321.textile_backup.core.BackupHelper;
|
import net.szum123321.textile_backup.core.BackupHelper;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
@ -31,6 +32,14 @@ public abstract class MinecraftServerMixin {
|
||||||
@Inject(method = "shutdown", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/server/MinecraftServer;save(ZZZ)Z"))
|
@Inject(method = "shutdown", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/server/MinecraftServer;save(ZZZ)Z"))
|
||||||
public void onFinalWorldSave(CallbackInfo ci) {
|
public void onFinalWorldSave(CallbackInfo ci) {
|
||||||
if (TextileBackup.config.shutdownBackup)
|
if (TextileBackup.config.shutdownBackup)
|
||||||
TextileBackup.executorService.submit(BackupHelper.create((MinecraftServer) (Object) this, null, false, "shutdown"));
|
TextileBackup.executorService.submit(
|
||||||
|
BackupHelper.create(
|
||||||
|
new BackupContext.Builder()
|
||||||
|
.setServer((MinecraftServer)(Object) this)
|
||||||
|
.setInitiator(BackupContext.BackupInitiator.Shutdown)
|
||||||
|
.setComment("shutdown")
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue