diff --git a/build.gradle b/build.gradle
index 42ed2c0..e2418ff 100644
--- a/build.gradle
+++ b/build.gradle
@@ -16,6 +16,13 @@ minecraft {
repositories{
maven { url 'https://server.bbkr.space/artifactory/libs-release' }
maven { url 'https://jitpack.io' }
+ maven { url "https://maven.shedaniel.me/" }
+ maven {
+ url "https://maven.terraformersmc.com/releases/"
+ content {
+ includeGroup "com.terraformersmc"
+ }
+ }
}
dependencies {
@@ -27,20 +34,30 @@ dependencies {
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
- modImplementation "io.github.cottonmc.cotton:cotton-config:1.0.0-rc.7"
+ //General config library
+ modApi("me.shedaniel.cloth:cloth-config-fabric:${project.cloth_version}") {
+ exclude(group: "net.fabricmc.fabric-api")
+ }
- include "io.github.cottonmc:Jankson-Fabric:3.0.0+j1.2.0"
- include "io.github.cottonmc.cotton:cotton-logging:1.0.0-rc.4"
- include "io.github.cottonmc.cotton:cotton-config:1.0.0-rc.7"
+ //Mod menu
+ modImplementation("com.terraformersmc:modmenu:${project.modmenu_version}")
+ //General compression library
modImplementation "org.apache.commons:commons-compress:1.19"
include "org.apache.commons:commons-compress:1.19"
+ //LZMA support
modImplementation "org.tukaani:xz:1.8"
include "org.tukaani:xz:1.8"
+ //Gzip compression, parallel, GITHUB
modImplementation 'com.github.shevek:parallelgzip:master-SNAPSHOT'
include 'com.github.shevek:parallelgzip:master-SNAPSHOT'
+
+ // Lazy DFU makes the dev env start up much faster by loading DataFixerUpper lazily, which would otherwise take a long time. We rarely need it anyway.
+ modRuntime("com.github.astei:lazydfu:${project.lazydfu_version}") {
+ exclude(module: "fabric-loader")
+ }
}
processResources {
diff --git a/gradle.properties b/gradle.properties
index dc60769..0aa132a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -8,6 +8,14 @@ loader_version=0.11.5
#Fabric api
fabric_version=0.35.1+1.17
+#Cloth Config
+cloth_version=5.0.34
+
+#ModMenu
+modmenu_version=2.0.2
+
+lazydfu_version=0.1.2
+
# Mod Properties
mod_version = 2.1.0
maven_group = net.szum123321
diff --git a/src/main/java/net/szum123321/textile_backup/ConfigHandler.java b/src/main/java/net/szum123321/textile_backup/ConfigHandler.java
deleted file mode 100644
index 6ef018d..0000000
--- a/src/main/java/net/szum123321/textile_backup/ConfigHandler.java
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- A simple backup mod for Fabric
- Copyright (C) 2020 Szum123321
-
- 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 net.szum123321.textile_backup;
-
-import blue.endless.jankson.Comment;
-import io.github.cottonmc.cotton.config.annotations.ConfigFile;
-
-import java.io.File;
-import java.time.format.DateTimeFormatter;
-import java.util.*;
-
-@ConfigFile(name = Statics.MOD_ID)
-public class ConfigHandler {
- @Comment("\nTime between automatic backups in seconds\n" +
- "When set to 0 backups will not be performed automatically\n")
- public long backupInterval = 3600;
-
- @Comment("\nDelay in seconds between typing-in /backup restore and it actually starting\n")
- public int restoreDelay = 30;
-
- @Comment("\nShould backups be done even if there are no players?\n")
- public boolean doBackupsOnEmptyServer = false;
-
- @Comment("\nShould backup be made on server shutdown?\n")
- public boolean shutdownBackup = true;
-
- @Comment("\nShould world be backed up before restoring a backup?\n")
- public boolean backupOldWorlds = true;
-
- @Comment("\nShould every world have its own backup folder?\n")
- public boolean perWorldBackup = true;
-
- @Comment("\nA path to the backup folder\n")
- public String path = "backup/";
-
- @Comment("\nThis setting allows you to exclude files form being backedup.\n"+
- "Be very careful when setting it, as it is easy corrupt your world!\n")
- public List fileBlacklist = new ArrayList<>();
-
- @Comment("\nShould backups be deleted after being restored?\n")
- public boolean deleteOldBackupAfterRestore = true;
-
- @Comment("\nMaximum number of backups to keep. If set to 0 then no backup will be deleted based their amount\n")
- public int backupsToKeep = 10;
-
- @Comment("\nMaximum age of backups to keep in seconds.\n If set to 0 then backups will not be deleted based their age \n")
- public long maxAge = 0;
-
- @Comment("\nMaximum size of backup folder in kilo bytes (1024).\n" +
- "If set to 0 then backups will not be deleted\n")
- public int maxSize = 0;
-
- @Comment("\nCompression level \n0 - 9\n Only affects zip compression.\n")
- public int compression = 7;
-
- @Comment("\nLimit how many cores can be used for compression.\n" +
- "0 means that all available cores will be used\n")
- public int compressionCoreCountLimit = 0;
-
- @Comment(value = "\nAvailable formats are:\n" +
- "ZIP - normal zip archive using standard deflate compression\n" +
- "GZIP - tar.gz using gzip compression\n" +
- "BZIP2 - tar.bz2 archive using bzip2 compression\n" +
- "LZMA - tar.xz using lzma compression\n" +
- "TAR - .tar with no compression\n")
- public ArchiveFormat format = ArchiveFormat.ZIP;
-
- @Comment("\nMinimal permission level required to run commands\n")
- public int permissionLevel = 4;
-
- @Comment("\nPlayer on singleplayer is always allowed to run command. Warning! On lan party everyone will be allowed to run it.\n")
- public boolean alwaysSingleplayerAllowed = true;
-
- @Comment("\nPlayers allowed to run backup commands without sufficient permission level\n")
- public Set playerWhitelist = new HashSet<>();
-
- @Comment("\nPlayers banned from running backup commands besides their sufficient permission level\n")
- public Set playerBlacklist = new HashSet<>();
-
- @Comment("\nFormat of date&time used to name backup files.\n" +
- "Remember not to use '#' symbol or any other character that is not allowed by your operating system such as:\n" +
- "':', '\\', etc...\n" +
- "For more info: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html\n")
- public String dateTimeFormat = "yyyy.MM.dd_HH-mm-ss";
-
- public Optional sanitize() {
- if(compressionCoreCountLimit > Runtime.getRuntime().availableProcessors())
- return Optional.of("compressionCoreCountLimit is too big! Your system only has: " + Runtime.getRuntime().availableProcessors() + " cores!");
-
- try {
- DateTimeFormatter.ofPattern(dateTimeFormat);
- } catch (IllegalArgumentException e) {
- return Optional.of("dateTimeFormat is wrong!\n" + e.getMessage() + "\n See: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html");
- }
-
- File path = new File(Statics.CONFIG.path).getAbsoluteFile();
-
- if (!path.exists()) {
- try {
- path.mkdirs();
- } catch (Exception e) {
- return Optional.of("Something went wrong while creating backup folder!\n" + e.getMessage());
- }
- }
-
- return Optional.empty();
- }
-
- public enum ArchiveFormat {
- ZIP("zip"),
- GZIP("tar", "gz"),
- BZIP2("tar", "bz2"),
- LZMA("tar", "xz"),
- TAR("tar");
-
- private final List extensionPieces;
-
- ArchiveFormat(String... extensionParts) {
- extensionPieces = Arrays.asList(extensionParts);
- }
-
- public String getCompleteString() {
- StringBuilder builder = new StringBuilder();
-
- extensionPieces.forEach(s -> builder.append('.').append(s));
-
- return builder.toString();
- }
-
- boolean isMultipart() {
- return extensionPieces.size() > 1;
- }
-
- public String getLastPiece() {
- return extensionPieces.get(extensionPieces.size() - 1);
- }
- }
-}
diff --git a/src/main/java/net/szum123321/textile_backup/Statics.java b/src/main/java/net/szum123321/textile_backup/Statics.java
index 1cfd42a..3cf6d90 100644
--- a/src/main/java/net/szum123321/textile_backup/Statics.java
+++ b/src/main/java/net/szum123321/textile_backup/Statics.java
@@ -18,8 +18,6 @@
package net.szum123321.textile_backup;
-import net.szum123321.textile_backup.core.CustomLogger;
-import net.szum123321.textile_backup.core.create.BackupScheduler;
import net.szum123321.textile_backup.core.restore.AwaitThread;
import java.io.File;
@@ -30,16 +28,10 @@ import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
public class Statics {
- public static final String MOD_ID = "textile_backup";
- public static final String MOD_NAME = "Textile Backup";
- public static final CustomLogger LOGGER = new CustomLogger(MOD_ID, MOD_NAME);
- public static ConfigHandler CONFIG;
-
- public static final BackupScheduler scheduler = new BackupScheduler();
- public static ExecutorService executorService = Executors.newSingleThreadExecutor();
-
public final static DateTimeFormatter defaultDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss");
+ public static ExecutorService executorService = Executors.newSingleThreadExecutor();
+
public static final AtomicBoolean globalShutdownBackupFlag = new AtomicBoolean(true);
public static boolean disableWatchdog = false;
public static AwaitThread restoreAwaitThread = null;
diff --git a/src/main/java/net/szum123321/textile_backup/TextileBackup.java b/src/main/java/net/szum123321/textile_backup/TextileBackup.java
index e2ffd7b..a638dda 100644
--- a/src/main/java/net/szum123321/textile_backup/TextileBackup.java
+++ b/src/main/java/net/szum123321/textile_backup/TextileBackup.java
@@ -19,8 +19,9 @@
package net.szum123321.textile_backup;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
-import io.github.cottonmc.cotton.config.ConfigManager;
+import me.shedaniel.autoconfig.AutoConfig;
+import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
@@ -34,40 +35,41 @@ import net.szum123321.textile_backup.commands.manage.WhitelistCommand;
import net.szum123321.textile_backup.commands.restore.KillRestoreCommand;
import net.szum123321.textile_backup.commands.manage.ListBackupsCommand;
import net.szum123321.textile_backup.commands.restore.RestoreBackupCommand;
+import net.szum123321.textile_backup.config.ConfigHelper;
+import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.BackupHelper;
+import net.szum123321.textile_backup.core.create.BackupScheduler;
-import java.util.Optional;
import java.util.concurrent.Executors;
public class TextileBackup implements ModInitializer {
+ public static final String MOD_NAME = "Textile Backup";
+ public static final String MOD_ID = "textile_backup";
+
+ private final static TextileLogger log = new TextileLogger(MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
@Override
public void onInitialize() {
- Statics.LOGGER.info("Starting Textile Backup by Szum123321.");
+ log.info("Starting Textile Backup by Szum123321");
- Statics.CONFIG = ConfigManager.loadConfig(ConfigHandler.class);
- Optional errorMessage = Statics.CONFIG.sanitize();
-
- if(errorMessage.isPresent()) {
- Statics.LOGGER.fatal("TextileBackup config file has wrong settings!\n{}", errorMessage.get());
- System.exit(1);
- }
+ ConfigHelper.updateInstance(AutoConfig.register(ConfigPOJO.class, JanksonConfigSerializer::new));
//TODO: finish writing wiki
- if(Statics.CONFIG.format == ConfigHandler.ArchiveFormat.ZIP) {
+ if(config.get().format == ConfigPOJO.ArchiveFormat.ZIP) {
Statics.tmpAvailable = Utilities.isTmpAvailable();
if(!Statics.tmpAvailable) {
- Statics.LOGGER.warn("""
+ log.warn("""
WARNING! It seems like the temporary folder is not accessible on this system!
This will cause problems with multithreaded zip compression, so a normal one will be used instead.
For more info please read: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems""");
}
}
- if(Statics.CONFIG.backupInterval > 0)
- ServerTickEvents.END_SERVER_TICK.register(Statics.scheduler::tick);
+ ServerTickEvents.END_SERVER_TICK.register(new BackupScheduler()::tick);
//Restart Executor Service in singleplayer
ServerLifecycleEvents.SERVER_STARTING.register(ignored -> {
@@ -77,7 +79,7 @@ public class TextileBackup implements ModInitializer {
ServerLifecycleEvents.SERVER_STOPPED.register(server -> {
Statics.executorService.shutdown();
- if (Statics.CONFIG.shutdownBackup && Statics.globalShutdownBackupFlag.get()) {
+ if (config.get().shutdownBackup && Statics.globalShutdownBackupFlag.get()) {
BackupHelper.create(
BackupContext.Builder
.newBackupContextBuilder()
@@ -93,11 +95,11 @@ public class TextileBackup implements ModInitializer {
LiteralArgumentBuilder.literal("backup")
.requires((ctx) -> {
try {
- return ((Statics.CONFIG.playerWhitelist.contains(ctx.getEntityOrThrow().getEntityName()) ||
- ctx.hasPermissionLevel(Statics.CONFIG.permissionLevel)) &&
- !Statics.CONFIG.playerBlacklist.contains(ctx.getEntityOrThrow().getEntityName())) ||
+ return ((config.get().playerWhitelist.contains(ctx.getEntityOrThrow().getEntityName()) ||
+ ctx.hasPermissionLevel(config.get().permissionLevel)) &&
+ !config.get().playerBlacklist.contains(ctx.getEntityOrThrow().getEntityName())) ||
(ctx.getMinecraftServer().isSinglePlayer() &&
- Statics.CONFIG.alwaysSingleplayerAllowed);
+ config.get().alwaysSingleplayerAllowed);
} catch (Exception ignored) { //Command was called from server console.
return true;
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/CustomLogger.java b/src/main/java/net/szum123321/textile_backup/TextileLogger.java
similarity index 89%
rename from src/main/java/net/szum123321/textile_backup/core/CustomLogger.java
rename to src/main/java/net/szum123321/textile_backup/TextileLogger.java
index b40fea2..9036e41 100644
--- a/src/main/java/net/szum123321/textile_backup/core/CustomLogger.java
+++ b/src/main/java/net/szum123321/textile_backup/TextileLogger.java
@@ -1,6 +1,6 @@
/*
* A simple backup mod for Fabric
- * Copyright (C) 2020 Szum123321
+ * Copyright (C) 2021 Szum123321
*
* 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
@@ -16,7 +16,7 @@
* along with this program. If not, see .
*/
-package net.szum123321.textile_backup.core;
+package net.szum123321.textile_backup;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.command.ServerCommandSource;
@@ -29,11 +29,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.MessageFactory;
import org.apache.logging.log4j.message.ParameterizedMessageFactory;
+import org.apache.logging.log4j.util.StackLocatorUtil;
/*
This is practically just a copy-pate of Cotton's ModLogger with a few changes
*/
-public class CustomLogger {
+public class TextileLogger {
//private final boolean isDev = FabricLoader.getInstance().isDevelopmentEnvironment();
private final MessageFactory messageFactory;
@@ -42,12 +43,19 @@ public class CustomLogger {
private final String prefix;
private final MutableText prefixText;
- public CustomLogger(String name, String prefix) {
+/* public TextileLogger(String name, String prefix) {
this.messageFactory = ParameterizedMessageFactory.INSTANCE;
this.logger = LogManager.getLogger(name, messageFactory);
this.prefix = "[" + prefix + "]" + " ";
this.prefixText = new LiteralText(this.prefix).styled(style -> style.withColor(0x5B23DA));
}
+*/
+ public TextileLogger(String prefix) {
+ this.messageFactory = ParameterizedMessageFactory.INSTANCE;
+ this.logger = LogManager.getLogger(StackLocatorUtil.getCallerClass(2), messageFactory);
+ this.prefix = "[" + prefix + "]" + " ";
+ this.prefixText = new LiteralText(this.prefix).styled(style -> style.withColor(0x5B23DA));
+ }
public MutableText getPrefixText() {
return prefixText.shallowCopy();
diff --git a/src/main/java/net/szum123321/textile_backup/client/ModMenuEntry.java b/src/main/java/net/szum123321/textile_backup/client/ModMenuEntry.java
new file mode 100644
index 0000000..e3cc4e2
--- /dev/null
+++ b/src/main/java/net/szum123321/textile_backup/client/ModMenuEntry.java
@@ -0,0 +1,13 @@
+package net.szum123321.textile_backup.client;
+
+import com.terraformersmc.modmenu.api.ConfigScreenFactory;
+import com.terraformersmc.modmenu.api.ModMenuApi;
+import me.shedaniel.autoconfig.AutoConfig;
+import net.szum123321.textile_backup.config.ConfigPOJO;
+
+public class ModMenuEntry implements ModMenuApi {
+ @Override
+ public ConfigScreenFactory> getModConfigScreenFactory() {
+ return parent -> AutoConfig.getConfigScreen(ConfigPOJO.class, parent).get();
+ }
+}
diff --git a/src/main/java/net/szum123321/textile_backup/commands/create/CleanupCommand.java b/src/main/java/net/szum123321/textile_backup/commands/create/CleanupCommand.java
index d76ddaf..5e44864 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/create/CleanupCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/create/CleanupCommand.java
@@ -21,19 +21,21 @@ package net.szum123321.textile_backup.commands.create;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
-import net.minecraft.text.LiteralText;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.create.BackupHelper;
import net.szum123321.textile_backup.core.Utilities;
public class CleanupCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("cleanup")
.executes(ctx -> execute(ctx.getSource()));
}
private static int execute(ServerCommandSource source) {
- Statics.LOGGER.sendInfo(
+ log.sendInfo(
source,
"Deleted: {} files.",
BackupHelper.executeFileLimit(source, Utilities.getLevelName(source.getMinecraftServer()))
diff --git a/src/main/java/net/szum123321/textile_backup/commands/create/StartBackupCommand.java b/src/main/java/net/szum123321/textile_backup/commands/create/StartBackupCommand.java
index bf24c41..f7cafe0 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/create/StartBackupCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/create/StartBackupCommand.java
@@ -23,12 +23,16 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.create.BackupContext;
import net.szum123321.textile_backup.core.create.BackupHelper;
import javax.annotation.Nullable;
public class StartBackupCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("start")
.then(CommandManager.argument("comment", StringArgumentType.string())
@@ -51,7 +55,7 @@ public class StartBackupCommand {
)
);
} catch (Exception e) {
- Statics.LOGGER.error("Something went wrong while executing command!", e);
+ log.error("Something went wrong while executing command!", e);
throw e;
}
}
diff --git a/src/main/java/net/szum123321/textile_backup/commands/manage/BlacklistCommand.java b/src/main/java/net/szum123321/textile_backup/commands/manage/BlacklistCommand.java
index b8960b3..67e237c 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/manage/BlacklistCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/manage/BlacklistCommand.java
@@ -3,14 +3,18 @@ package net.szum123321.textile_backup.commands.manage;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import io.github.cottonmc.cotton.config.ConfigManager;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
public class BlacklistCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("blacklist")
.then(CommandManager.literal("add")
@@ -27,7 +31,7 @@ public class BlacklistCommand {
}
private static int help(ServerCommandSource source) {
- Statics.LOGGER.sendInfo(source, "Available command are: add [player], remove [player], list.");
+ log.sendInfo(source, "Available command are: add [player], remove [player], list.");
return 1;
}
@@ -37,12 +41,12 @@ public class BlacklistCommand {
builder.append("Currently on the blacklist are: ");
- for(String name : Statics.CONFIG.playerBlacklist){
+ for(String name : config.get().playerBlacklist){
builder.append(name);
builder.append(", ");
}
- Statics.LOGGER.sendInfo(source, builder.toString());
+ log.sendInfo(source, builder.toString());
return 1;
}
@@ -50,11 +54,11 @@ public class BlacklistCommand {
private static int executeAdd(CommandContext ctx) throws CommandSyntaxException {
ServerPlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
- if(Statics.CONFIG.playerBlacklist.contains(player.getEntityName())) {
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} is already blacklisted.", player.getEntityName());
+ if(config.get().playerBlacklist.contains(player.getEntityName())) {
+ log.sendInfo(ctx.getSource(), "Player: {} is already blacklisted.", player.getEntityName());
} else {
- Statics.CONFIG.playerBlacklist.add(player.getEntityName());
- ConfigManager.saveConfig(Statics.CONFIG);
+ config.get().playerBlacklist.add(player.getEntityName());
+ config.save();
StringBuilder builder = new StringBuilder();
@@ -62,8 +66,8 @@ public class BlacklistCommand {
builder.append(player.getEntityName());
builder.append(" added to the blacklist");
- if(Statics.CONFIG.playerWhitelist.contains(player.getEntityName())){
- Statics.CONFIG.playerWhitelist.remove(player.getEntityName());
+ if(config.get().playerWhitelist.contains(player.getEntityName())){
+ config.get().playerWhitelist.remove(player.getEntityName());
builder.append(" and removed form the whitelist");
}
@@ -71,7 +75,7 @@ public class BlacklistCommand {
ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player);
- Statics.LOGGER.sendInfo(ctx.getSource(), builder.toString());
+ log.sendInfo(ctx.getSource(), builder.toString());
}
return 1;
@@ -80,15 +84,15 @@ public class BlacklistCommand {
private static int executeRemove(CommandContext ctx) throws CommandSyntaxException {
ServerPlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
- if(!Statics.CONFIG.playerBlacklist.contains(player.getEntityName())) {
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} newer was blacklisted.", player.getEntityName());
+ if(!config.get().playerBlacklist.contains(player.getEntityName())) {
+ log.sendInfo(ctx.getSource(), "Player: {} newer was blacklisted.", player.getEntityName());
} else {
- Statics.CONFIG.playerBlacklist.remove(player.getEntityName());
- ConfigManager.saveConfig(Statics.CONFIG);
+ config.get().playerBlacklist.remove(player.getEntityName());
+ config.save();
ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player);
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} removed from the blacklist successfully.", player.getEntityName());
+ log.sendInfo(ctx.getSource(), "Player: {} removed from the blacklist successfully.", player.getEntityName());
}
return 1;
diff --git a/src/main/java/net/szum123321/textile_backup/commands/manage/DeleteCommand.java b/src/main/java/net/szum123321/textile_backup/commands/manage/DeleteCommand.java
index d98db4c..d4a6929 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/manage/DeleteCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/manage/DeleteCommand.java
@@ -24,6 +24,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.commands.CommandExceptions;
import net.szum123321.textile_backup.Statics;
import net.szum123321.textile_backup.commands.FileSuggestionProvider;
@@ -36,6 +38,8 @@ import java.util.Arrays;
import java.util.Optional;
public class DeleteCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("delete")
.then(CommandManager.argument("file", StringArgumentType.word())
@@ -63,20 +67,20 @@ public class DeleteCommand {
if(optionalFile.isPresent()) {
if(Statics.untouchableFile.isEmpty() || !Statics.untouchableFile.get().equals(optionalFile.get())) {
if(optionalFile.get().delete()) {
- Statics.LOGGER.sendInfo(source, "File {} successfully deleted!", optionalFile.get().getName());
+ log.sendInfo(source, "File {} successfully deleted!", optionalFile.get().getName());
if(source.getEntity() instanceof PlayerEntity)
- Statics.LOGGER.info("Player {} deleted {}.", source.getPlayer().getName(), optionalFile.get().getName());
+ log.info("Player {} deleted {}.", source.getPlayer().getName(), optionalFile.get().getName());
} else {
- Statics.LOGGER.sendError(source, "Something went wrong while deleting file!");
+ log.sendError(source, "Something went wrong while deleting file!");
}
} else {
- Statics.LOGGER.sendError(source, "Couldn't delete the file because it's being restored right now.");
- Statics.LOGGER.sendHint(source, "If you want to abort restoration then use: /backup killR");
+ log.sendError(source, "Couldn't delete the file because it's being restored right now.");
+ log.sendHint(source, "If you want to abort restoration then use: /backup killR");
}
} else {
- Statics.LOGGER.sendError(source, "Couldn't find file by this name.");
- Statics.LOGGER.sendHint(source, "Maybe try /backup list");
+ log.sendError(source, "Couldn't find file by this name.");
+ log.sendHint(source, "Maybe try /backup list");
}
return 0;
diff --git a/src/main/java/net/szum123321/textile_backup/commands/manage/ListBackupsCommand.java b/src/main/java/net/szum123321/textile_backup/commands/manage/ListBackupsCommand.java
index 2deb6d8..7d609ca 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/manage/ListBackupsCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/manage/ListBackupsCommand.java
@@ -21,12 +21,15 @@ package net.szum123321.textile_backup.commands.manage;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.restore.RestoreHelper;
import java.util.*;
public class ListBackupsCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("list")
.executes(ctx -> { StringBuilder builder = new StringBuilder();
@@ -50,7 +53,7 @@ public class ListBackupsCommand {
}
}
- Statics.LOGGER.sendInfo(ctx.getSource(), builder.toString());
+ log.sendInfo(ctx.getSource(), builder.toString());
return 1;
});
diff --git a/src/main/java/net/szum123321/textile_backup/commands/manage/WhitelistCommand.java b/src/main/java/net/szum123321/textile_backup/commands/manage/WhitelistCommand.java
index 8f5cc8f..d7ac8d1 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/manage/WhitelistCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/manage/WhitelistCommand.java
@@ -3,14 +3,18 @@ package net.szum123321.textile_backup.commands.manage;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
-import io.github.cottonmc.cotton.config.ConfigManager;
import net.minecraft.command.argument.EntityArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayerEntity;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
public class WhitelistCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static LiteralArgumentBuilder register(){
return CommandManager.literal("whitelist")
.then(CommandManager.literal("add")
@@ -27,7 +31,7 @@ public class WhitelistCommand {
}
private static int help(ServerCommandSource source){
- Statics.LOGGER.sendInfo(source, "Available command are: add [player], remove [player], list.");
+ log.sendInfo(source, "Available command are: add [player], remove [player], list.");
return 1;
}
@@ -37,12 +41,12 @@ public class WhitelistCommand {
builder.append("Currently on the whitelist are: ");
- for(String name : Statics.CONFIG.playerWhitelist){
+ for(String name : config.get().playerWhitelist){
builder.append(name);
builder.append(", ");
}
- Statics.LOGGER.sendInfo(source, builder.toString());
+ log.sendInfo(source, builder.toString());
return 1;
}
@@ -50,11 +54,11 @@ public class WhitelistCommand {
private static int executeAdd(CommandContext ctx) throws CommandSyntaxException {
ServerPlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
- if(Statics.CONFIG.playerWhitelist.contains(player.getEntityName())) {
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} is already whitelisted.", player.getEntityName());
+ if(config.get().playerWhitelist.contains(player.getEntityName())) {
+ log.sendInfo(ctx.getSource(), "Player: {} is already whitelisted.", player.getEntityName());
} else {
- Statics.CONFIG.playerWhitelist.add(player.getEntityName());
- ConfigManager.saveConfig(Statics.CONFIG);
+ config.get().playerWhitelist.add(player.getEntityName());
+ config.save();
StringBuilder builder = new StringBuilder();
@@ -62,8 +66,8 @@ public class WhitelistCommand {
builder.append(player.getEntityName());
builder.append(" added to the whitelist");
- if(Statics.CONFIG.playerBlacklist.contains(player.getEntityName())){
- Statics.CONFIG.playerBlacklist.remove(player.getEntityName());
+ if(config.get().playerBlacklist.contains(player.getEntityName())){
+ config.get().playerBlacklist.remove(player.getEntityName());
builder.append(" and removed form the blacklist");
}
@@ -71,7 +75,7 @@ public class WhitelistCommand {
ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player);
- Statics.LOGGER.sendInfo(ctx.getSource(), builder.toString());
+ log.sendInfo(ctx.getSource(), builder.toString());
}
return 1;
@@ -80,15 +84,15 @@ public class WhitelistCommand {
private static int executeRemove(CommandContext ctx) throws CommandSyntaxException {
ServerPlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
- if(!Statics.CONFIG.playerWhitelist.contains(player.getEntityName())) {
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} newer was whitelisted.", player.getEntityName());
+ if(!config.get().playerWhitelist.contains(player.getEntityName())) {
+ log.sendInfo(ctx.getSource(), "Player: {} newer was whitelisted.", player.getEntityName());
} else {
- Statics.CONFIG.playerWhitelist.remove(player.getEntityName());
- ConfigManager.saveConfig(Statics.CONFIG);
+ config.get().playerWhitelist.remove(player.getEntityName());
+ config.save();
ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player);
- Statics.LOGGER.sendInfo(ctx.getSource(), "Player: {} removed from the whitelist successfully.", player.getEntityName());
+ log.sendInfo(ctx.getSource(), "Player: {} removed from the whitelist successfully.", player.getEntityName());
}
return 1;
diff --git a/src/main/java/net/szum123321/textile_backup/commands/restore/KillRestoreCommand.java b/src/main/java/net/szum123321/textile_backup/commands/restore/KillRestoreCommand.java
index c6a474d..14ce9bd 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/restore/KillRestoreCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/restore/KillRestoreCommand.java
@@ -23,10 +23,13 @@ import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import java.util.Optional;
public class KillRestoreCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
public static LiteralArgumentBuilder register() {
return CommandManager.literal("killR")
.executes(ctx -> {
@@ -35,16 +38,16 @@ public class KillRestoreCommand {
Statics.globalShutdownBackupFlag.set(true);
Statics.untouchableFile = Optional.empty();
- Statics.LOGGER.info("{} cancelled backup restoration.", ctx.getSource().getEntity() instanceof PlayerEntity ?
+ log.info("{} cancelled backup restoration.", ctx.getSource().getEntity() instanceof PlayerEntity ?
"Player: " + ctx.getSource().getName() :
"SERVER"
);
if(ctx.getSource().getEntity() instanceof PlayerEntity)
- Statics.LOGGER.sendInfo(ctx.getSource(), "Backup restoration successfully stopped.");
+ log.sendInfo(ctx.getSource(), "Backup restoration successfully stopped.");
} else {
- Statics.LOGGER.sendInfo(ctx.getSource(), "Failed to stop backup restoration");
+ log.sendInfo(ctx.getSource(), "Failed to stop backup restoration");
}
return 1;
});
diff --git a/src/main/java/net/szum123321/textile_backup/commands/restore/RestoreBackupCommand.java b/src/main/java/net/szum123321/textile_backup/commands/restore/RestoreBackupCommand.java
index ad516f3..beba511 100644
--- a/src/main/java/net/szum123321/textile_backup/commands/restore/RestoreBackupCommand.java
+++ b/src/main/java/net/szum123321/textile_backup/commands/restore/RestoreBackupCommand.java
@@ -24,6 +24,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.commands.CommandExceptions;
import net.szum123321.textile_backup.Statics;
import net.szum123321.textile_backup.commands.FileSuggestionProvider;
@@ -36,6 +38,8 @@ import java.time.format.DateTimeParseException;
import java.util.Optional;
public class RestoreBackupCommand {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static LiteralArgumentBuilder register() {
return CommandManager.literal("restore")
.then(CommandManager.argument("file", StringArgumentType.word())
@@ -57,9 +61,9 @@ public class RestoreBackupCommand {
).executes(context -> {
ServerCommandSource source = context.getSource();
- Statics.LOGGER.sendInfo(source, "To restore given backup you have to provide exact creation time in format:");
- Statics.LOGGER.sendInfo(source, "[YEAR]-[MONTH]-[DAY]_[HOUR].[MINUTE].[SECOND]");
- Statics.LOGGER.sendInfo(source, "Example: /backup restore 2020-08-05_10.58.33");
+ log.sendInfo(source, "To restore given backup you have to provide exact creation time in format:");
+ log.sendInfo(source, "[YEAR]-[MONTH]-[DAY]_[HOUR].[MINUTE].[SECOND]");
+ log.sendInfo(source, "Example: /backup restore 2020-08-05_10.58.33");
return 1;
});
@@ -78,9 +82,9 @@ public class RestoreBackupCommand {
Optional backupFile = RestoreHelper.findFileAndLockIfPresent(dateTime, source.getMinecraftServer());
if(backupFile.isPresent()) {
- Statics.LOGGER.info("Found file to restore {}", backupFile.get().getFile().getName());
+ log.info("Found file to restore {}", backupFile.get().getFile().getName());
} else {
- Statics.LOGGER.sendInfo(source, "No file created on {} was found!", dateTime.format(Statics.defaultDateTimeFormatter));
+ log.sendInfo(source, "No file created on {} was found!", dateTime.format(Statics.defaultDateTimeFormatter));
return 0;
}
@@ -97,7 +101,7 @@ public class RestoreBackupCommand {
return 1;
} else {
- Statics.LOGGER.sendInfo(source, "Someone has already started another restoration.");
+ log.sendInfo(source, "Someone has already started another restoration.");
return 0;
}
diff --git a/src/main/java/net/szum123321/textile_backup/config/ConfigHelper.java b/src/main/java/net/szum123321/textile_backup/config/ConfigHelper.java
new file mode 100644
index 0000000..07332bd
--- /dev/null
+++ b/src/main/java/net/szum123321/textile_backup/config/ConfigHelper.java
@@ -0,0 +1,32 @@
+/*
+ * A simple backup mod for Fabric
+ * Copyright (C) 2021 Szum123321
+ *
+ * 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 net.szum123321.textile_backup.config;
+
+import me.shedaniel.autoconfig.ConfigHolder;
+
+public class ConfigHelper {
+ public static final ConfigHelper INSTANCE = new ConfigHelper();
+ private ConfigHolder configHolder;
+
+ public static void updateInstance(ConfigHolder ch) { INSTANCE.configHolder = ch; }
+
+ public ConfigPOJO get() { return configHolder.get(); }
+
+ public void save() { configHolder.save(); }
+}
diff --git a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java
new file mode 100644
index 0000000..2447156
--- /dev/null
+++ b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java
@@ -0,0 +1,174 @@
+/*
+ * A simple backup mod for Fabric
+ * Copyright (C) 2021 Szum123321
+ *
+ * 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 net.szum123321.textile_backup.config;
+
+import me.shedaniel.autoconfig.ConfigData;
+import me.shedaniel.autoconfig.annotation.Config;
+import me.shedaniel.autoconfig.annotation.ConfigEntry;
+import me.shedaniel.cloth.clothconfig.shadowed.blue.endless.jankson.Comment;
+import net.szum123321.textile_backup.TextileBackup;
+
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+@Config(name = TextileBackup.MOD_ID)
+public class ConfigPOJO implements ConfigData {
+ @Comment("""
+ Format of date&time used to name backup files.
+ Remember not to use '#' symbol or any other character that is not allowed by your operating system such as:
+ ':', '\\', etc...
+ For more info: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html""")
+ public String dateTimeFormat = "yyyy.MM.dd_HH-mm-ss";
+
+ @Comment("Should every world have its own backup folder?")
+ @ConfigEntry.Gui.Excluded
+ public boolean perWorldBackup = true;
+
+ @Comment("A path to the backup folder")
+ public String path = "backup/";
+
+ @Comment("""
+ This setting allows you to exclude files form being backed-up.
+ Be very careful when setting it, as it is easy corrupt your world!""")
+ public List fileBlacklist = new ArrayList<>();
+
+ @Comment("Should backups be deleted after being restored?")
+ public boolean deleteOldBackupAfterRestore = true;
+
+ @Comment("Maximum number of backups to keep.\nIf set to 0 then no backup will be deleted based their amount")
+ public int backupsToKeep = 10;
+
+ @Comment("""
+ Maximum age of backups to keep in seconds.
+ If set to 0 then backups will not be deleted based their age""")
+ public long maxAge = 0;
+
+ @Comment("""
+ Maximum size of backup folder in kilo bytes (1024).
+ If set to 0 then backups will not be deleted""")
+ public int maxSize = 0;
+
+ @Comment("""
+ Time between automatic backups in seconds
+ When set to 0 backups will not be performed automatically""")
+ @ConfigEntry.Gui.Tooltip()
+ @ConfigEntry.Category("Create")
+ public long backupInterval = 3600;
+
+ @Comment("Should backups be done even if there are no players?")
+ @ConfigEntry.Category("Create")
+ public boolean doBackupsOnEmptyServer = false;
+
+ @Comment("Should backup be made on server shutdown?")
+ @ConfigEntry.Category("Create")
+ public boolean shutdownBackup = true;
+
+ @Comment("Should world be backed up before restoring a backup?")
+ @ConfigEntry.Category("Create")
+ public boolean backupOldWorlds = true;
+
+ @Comment("Compression level 0 - 9 Only affects zip compression.")
+ @ConfigEntry.BoundedDiscrete(max = 9)
+ @ConfigEntry.Category("Create")
+ public int compression = 7;
+
+ @Comment("""
+ Limit how many cores can be used for compression.
+ 0 means that all available cores will be used""")
+ @ConfigEntry.Category("Create")
+ public int compressionCoreCountLimit = 0;
+
+ @Comment(value = """
+ Available formats are:
+ ZIP - normal zip archive using standard deflate compression
+ GZIP - tar.gz using gzip compression
+ BZIP2 - tar.bz2 archive using bzip2 compression
+ LZMA - tar.xz using lzma compression
+ TAR - .tar with no compression""")
+ @ConfigEntry.Category("Create")
+ @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON)
+ public ArchiveFormat format = ArchiveFormat.ZIP;
+
+ @Comment("Minimal permission level required to run commands")
+ @ConfigEntry.Category("Manage")
+ public int permissionLevel = 4;
+
+ @Comment("""
+ Player on singleplayer is always allowed to run command.
+ Warning! On lan party everyone will be allowed to run it.""")
+ @ConfigEntry.Category("Manage")
+ public boolean alwaysSingleplayerAllowed = true;
+
+ @Comment("Players allowed to run backup commands without sufficient permission level")
+ @ConfigEntry.Category("Manage")
+ public Set playerWhitelist = new HashSet<>();
+
+ @Comment("Players banned from running backup commands besides their sufficient permission level")
+ @ConfigEntry.Category("Manage")
+ public Set playerBlacklist = new HashSet<>();
+
+ @Comment("Delay in seconds between typing-in /backup restore and it actually starting")
+ @ConfigEntry.Category("Restore")
+ public int restoreDelay = 30;
+
+ @Override
+ public void validatePostLoad() throws ValidationException {
+ if(compressionCoreCountLimit > Runtime.getRuntime().availableProcessors())
+ throw new ValidationException("compressionCoreCountLimit is too high! Your system only has: " + Runtime.getRuntime().availableProcessors() + " cores!");
+
+ try {
+ DateTimeFormatter.ofPattern(dateTimeFormat);
+ } catch (IllegalArgumentException e) {
+ throw new ValidationException(
+ "dateTimeFormat is wrong! See: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html",
+ e
+ );
+ }
+ }
+
+ public enum ArchiveFormat {
+ ZIP("zip"),
+ GZIP("tar", "gz"),
+ BZIP2("tar", "bz2"),
+ LZMA("tar", "xz"),
+ TAR("tar");
+
+ private final List extensionPieces;
+
+ ArchiveFormat(String... extensionParts) {
+ extensionPieces = Arrays.asList(extensionParts);
+ }
+
+ public String getCompleteString() {
+ StringBuilder builder = new StringBuilder();
+
+ extensionPieces.forEach(s -> builder.append('.').append(s));
+
+ return builder.toString();
+ }
+
+ boolean isMultipart() {
+ return extensionPieces.size() > 1;
+ }
+
+ public String getLastPiece() {
+ return extensionPieces.get(extensionPieces.size() - 1);
+ }
+ }
+}
diff --git a/src/main/java/net/szum123321/textile_backup/core/Utilities.java b/src/main/java/net/szum123321/textile_backup/core/Utilities.java
index e85ecae..68ba125 100644
--- a/src/main/java/net/szum123321/textile_backup/core/Utilities.java
+++ b/src/main/java/net/szum123321/textile_backup/core/Utilities.java
@@ -21,7 +21,8 @@ package net.szum123321.textile_backup.core;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.world.World;
-import net.szum123321.textile_backup.ConfigHandler;
+import net.szum123321.textile_backup.config.ConfigHelper;
+import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.Statics;
import net.szum123321.textile_backup.mixin.MinecraftServerSessionAccessor;
@@ -36,6 +37,8 @@ import java.util.Arrays;
import java.util.Optional;
public class Utilities {
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static String getLevelName(MinecraftServer server) {
return ((MinecraftServerSessionAccessor)server).getSession().getDirectoryName();
}
@@ -47,18 +50,16 @@ public class Utilities {
}
public static File getBackupRootPath(String worldName) {
- File path = new File(Statics.CONFIG.path).getAbsoluteFile();
+ File path = new File(config.get().path).getAbsoluteFile();
- if (Statics.CONFIG.perWorldBackup)
- path = path.toPath().resolve(worldName).toFile();
+ if (config.get().perWorldBackup) path = path.toPath().resolve(worldName).toFile();
- if (!path.exists()) {
- path.mkdirs();
- }
+ if (!path.exists()) path.mkdirs();
return path;
}
+ //This is quite pointless
public static boolean isTmpAvailable() {
try {
File tmp = File.createTempFile("textile_backup_tmp_test", String.valueOf(Instant.now().getEpochSecond()));
@@ -88,26 +89,23 @@ public class Utilities {
public static boolean isBlacklisted(Path path) {
if(isWindows()) { //hotfix!
- if (path.getFileName().toString().equals("session.lock")) {
- Statics.LOGGER.trace("Skipping session.lock");
- return true;
- }
+ if (path.getFileName().toString().equals("session.lock")) return true;
}
- for(String i : Statics.CONFIG.fileBlacklist) if(path.startsWith(i)) return true;
+ for(String i : config.get().fileBlacklist) if(path.startsWith(i)) return true;
return false;
}
- public static Optional getArchiveExtension(String fileName) {
+ public static Optional getArchiveExtension(String fileName) {
String[] parts = fileName.split("\\.");
- return Arrays.stream(ConfigHandler.ArchiveFormat.values())
+ return Arrays.stream(ConfigPOJO.ArchiveFormat.values())
.filter(format -> format.getLastPiece().equals(parts[parts.length - 1]))
.findAny();
}
- public static Optional getArchiveExtension(File f) {
+ public static Optional getArchiveExtension(File f) {
return getArchiveExtension(f.getName());
}
@@ -155,7 +153,7 @@ public class Utilities {
}
public static DateTimeFormatter getDateTimeFormatter() {
- return DateTimeFormatter.ofPattern(Statics.CONFIG.dateTimeFormat);
+ return DateTimeFormatter.ofPattern(config.get().dateTimeFormat);
}
public static DateTimeFormatter getBackupDateTimeFormatter() {
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/BackupHelper.java b/src/main/java/net/szum123321/textile_backup/core/create/BackupHelper.java
index d590d59..7d643e6 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/BackupHelper.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/BackupHelper.java
@@ -25,6 +25,9 @@ import net.minecraft.text.MutableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.Util;
import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Utilities;
import org.apache.commons.io.FileUtils;
@@ -37,6 +40,9 @@ import java.util.Comparator;
import java.util.UUID;
public class BackupHelper {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static Runnable create(BackupContext ctx) {
notifyPlayers(ctx);
@@ -55,17 +61,17 @@ public class BackupHelper {
builder.append(" on: ");
builder.append(Utilities.getDateTimeFormatter().format(LocalDateTime.now()));
- Statics.LOGGER.info(builder.toString());
+ log.info(builder.toString());
if (ctx.shouldSave()) {
- Statics.LOGGER.sendInfoAL(ctx, "Saving server...");
+ log.sendInfoAL(ctx, "Saving server...");
ctx.getServer().getPlayerManager().saveAllPlayerData();
try {
ctx.getServer().save(false, true, true);
} catch (Exception e) {
- Statics.LOGGER.sendErrorAL(ctx,"An exception occurred when trying to save the world!");
+ log.sendErrorAL(ctx,"An exception occurred when trying to save the world!");
}
}
@@ -73,7 +79,7 @@ public class BackupHelper {
}
private static void notifyPlayers(BackupContext ctx) {
- MutableText message = Statics.LOGGER.getPrefixText();
+ MutableText message = log.getPrefixText();
message.append(new LiteralText("Warning! Server backup will begin shortly. You may experience some lag.").formatted(Formatting.WHITE));
UUID uuid;
@@ -94,30 +100,30 @@ public class BackupHelper {
int deletedFiles = 0;
if (root.isDirectory() && root.exists() && root.listFiles() != null) {
- if (Statics.CONFIG.maxAge > 0) { // delete files older that configured
+ if (config.get().maxAge > 0) { // delete files older that configured
final LocalDateTime now = LocalDateTime.now();
deletedFiles += Arrays.stream(root.listFiles())
.filter(Utilities::isValidBackup)// We check if we can get file's creation date so that the next line won't throw an exception
- .filter(f -> now.toEpochSecond(ZoneOffset.UTC) - Utilities.getFileCreationTime(f).get().toEpochSecond(ZoneOffset.UTC) > Statics.CONFIG.maxAge)
+ .filter(f -> now.toEpochSecond(ZoneOffset.UTC) - Utilities.getFileCreationTime(f).get().toEpochSecond(ZoneOffset.UTC) > config.get().maxAge)
.map(f -> deleteFile(f, ctx))
.filter(b -> b).count(); //a bit awkward
}
- if (Statics.CONFIG.backupsToKeep > 0 && root.listFiles().length > Statics.CONFIG.backupsToKeep) {
+ if (config.get().backupsToKeep > 0 && root.listFiles().length > config.get().backupsToKeep) {
deletedFiles += Arrays.stream(root.listFiles())
.filter(Utilities::isValidBackup)
.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime((File) f).get()).reversed())
- .skip(Statics.CONFIG.backupsToKeep)
+ .skip(config.get().backupsToKeep)
.map(f -> deleteFile(f, ctx))
.filter(b -> b).count();
}
- if (Statics.CONFIG.maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > Statics.CONFIG.maxSize) {
+ if (config.get().maxSize > 0 && FileUtils.sizeOfDirectory(root) / 1024 > config.get().maxSize) {
deletedFiles += Arrays.stream(root.listFiles())
.filter(Utilities::isValidBackup)
.sorted(Comparator.comparing(f -> Utilities.getFileCreationTime(f).get()))
- .takeWhile(f -> FileUtils.sizeOfDirectory(root) / 1024 > Statics.CONFIG.maxSize)
+ .takeWhile(f -> FileUtils.sizeOfDirectory(root) / 1024 > config.get().maxSize)
.map(f -> deleteFile(f, ctx))
.filter(b -> b).count();
}
@@ -129,10 +135,10 @@ public class BackupHelper {
private static boolean deleteFile(File f, ServerCommandSource ctx) {
if(Statics.untouchableFile.isEmpty()|| !Statics.untouchableFile.get().equals(f)) {
if(f.delete()) {
- Statics.LOGGER.sendInfoAL(ctx, "Deleting: {}", f.getName());
+ log.sendInfoAL(ctx, "Deleting: {}", f.getName());
return true;
} else {
- Statics.LOGGER.sendErrorAL(ctx, "Something went wrong while deleting: {}.", f.getName());
+ log.sendErrorAL(ctx, "Something went wrong while deleting: {}.", f.getName());
}
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/BackupScheduler.java b/src/main/java/net/szum123321/textile_backup/core/create/BackupScheduler.java
index 8ff78a9..b2ca19e 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/BackupScheduler.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/BackupScheduler.java
@@ -20,11 +20,14 @@ package net.szum123321.textile_backup.core.create;
import net.minecraft.server.MinecraftServer;
import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.ActionInitiator;
import java.time.Instant;
public class BackupScheduler {
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
private boolean scheduled;
private long nextBackup;
@@ -34,9 +37,10 @@ public class BackupScheduler {
}
public void tick(MinecraftServer server) {
+ if(config.get().backupInterval < 1) return;
long now = Instant.now().getEpochSecond();
- if(Statics.CONFIG.doBackupsOnEmptyServer || server.getPlayerManager().getCurrentPlayerCount() > 0) {
+ if(config.get().doBackupsOnEmptyServer || server.getPlayerManager().getCurrentPlayerCount() > 0) {
if(scheduled) {
if(nextBackup <= now) {
Statics.executorService.submit(
@@ -50,13 +54,13 @@ public class BackupScheduler {
)
);
- nextBackup = now + Statics.CONFIG.backupInterval;
+ nextBackup = now + config.get().backupInterval;
}
} else {
- nextBackup = now + Statics.CONFIG.backupInterval;
+ nextBackup = now + config.get().backupInterval;
scheduled = true;
}
- } else if(!Statics.CONFIG.doBackupsOnEmptyServer && server.getPlayerManager().getCurrentPlayerCount() == 0) {
+ } else if(!config.get().doBackupsOnEmptyServer && server.getPlayerManager().getCurrentPlayerCount() == 0) {
if(scheduled && nextBackup <= now) {
Statics.executorService.submit(
BackupHelper.create(
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/MakeBackupRunnable.java b/src/main/java/net/szum123321/textile_backup/core/create/MakeBackupRunnable.java
index 5138a37..5879060 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/MakeBackupRunnable.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/MakeBackupRunnable.java
@@ -19,6 +19,9 @@
package net.szum123321.textile_backup.core.create;
import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.create.compressors.*;
import net.szum123321.textile_backup.core.Utilities;
@@ -33,6 +36,9 @@ import java.io.OutputStream;
import java.time.LocalDateTime;
public class MakeBackupRunnable implements Runnable {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
private final BackupContext context;
public MakeBackupRunnable(BackupContext context){
@@ -45,11 +51,11 @@ public class MakeBackupRunnable implements Runnable {
Utilities.disableWorldSaving(context.getServer());
Statics.disableWatchdog = true;
- Statics.LOGGER.sendInfoAL(context, "Starting backup");
+ log.sendInfoAL(context, "Starting backup");
File world = Utilities.getWorldFolder(context.getServer());
- Statics.LOGGER.trace("Minecraft world is: {}", world);
+ log.trace("Minecraft world is: {}", world);
File outFile = Utilities
.getBackupRootPath(Utilities.getLevelName(context.getServer()))
@@ -57,32 +63,32 @@ public class MakeBackupRunnable implements Runnable {
.resolve(getFileName())
.toFile();
- Statics.LOGGER.trace("Outfile is: {}", outFile);
+ log.trace("Outfile is: {}", outFile);
outFile.getParentFile().mkdirs();
try {
outFile.createNewFile();
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred when trying to create new backup file!", e);
+ log.error("An exception occurred when trying to create new backup file!", e);
if(context.getInitiator() == ActionInitiator.Player)
- Statics.LOGGER.sendError(context, "An exception occurred when trying to create new backup file!");
+ log.sendError(context, "An exception occurred when trying to create new backup file!");
return;
}
int coreCount;
- if(Statics.CONFIG.compressionCoreCountLimit <= 0) {
+ if(config.get().compressionCoreCountLimit <= 0) {
coreCount = Runtime.getRuntime().availableProcessors();
} else {
- coreCount = Math.min(Statics.CONFIG.compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
+ coreCount = Math.min(config.get().compressionCoreCountLimit, Runtime.getRuntime().availableProcessors());
}
- Statics.LOGGER.trace("Running compression on {} threads. Available cores: {}", coreCount, Runtime.getRuntime().availableProcessors());
+ log.trace("Running compression on {} threads. Available cores: {}", coreCount, Runtime.getRuntime().availableProcessors());
- switch (Statics.CONFIG.format) {
+ switch (config.get().format) {
case ZIP -> {
if (Statics.tmpAvailable && coreCount > 1)
ParallelZipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
@@ -98,16 +104,16 @@ public class MakeBackupRunnable implements Runnable {
}.createArchive(world, outFile, context, coreCount);
case TAR -> new AbstractTarArchiver().createArchive(world, outFile, context, coreCount);
default -> {
- Statics.LOGGER.warn("Specified compressor ({}) is not supported! Zip will be used instead!", Statics.CONFIG.format);
+ log.warn("Specified compressor ({}) is not supported! Zip will be used instead!", config.get().format);
if (context.getInitiator() == ActionInitiator.Player)
- Statics.LOGGER.sendError(context.getCommandSource(), "Error! No correct compression format specified! Using default compressor!");
+ log.sendError(context.getCommandSource(), "Error! No correct compression format specified! Using default compressor!");
ZipCompressor.getInstance().createArchive(world, outFile, context, coreCount);
}
}
BackupHelper.executeFileLimit(context.getCommandSource(), Utilities.getLevelName(context.getServer()));
- Statics.LOGGER.sendInfoAL(context, "Done!");
+ log.sendInfoAL(context, "Done!");
} finally {
Utilities.enableWorldSaving(context.getServer());
Statics.disableWatchdog = false;
@@ -119,6 +125,6 @@ public class MakeBackupRunnable implements Runnable {
return Utilities.getDateTimeFormatter().format(now) +
(context.getComment() != null ? "#" + context.getComment().replace("#", "") : "") +
- Statics.CONFIG.format.getCompleteString();
+ config.get().format.getCompleteString();
}
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/compressors/AbstractCompressor.java b/src/main/java/net/szum123321/textile_backup/core/create/compressors/AbstractCompressor.java
index a4634d0..105a317 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/compressors/AbstractCompressor.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/compressors/AbstractCompressor.java
@@ -18,7 +18,8 @@
package net.szum123321.textile_backup.core.create.compressors;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.NoSpaceLeftOnDeviceException;
import net.szum123321.textile_backup.core.Utilities;
@@ -32,6 +33,8 @@ import java.time.Instant;
import java.util.concurrent.ExecutionException;
public abstract class AbstractCompressor {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public void createArchive(File inputFile, File outputFile, BackupContext ctx, int coreLimit) {
Instant start = Instant.now();
@@ -48,35 +51,35 @@ public abstract class AbstractCompressor {
//hopefully one broken file won't spoil the whole archive
addEntry(file, inputFile.toPath().relativize(file.toPath()).toString(), arc);
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred while trying to compress: {}", inputFile.toPath().relativize(file.toPath()).toString(), e);
+ log.error("An exception occurred while trying to compress: {}", inputFile.toPath().relativize(file.toPath()).toString(), e);
if (ctx.getInitiator() == ActionInitiator.Player)
- Statics.LOGGER.sendError(ctx, "Something went wrong while compressing files!");
+ log.sendError(ctx, "Something went wrong while compressing files!");
}
});
finish(arc);
} catch(NoSpaceLeftOnDeviceException e) {
- Statics.LOGGER.error("CRITICAL ERROR OCCURRED!");
- Statics.LOGGER.error("The backup is corrupted.");
- Statics.LOGGER.error("Don't panic! This is a known issue!");
- Statics.LOGGER.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
- Statics.LOGGER.error("In case this isn't it here's also the exception itself!", e);
+ log.error("CRITICAL ERROR OCCURRED!");
+ log.error("The backup is corrupted.");
+ log.error("Don't panic! This is a known issue!");
+ log.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
+ log.error("In case this isn't it here's also the exception itself!", e);
if(ctx.getInitiator() == ActionInitiator.Player) {
- Statics.LOGGER.sendError(ctx, "Backup failed. The file is corrupt.");
- Statics.LOGGER.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
+ log.sendError(ctx, "Backup failed. The file is corrupt.");
+ log.error("For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems");
}
} catch (IOException | InterruptedException | ExecutionException e) {
- Statics.LOGGER.error("An exception occurred!", e);
+ log.error("An exception occurred!", e);
} catch (Exception e) {
if(ctx.getInitiator() == ActionInitiator.Player)
- Statics.LOGGER.sendError(ctx, "Something went wrong while compressing files!");
+ log.sendError(ctx, "Something went wrong while compressing files!");
}
close();
- Statics.LOGGER.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
+ log.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
}
protected abstract OutputStream createArchiveOutputStream(OutputStream stream, BackupContext ctx, int coreLimit) throws IOException;
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/compressors/ParallelZipCompressor.java b/src/main/java/net/szum123321/textile_backup/core/create/compressors/ParallelZipCompressor.java
index b7a0c9e..bab11a7 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/compressors/ParallelZipCompressor.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/compressors/ParallelZipCompressor.java
@@ -18,7 +18,8 @@
package net.szum123321.textile_backup.core.create.compressors;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.NoSpaceLeftOnDeviceException;
import net.szum123321.textile_backup.core.create.BackupContext;
import org.apache.commons.compress.archivers.zip.*;
@@ -36,6 +37,8 @@ import java.util.zip.ZipEntry;
https://stackoverflow.com/users/2987755/dkb
*/
public class ParallelZipCompressor extends ZipCompressor {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
//These fields are used to discriminate against the issue #51
private final static SimpleStackTraceElement[] STACKTRACE = {
new SimpleStackTraceElement("sun.nio.ch.FileDispatcherImpl", "write0", true),
@@ -130,7 +133,7 @@ public class ParallelZipCompressor extends ZipCompressor {
try {
return new FileInputStream(sourceFile);
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred while trying to create an input stream from file: {}!", sourceFile.getName(), e);
+ log.error("An exception occurred while trying to create an input stream from file: {}!", sourceFile.getName(), e);
}
return null;
diff --git a/src/main/java/net/szum123321/textile_backup/core/create/compressors/ZipCompressor.java b/src/main/java/net/szum123321/textile_backup/core/create/compressors/ZipCompressor.java
index 46f2c35..ea98afd 100644
--- a/src/main/java/net/szum123321/textile_backup/core/create/compressors/ZipCompressor.java
+++ b/src/main/java/net/szum123321/textile_backup/core/create/compressors/ZipCompressor.java
@@ -18,7 +18,7 @@
package net.szum123321.textile_backup.core.create.compressors;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.config.ConfigHelper;
import net.szum123321.textile_backup.core.Utilities;
import net.szum123321.textile_backup.core.create.BackupContext;
import org.apache.commons.compress.archivers.zip.Zip64Mode;
@@ -27,12 +27,13 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.utils.IOUtils;
import java.io.*;
-import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.zip.CRC32;
import java.util.zip.Checksum;
public class ZipCompressor extends AbstractCompressor {
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static ZipCompressor getInstance() {
return new ZipCompressor();
}
@@ -43,7 +44,7 @@ public class ZipCompressor extends AbstractCompressor {
arc.setMethod(ZipArchiveOutputStream.DEFLATED);
arc.setUseZip64(Zip64Mode.AsNeeded);
- arc.setLevel(Statics.CONFIG.compression);
+ arc.setLevel(config.get().compression);
arc.setComment("Created on: " + Utilities.getDateTimeFormatter().format(LocalDateTime.now()));
return arc;
diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/AwaitThread.java b/src/main/java/net/szum123321/textile_backup/core/restore/AwaitThread.java
index 6c60ab7..c022092 100644
--- a/src/main/java/net/szum123321/textile_backup/core/restore/AwaitThread.java
+++ b/src/main/java/net/szum123321/textile_backup/core/restore/AwaitThread.java
@@ -18,7 +18,8 @@
package net.szum123321.textile_backup.core.restore;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import java.util.concurrent.atomic.AtomicInteger;
@@ -26,6 +27,7 @@ import java.util.concurrent.atomic.AtomicInteger;
This thread waits some amount of time and then starts a new, independent thread
*/
public class AwaitThread extends Thread {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
private final static AtomicInteger threadCounter = new AtomicInteger(0);
private final int delay;
@@ -40,13 +42,13 @@ public class AwaitThread extends Thread {
@Override
public void run() {
- Statics.LOGGER.info("Countdown begins... Waiting {} second.", delay);
+ log.info("Countdown begins... Waiting {} second.", delay);
// 𝄞 This is final count down! Tu ruru Tu, Tu Ru Tu Tu ♪
try {
Thread.sleep(delay * 1000L);
} catch (InterruptedException e) {
- Statics.LOGGER.info("Backup restoration cancelled.");
+ log.info("Backup restoration cancelled.");
return;
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreBackupRunnable.java b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreBackupRunnable.java
index 5cbaca3..33ab6d2 100644
--- a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreBackupRunnable.java
+++ b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreBackupRunnable.java
@@ -18,7 +18,10 @@
package net.szum123321.textile_backup.core.restore;
-import net.szum123321.textile_backup.ConfigHandler;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
+import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.LivingServer;
import net.szum123321.textile_backup.Statics;
@@ -31,6 +34,9 @@ import net.szum123321.textile_backup.core.restore.decompressors.ZipDecompressor;
import java.io.File;
public class RestoreBackupRunnable implements Runnable {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
private final RestoreContext ctx;
public RestoreBackupRunnable(RestoreContext ctx) {
@@ -41,12 +47,12 @@ public class RestoreBackupRunnable implements Runnable {
public void run() {
Statics.globalShutdownBackupFlag.set(false);
- Statics.LOGGER.info("Shutting down server...");
+ log.info("Shutting down server...");
ctx.getServer().stop(false);
awaitServerShutdown();
- if(Statics.CONFIG.backupOldWorlds) {
+ if(config.get().backupOldWorlds) {
BackupHelper.create(
BackupContext.Builder
.newBackupContextBuilder()
@@ -59,31 +65,35 @@ public class RestoreBackupRunnable implements Runnable {
File worldFile = Utilities.getWorldFolder(ctx.getServer());
- Statics.LOGGER.info("Deleting old world...");
+ log.info("Deleting old world...");
if(!deleteDirectory(worldFile))
- Statics.LOGGER.error("Something went wrong while deleting old world!");
+ log.error("Something went wrong while deleting old world!");
worldFile.mkdirs();
- Statics.LOGGER.info("Starting decompression...");
+ log.info("Starting decompression...");
- if(ctx.getFile().getArchiveFormat() == ConfigHandler.ArchiveFormat.ZIP)
+ if(ctx.getFile().getArchiveFormat() == ConfigPOJO.ArchiveFormat.ZIP)
ZipDecompressor.decompress(ctx.getFile().getFile(), worldFile);
else
GenericTarDecompressor.decompress(ctx.getFile().getFile(), worldFile);
- if(Statics.CONFIG.deleteOldBackupAfterRestore) {
- Statics.LOGGER.info("Deleting old backup");
+ if(config.get().deleteOldBackupAfterRestore) {
+ log.info("Deleting old backup");
if(!ctx.getFile().getFile().delete())
- Statics.LOGGER.info("Something went wrong while deleting old backup");
+ log.info("Something went wrong while deleting old backup");
}
//in case we're playing on client
Statics.globalShutdownBackupFlag.set(true);
- Statics.LOGGER.info("Done!");
+ log.info("Done!");
+
+ //Might solve #37
+ //Idk if it's a good idea...
+ //Runtime.getRuntime().exit(0);
}
private void awaitServerShutdown() {
@@ -91,7 +101,7 @@ public class RestoreBackupRunnable implements Runnable {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
- Statics.LOGGER.error("Exception occurred!", e);
+ log.error("Exception occurred!", e);
}
}
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreHelper.java b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreHelper.java
index 44b7c42..6b0d749 100644
--- a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreHelper.java
+++ b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreHelper.java
@@ -24,7 +24,10 @@ import net.minecraft.text.LiteralText;
import net.minecraft.text.MutableText;
import net.minecraft.util.Formatting;
import net.minecraft.util.Util;
-import net.szum123321.textile_backup.ConfigHandler;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
+import net.szum123321.textile_backup.config.ConfigHelper;
+import net.szum123321.textile_backup.config.ConfigPOJO;
import net.szum123321.textile_backup.Statics;
import net.szum123321.textile_backup.core.ActionInitiator;
import net.szum123321.textile_backup.core.Utilities;
@@ -36,6 +39,9 @@ import java.util.*;
import java.util.stream.Collectors;
public class RestoreHelper {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+ private final static ConfigHelper config = ConfigHelper.INSTANCE;
+
public static Optional findFileAndLockIfPresent(LocalDateTime backupTime, MinecraftServer server) {
File root = Utilities.getBackupRootPath(Utilities.getLevelName(server));
@@ -52,24 +58,24 @@ public class RestoreHelper {
public static AwaitThread create(RestoreContext ctx) {
if(ctx.getInitiator() == ActionInitiator.Player)
- Statics.LOGGER.info("Backup restoration was initiated by: {}", ctx.getCommandSource().getName());
+ log.info("Backup restoration was initiated by: {}", ctx.getCommandSource().getName());
else
- Statics.LOGGER.info("Backup restoration was initiated form Server Console");
+ log.info("Backup restoration was initiated form Server Console");
notifyPlayers(ctx);
return new AwaitThread(
- Statics.CONFIG.restoreDelay,
+ config.get().restoreDelay,
new RestoreBackupRunnable(ctx)
);
}
private static void notifyPlayers(RestoreContext ctx) {
- MutableText message = Statics.LOGGER.getPrefixText();
+ MutableText message = log.getPrefixText();
message.append(
new LiteralText(
"Warning! The server is going to shut down in " +
- Statics.CONFIG.restoreDelay +
+ config.get().restoreDelay +
" seconds!"
).formatted(Formatting.WHITE)
);
@@ -100,7 +106,7 @@ public class RestoreHelper {
public static class RestoreableFile implements Comparable {
private final File file;
- private final ConfigHandler.ArchiveFormat archiveFormat;
+ private final ConfigPOJO.ArchiveFormat archiveFormat;
private final LocalDateTime creationTime;
private final String comment;
@@ -131,7 +137,7 @@ public class RestoreHelper {
return file;
}
- public ConfigHandler.ArchiveFormat getArchiveFormat() {
+ public ConfigPOJO.ArchiveFormat getArchiveFormat() {
return archiveFormat;
}
diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/GenericTarDecompressor.java b/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/GenericTarDecompressor.java
index a305b5b..bc26258 100644
--- a/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/GenericTarDecompressor.java
+++ b/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/GenericTarDecompressor.java
@@ -18,7 +18,8 @@
package net.szum123321.textile_backup.core.restore.decompressors;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.Utilities;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
@@ -32,6 +33,8 @@ import java.time.Duration;
import java.time.Instant;
public class GenericTarDecompressor {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static void decompress(File input, File target) {
Instant start = Instant.now();
@@ -43,7 +46,7 @@ public class GenericTarDecompressor {
while ((entry = archiveInputStream.getNextTarEntry()) != null) {
if(!archiveInputStream.canReadEntryData(entry)) {
- Statics.LOGGER.error("Something when wrong while trying to decompress {}", entry.getName());
+ log.error("Something when wrong while trying to decompress {}", entry.getName());
continue;
}
@@ -55,22 +58,22 @@ public class GenericTarDecompressor {
File parent = file.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
- Statics.LOGGER.error("Failed to create {}", parent);
+ log.error("Failed to create {}", parent);
} else {
try (OutputStream outputStream = Files.newOutputStream(file.toPath());
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
IOUtils.copy(archiveInputStream, bufferedOutputStream);
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred while trying to decompress file: {}", file.getName(), e);
+ log.error("An exception occurred while trying to decompress file: {}", file.getName(), e);
}
}
}
}
} catch (IOException | CompressorException e) {
- Statics.LOGGER.error("An exception occurred! ", e);
+ log.error("An exception occurred! ", e);
}
- Statics.LOGGER.info("Decompression took {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
+ log.info("Decompression took {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
}
private static InputStream getCompressorInputStream(InputStream inputStream) throws CompressorException {
diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/ZipDecompressor.java b/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/ZipDecompressor.java
index a07e952..3fee7eb 100644
--- a/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/ZipDecompressor.java
+++ b/src/main/java/net/szum123321/textile_backup/core/restore/decompressors/ZipDecompressor.java
@@ -18,7 +18,8 @@
package net.szum123321.textile_backup.core.restore.decompressors;
-import net.szum123321.textile_backup.Statics;
+import net.szum123321.textile_backup.TextileBackup;
+import net.szum123321.textile_backup.TextileLogger;
import net.szum123321.textile_backup.core.Utilities;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
@@ -30,6 +31,8 @@ import java.time.Duration;
import java.time.Instant;
public class ZipDecompressor {
+ private final static TextileLogger log = new TextileLogger(TextileBackup.MOD_NAME);
+
public static void decompress(File inputFile, File target) {
Instant start = Instant.now();
@@ -40,7 +43,7 @@ public class ZipDecompressor {
while ((entry = zipInputStream.getNextZipEntry()) != null) {
if(!zipInputStream.canReadEntryData(entry)){
- Statics.LOGGER.error("Something when wrong while trying to decompress {}", entry.getName());
+ log.error("Something when wrong while trying to decompress {}", entry.getName());
continue;
}
@@ -52,21 +55,21 @@ public class ZipDecompressor {
File parent = file.getParentFile();
if (!parent.isDirectory() && !parent.mkdirs()) {
- Statics.LOGGER.error("Failed to create {}", parent);
+ log.error("Failed to create {}", parent);
} else {
try (OutputStream outputStream = Files.newOutputStream(file.toPath());
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream)) {
IOUtils.copy(zipInputStream, bufferedOutputStream);
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred while trying to decompress file: {}", file.getName(), e);
+ log.error("An exception occurred while trying to decompress file: {}", file.getName(), e);
}
}
}
}
} catch (IOException e) {
- Statics.LOGGER.error("An exception occurred! ", e);
+ log.error("An exception occurred! ", e);
}
- Statics.LOGGER.info("Decompression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
+ log.info("Decompression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now())));
}
}
diff --git a/src/main/resources/assets/textile_backup/lang/en_us.json b/src/main/resources/assets/textile_backup/lang/en_us.json
new file mode 100644
index 0000000..779b4d7
--- /dev/null
+++ b/src/main/resources/assets/textile_backup/lang/en_us.json
@@ -0,0 +1,49 @@
+{
+ "text.autoconfig.textile_backup.title": "Textile Backup Configuration",
+
+ "text.autoconfig.textile_backup.category.default": "General",
+ "text.autoconfig.textile_backup.category.Create": "Backup settings",
+ "text.autoconfig.textile_backup.category.Restore": "Restore",
+ "text.autoconfig.textile_backup.category.Manage": "Management",
+
+ "text.autoconfig.textile_backup.option.backupInterval": "Backup Interval",
+ "text.autoconfig.textile_backup.option.backupInterval.@Tooltip": "AAAAAA",
+
+ "text.autoconfig.textile_backup.option.restoreDelay": "Restore Delay",
+
+ "text.autoconfig.textile_backup.option.doBackupsOnEmptyServer": "Do backups on empty server",
+
+ "text.autoconfig.textile_backup.option.shutdownBackup": "Make a backup on shutdown",
+
+ "text.autoconfig.textile_backup.option.backupOldWorlds": "Backup old worlds",
+
+ "text.autoconfig.textile_backup.option.perWorldBackup": "Use separate folders for different worlds",
+
+ "text.autoconfig.textile_backup.option.path": "Path to backup folder",
+
+ "text.autoconfig.textile_backup.option.fileBlacklist": "Blacklised files",
+
+ "text.autoconfig.textile_backup.option.deleteOldBackupAfterRestore": "Delete restored backup",
+
+ "text.autoconfig.textile_backup.option.backupsToKeep": "Number of backups to keep",
+
+ "text.autoconfig.textile_backup.option.maxAge": "Max age of backup",
+
+ "text.autoconfig.textile_backup.option.maxSize": "Max size of backup folder",
+
+ "text.autoconfig.textile_backup.option.compression": "Compression level (Zip only)",
+
+ "text.autoconfig.textile_backup.option.compressionCoreCountLimit": "Max number of cores used for compression",
+
+ "text.autoconfig.textile_backup.option.format": "Archive and compression format",
+
+ "text.autoconfig.textile_backup.option.permissionLevel": "Min permission level required to run any command",
+
+ "text.autoconfig.textile_backup.option.alwaysSingleplayerAllowed": "Always allow on sigle-player",
+
+ "text.autoconfig.textile_backup.option.playerWhitelist": "Admin Whitelist",
+
+ "text.autoconfig.textile_backup.option.playerBlacklist": "Admin Blacklist",
+
+ "text.autoconfig.textile_backup.option.dateTimeFormat": "Date&Time format"
+}
\ No newline at end of file
diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json
index d7e5138..0af516a 100644
--- a/src/main/resources/fabric.mod.json
+++ b/src/main/resources/fabric.mod.json
@@ -27,6 +27,9 @@
"entrypoints": {
"main": [
"net.szum123321.textile_backup.TextileBackup"
+ ],
+ "modmenu": [
+ "net.szum123321.textile_backup.client.ModMenuEntry"
]
},
"mixins": [