From a8f98c460e00ad70e19e094634a4a2cc52c0cec8 Mon Sep 17 00:00:00 2001 From: szymon Date: Sat, 26 Jun 2021 13:10:35 +0200 Subject: [PATCH 01/18] Many, many changes: - I migrated from cotton config to Cloth config + Auto config, that way it's easy to provide modmenu integration while keeping backward-compatibility. Because settings might change at runtime it's now necessary to keep the config reference up-to-date. I done this by using wrapper class around ConfigHolder<> and having a reference to main instance in each class accessing the config. - Switched form using one global logger to creating new instance in every class. - Removed BackupScheduler from Statics. Why did I put it there in the first place? --- build.gradle | 25 ++- gradle.properties | 8 + .../textile_backup/ConfigHandler.java | 154 ---------------- .../szum123321/textile_backup/Statics.java | 12 +- .../textile_backup/TextileBackup.java | 40 ++-- .../CustomLogger.java => TextileLogger.java} | 16 +- .../textile_backup/client/ModMenuEntry.java | 13 ++ .../commands/create/CleanupCommand.java | 8 +- .../commands/create/StartBackupCommand.java | 6 +- .../commands/manage/BlacklistCommand.java | 38 ++-- .../commands/manage/DeleteCommand.java | 18 +- .../commands/manage/ListBackupsCommand.java | 7 +- .../commands/manage/WhitelistCommand.java | 38 ++-- .../commands/restore/KillRestoreCommand.java | 9 +- .../restore/RestoreBackupCommand.java | 16 +- .../textile_backup/config/ConfigHelper.java | 32 ++++ .../textile_backup/config/ConfigPOJO.java | 174 ++++++++++++++++++ .../textile_backup/core/Utilities.java | 30 ++- .../core/create/BackupHelper.java | 30 +-- .../core/create/BackupScheduler.java | 12 +- .../core/create/MakeBackupRunnable.java | 32 ++-- .../compressors/AbstractCompressor.java | 29 +-- .../compressors/ParallelZipCompressor.java | 7 +- .../create/compressors/ZipCompressor.java | 7 +- .../core/restore/AwaitThread.java | 8 +- .../core/restore/RestoreBackupRunnable.java | 34 ++-- .../core/restore/RestoreHelper.java | 22 ++- .../decompressors/GenericTarDecompressor.java | 15 +- .../decompressors/ZipDecompressor.java | 15 +- .../assets/textile_backup/lang/en_us.json | 49 +++++ src/main/resources/fabric.mod.json | 3 + 31 files changed, 562 insertions(+), 345 deletions(-) delete mode 100644 src/main/java/net/szum123321/textile_backup/ConfigHandler.java rename src/main/java/net/szum123321/textile_backup/{core/CustomLogger.java => TextileLogger.java} (89%) create mode 100644 src/main/java/net/szum123321/textile_backup/client/ModMenuEntry.java create mode 100644 src/main/java/net/szum123321/textile_backup/config/ConfigHelper.java create mode 100644 src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java create mode 100644 src/main/resources/assets/textile_backup/lang/en_us.json 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": [ From e9f6a29eb27ca740dfbea93df029be84dccf0868 Mon Sep 17 00:00:00 2001 From: szymon Date: Tue, 6 Jul 2021 22:15:30 +0200 Subject: [PATCH 02/18] Yes! Zero changes to config file look! --- .../textile_backup/config/ConfigPOJO.java | 139 ++++++++++-------- .../assets/textile_backup/lang/en_us.json | 5 +- 2 files changed, 84 insertions(+), 60 deletions(-) diff --git a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java index 2447156..04e5035 100644 --- a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java +++ b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java @@ -30,102 +30,125 @@ 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""") + \nTime 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?") + @Comment("\nDelay in seconds between typing-in /backup restore and it actually starting\n") + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Category("Restore") + public int restoreDelay = 30; + + @Comment("\nShould backups be done even if there are no players?\n") + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Create") public boolean doBackupsOnEmptyServer = false; - @Comment("Should backup be made on server shutdown?") + @Comment("\nShould backup be made on server shutdown?\n") + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Create") public boolean shutdownBackup = true; - @Comment("Should world be backed up before restoring a backup?") - @ConfigEntry.Category("Create") + @Comment("\nShould world be backed up before restoring a backup?\n") + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Category("Restore") public boolean backupOldWorlds = true; - @Comment("Compression level 0 - 9 Only affects zip compression.") + @Comment("\nShould every world have its own backup folder?\n") + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Excluded + public boolean perWorldBackup = true; + + @Comment("\nA path to the backup folder\n") + @ConfigEntry.Gui.NoTooltip() + public String path = "backup/"; + + @Comment(""" + \nThis setting allows you to exclude files form being backedup. + Be very careful when setting it, as it is easy corrupt your world! + """) + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Category("Create") + public List fileBlacklist = new ArrayList<>(); + + @Comment("\nShould backups be deleted after being restored?\n") + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Category("Restore") + 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") + @ConfigEntry.Gui.NoTooltip() + 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") + @ConfigEntry.Gui.NoTooltip() + public long maxAge = 0; + + @Comment(""" + \nMaximum size of backup folder in kilo bytes (1024). + If set to 0 then backups will not be deleted + """) + @ConfigEntry.Gui.NoTooltip() + public int maxSize = 0; + + @Comment("\nCompression level \n0 - 9\n Only affects zip compression.\n") + @ConfigEntry.Gui.NoTooltip() @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""") + \nLimit how many cores can be used for compression. + 0 means that all available cores will be used + """) + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Create") public int compressionCoreCountLimit = 0; - @Comment(value = """ - Available formats are: + @Comment(""" + \nAvailable 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""") + TAR - .tar with no compression + """) + @ConfigEntry.Gui.NoTooltip() @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") + @Comment("\nMinimal permission level required to run commands\n") @ConfigEntry.Category("Manage") + @ConfigEntry.Gui.NoTooltip() 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.""") + @Comment("\nPlayer on singleplayer is always allowed to run command. Warning! On lan party everyone will be allowed to run it.\n") + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Manage") public boolean alwaysSingleplayerAllowed = true; - @Comment("Players allowed to run backup commands without sufficient permission level") + @Comment("\nPlayers allowed to run backup commands without sufficient permission level\n") + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Manage") - public Set playerWhitelist = new HashSet<>(); + public List playerWhitelist = new ArrayList<>(); - @Comment("Players banned from running backup commands besides their sufficient permission level") + @Comment("\nPlayers banned from running backup commands besides their sufficient permission level\n") + @ConfigEntry.Gui.NoTooltip() @ConfigEntry.Category("Manage") - public Set playerBlacklist = new HashSet<>(); + public List playerBlacklist = new ArrayList<>(); - @Comment("Delay in seconds between typing-in /backup restore and it actually starting") - @ConfigEntry.Category("Restore") - public int restoreDelay = 30; + @Comment(""" + \nFormat 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 + """) + @ConfigEntry.Gui.Tooltip() + public String dateTimeFormat = "yyyy.MM.dd_HH-mm-ss"; @Override public void validatePostLoad() throws ValidationException { diff --git a/src/main/resources/assets/textile_backup/lang/en_us.json b/src/main/resources/assets/textile_backup/lang/en_us.json index 779b4d7..3ae07fe 100644 --- a/src/main/resources/assets/textile_backup/lang/en_us.json +++ b/src/main/resources/assets/textile_backup/lang/en_us.json @@ -7,7 +7,7 @@ "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.backupInterval.@Tooltip": "Time between each automatic backup (in seconds)", "text.autoconfig.textile_backup.option.restoreDelay": "Restore Delay", @@ -45,5 +45,6 @@ "text.autoconfig.textile_backup.option.playerBlacklist": "Admin Blacklist", - "text.autoconfig.textile_backup.option.dateTimeFormat": "Date&Time format" + "text.autoconfig.textile_backup.option.dateTimeFormat": "Date&Time format", + "text.autoconfig.textile_backup.option.dateTimeFormat.@Tooltip": "See: https://github.com/Szum123321/textile_backup/wiki/Date-time-format" } \ No newline at end of file From cdd2b78c43334f85badb1e1a13496405095b7daf Mon Sep 17 00:00:00 2001 From: szymon Date: Tue, 6 Jul 2021 22:33:00 +0200 Subject: [PATCH 03/18] getMinecraftServer was renamed to getServer Also updated to mc 1.17.1 --- gradle.properties | 8 ++++---- .../java/net/szum123321/textile_backup/TextileBackup.java | 2 +- .../textile_backup/commands/FileSuggestionProvider.java | 3 +-- .../textile_backup/commands/create/CleanupCommand.java | 2 +- .../textile_backup/commands/manage/BlacklistCommand.java | 4 ++-- .../textile_backup/commands/manage/DeleteCommand.java | 2 +- .../commands/manage/ListBackupsCommand.java | 2 +- .../textile_backup/commands/manage/WhitelistCommand.java | 4 ++-- .../commands/restore/RestoreBackupCommand.java | 2 +- .../textile_backup/core/create/BackupContext.java | 3 +-- .../textile_backup/core/restore/RestoreContext.java | 2 +- 11 files changed, 16 insertions(+), 18 deletions(-) diff --git a/gradle.properties b/gradle.properties index 0aa132a..6b00a4c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,12 +1,12 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx1G -minecraft_version=1.17 -yarn_mappings=1.17+build.10 -loader_version=0.11.5 +minecraft_version=1.17.1 +yarn_mappings=1.17.1+build.1 +loader_version=0.11.6 #Fabric api -fabric_version=0.35.1+1.17 +fabric_version=0.36.1+1.17 #Cloth Config cloth_version=5.0.34 diff --git a/src/main/java/net/szum123321/textile_backup/TextileBackup.java b/src/main/java/net/szum123321/textile_backup/TextileBackup.java index a638dda..1434d93 100644 --- a/src/main/java/net/szum123321/textile_backup/TextileBackup.java +++ b/src/main/java/net/szum123321/textile_backup/TextileBackup.java @@ -98,7 +98,7 @@ public class TextileBackup implements ModInitializer { return ((config.get().playerWhitelist.contains(ctx.getEntityOrThrow().getEntityName()) || ctx.hasPermissionLevel(config.get().permissionLevel)) && !config.get().playerBlacklist.contains(ctx.getEntityOrThrow().getEntityName())) || - (ctx.getMinecraftServer().isSinglePlayer() && + (ctx.getServer().isSinglePlayer() && config.get().alwaysSingleplayerAllowed); } catch (Exception ignored) { //Command was called from server console. return true; diff --git a/src/main/java/net/szum123321/textile_backup/commands/FileSuggestionProvider.java b/src/main/java/net/szum123321/textile_backup/commands/FileSuggestionProvider.java index eb2534f..99d3d57 100644 --- a/src/main/java/net/szum123321/textile_backup/commands/FileSuggestionProvider.java +++ b/src/main/java/net/szum123321/textile_backup/commands/FileSuggestionProvider.java @@ -28,7 +28,6 @@ import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.command.ServerCommandSource; import net.szum123321.textile_backup.Statics; import net.szum123321.textile_backup.core.restore.RestoreHelper; -import org.lwjgl.system.CallbackI; import java.util.concurrent.CompletableFuture; @@ -43,7 +42,7 @@ public final class FileSuggestionProvider implements SuggestionProvider getSuggestions(CommandContext ctx, SuggestionsBuilder builder) throws CommandSyntaxException { String remaining = builder.getRemaining(); - for (RestoreHelper.RestoreableFile file : RestoreHelper.getAvailableBackups(ctx.getSource().getMinecraftServer())) { + for (RestoreHelper.RestoreableFile file : RestoreHelper.getAvailableBackups(ctx.getSource().getServer())) { String formattedCreationTime = file.getCreationTime().format(Statics.defaultDateTimeFormatter); if (formattedCreationTime.startsWith(remaining)) { 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 5e44864..4ca516f 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 @@ -38,7 +38,7 @@ public class CleanupCommand { log.sendInfo( source, "Deleted: {} files.", - BackupHelper.executeFileLimit(source, Utilities.getLevelName(source.getMinecraftServer())) + BackupHelper.executeFileLimit(source, Utilities.getLevelName(source.getServer())) ); return 1; 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 67e237c..2b0d0c2 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 @@ -73,7 +73,7 @@ public class BlacklistCommand { builder.append(" successfully."); - ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player); + ctx.getSource().getServer().getCommandManager().sendCommandTree(player); log.sendInfo(ctx.getSource(), builder.toString()); } @@ -90,7 +90,7 @@ public class BlacklistCommand { config.get().playerBlacklist.remove(player.getEntityName()); config.save(); - ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player); + ctx.getSource().getServer().getCommandManager().sendCommandTree(player); log.sendInfo(ctx.getSource(), "Player: {} removed from the blacklist successfully.", player.getEntityName()); } 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 d4a6929..d2cae78 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 @@ -57,7 +57,7 @@ public class DeleteCommand { throw CommandExceptions.DATE_TIME_PARSE_COMMAND_EXCEPTION_TYPE.create(e); } - File root = Utilities.getBackupRootPath(Utilities.getLevelName(source.getMinecraftServer())); + File root = Utilities.getBackupRootPath(Utilities.getLevelName(source.getServer())); Optional optionalFile = Arrays.stream(root.listFiles()) .filter(Utilities::isValidBackup) 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 7d609ca..42c49d9 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 @@ -33,7 +33,7 @@ public class ListBackupsCommand { public static LiteralArgumentBuilder register() { return CommandManager.literal("list") .executes(ctx -> { StringBuilder builder = new StringBuilder(); - List backups = RestoreHelper.getAvailableBackups(ctx.getSource().getMinecraftServer()); + List backups = RestoreHelper.getAvailableBackups(ctx.getSource().getServer()); if(backups.size() == 0) { builder.append("There a no backups available for this world."); 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 d7ac8d1..56d4416 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 @@ -73,7 +73,7 @@ public class WhitelistCommand { builder.append(" successfully."); - ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player); + ctx.getSource().getServer().getCommandManager().sendCommandTree(player); log.sendInfo(ctx.getSource(), builder.toString()); } @@ -90,7 +90,7 @@ public class WhitelistCommand { config.get().playerWhitelist.remove(player.getEntityName()); config.save(); - ctx.getSource().getMinecraftServer().getCommandManager().sendCommandTree(player); + ctx.getSource().getServer().getCommandManager().sendCommandTree(player); log.sendInfo(ctx.getSource(), "Player: {} removed from the whitelist successfully.", player.getEntityName()); } 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 beba511..bb516c9 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 @@ -79,7 +79,7 @@ public class RestoreBackupCommand { throw CommandExceptions.DATE_TIME_PARSE_COMMAND_EXCEPTION_TYPE.create(e); } - Optional backupFile = RestoreHelper.findFileAndLockIfPresent(dateTime, source.getMinecraftServer()); + Optional backupFile = RestoreHelper.findFileAndLockIfPresent(dateTime, source.getServer()); if(backupFile.isPresent()) { log.info("Found file to restore {}", backupFile.get().getFile().getName()); diff --git a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java index ac729bc..d8e6812 100644 --- a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java +++ b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java @@ -121,8 +121,7 @@ public record BackupContext(MinecraftServer server, } if (server == null) { - if (commandSource != null) - setServer(commandSource.getMinecraftServer()); + if (commandSource != null) setServer(commandSource.getServer()); else throw new RuntimeException("Both MinecraftServer and ServerCommandSource weren't provided!"); } diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java index a3719bd..a94236d 100644 --- a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java +++ b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java @@ -92,7 +92,7 @@ public record RestoreContext(RestoreHelper.RestoreableFile file, } public RestoreContext build() { - if (server == null) server = serverCommandSource.getMinecraftServer(); + if (server == null) server = serverCommandSource.getServer(); ActionInitiator initiator = serverCommandSource.getEntity() instanceof PlayerEntity ? ActionInitiator.Player : ActionInitiator.ServerConsole; From a0c7b478cbcdf5b628da17722d8cc5cbe03a6094 Mon Sep 17 00:00:00 2001 From: szymon Date: Wed, 7 Jul 2021 14:21:22 +0200 Subject: [PATCH 04/18] Added missing save command --- .../textile_backup/commands/manage/BlacklistCommand.java | 1 + .../textile_backup/commands/manage/WhitelistCommand.java | 1 + 2 files changed, 2 insertions(+) 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 2b0d0c2..f7c1669 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 @@ -68,6 +68,7 @@ public class BlacklistCommand { if(config.get().playerWhitelist.contains(player.getEntityName())){ config.get().playerWhitelist.remove(player.getEntityName()); + config.save(); builder.append(" and removed form the whitelist"); } 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 56d4416..1ba5eae 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 @@ -68,6 +68,7 @@ public class WhitelistCommand { if(config.get().playerBlacklist.contains(player.getEntityName())){ config.get().playerBlacklist.remove(player.getEntityName()); + config.save(); builder.append(" and removed form the blacklist"); } From 8858bd498bf49f59a76f058132899a18a5ea0f87 Mon Sep 17 00:00:00 2001 From: szymon Date: Wed, 7 Jul 2021 14:21:49 +0200 Subject: [PATCH 05/18] Use stream instead of for loop --- .../java/net/szum123321/textile_backup/core/Utilities.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 68ba125..6131490 100644 --- a/src/main/java/net/szum123321/textile_backup/core/Utilities.java +++ b/src/main/java/net/szum123321/textile_backup/core/Utilities.java @@ -92,9 +92,7 @@ public class Utilities { if (path.getFileName().toString().equals("session.lock")) return true; } - for(String i : config.get().fileBlacklist) if(path.startsWith(i)) return true; - - return false; + return config.get().fileBlacklist.stream().anyMatch(path::startsWith); } public static Optional getArchiveExtension(String fileName) { From 47f8c5cbc32cdf10579d03c4d128211ba9c834e8 Mon Sep 17 00:00:00 2001 From: szymon Date: Wed, 7 Jul 2021 14:23:54 +0200 Subject: [PATCH 06/18] Style correction, removed unnecessary constructors from records --- .../textile_backup/core/create/BackupContext.java | 12 +++--------- .../textile_backup/core/create/BackupHelper.java | 5 ++--- .../core/create/compressors/AbstractCompressor.java | 11 ++++++----- .../core/restore/RestoreBackupRunnable.java | 3 +-- .../textile_backup/core/restore/RestoreContext.java | 10 ++-------- 5 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java index d8e6812..3455c4d 100644 --- a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java +++ b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java @@ -24,17 +24,11 @@ import net.minecraft.server.command.ServerCommandSource; import net.szum123321.textile_backup.core.ActionInitiator; import org.jetbrains.annotations.NotNull; -public record BackupContext(MinecraftServer server, +public record BackupContext(@NotNull MinecraftServer server, ServerCommandSource commandSource, - ActionInitiator initiator, boolean save, + ActionInitiator initiator, + boolean save, String comment) { - public BackupContext(@NotNull MinecraftServer server, ServerCommandSource commandSource, @NotNull ActionInitiator 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; 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 7d643e6..d06ac61 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 @@ -52,11 +52,10 @@ public class BackupHelper { builder.append(ctx.getInitiator().getPrefix()); - if(ctx.startedByPlayer()) { + if(ctx.startedByPlayer()) builder.append(ctx.getCommandSource().getDisplayName().getString()); - } else { + else builder.append(ctx.getInitiator().getName()); - } builder.append(" on: "); builder.append(Utilities.getDateTimeFormatter().format(LocalDateTime.now())); 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 105a317..63498ed 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 @@ -60,11 +60,12 @@ public abstract class AbstractCompressor { finish(arc); } catch(NoSpaceLeftOnDeviceException 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); + log.error(""" + CRITICAL ERROR OCCURRED! + The backup is corrupted.; + Don't panic! This is a known issue! + For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems + In case this isn't it here's also the exception itself!""", e); if(ctx.getInitiator() == ActionInitiator.Player) { log.sendError(ctx, "Backup failed. The file is corrupt."); 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 33ab6d2..171bb55 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 @@ -82,8 +82,7 @@ public class RestoreBackupRunnable implements Runnable { if(config.get().deleteOldBackupAfterRestore) { log.info("Deleting old backup"); - if(!ctx.getFile().getFile().delete()) - log.info("Something went wrong while deleting old backup"); + if(!ctx.getFile().getFile().delete()) log.info("Something went wrong while deleting old backup"); } //in case we're playing on client diff --git a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java index a94236d..6ccc998 100644 --- a/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java +++ b/src/main/java/net/szum123321/textile_backup/core/restore/RestoreContext.java @@ -26,16 +26,10 @@ import net.szum123321.textile_backup.core.ActionInitiator; import javax.annotation.Nullable; public record RestoreContext(RestoreHelper.RestoreableFile file, - MinecraftServer server, @Nullable String comment, + MinecraftServer server, + @Nullable String comment, ActionInitiator initiator, ServerCommandSource commandSource) { - public RestoreContext(RestoreHelper.RestoreableFile file, MinecraftServer server, @Nullable String comment, ActionInitiator initiator, ServerCommandSource commandSource) { - this.file = file; - this.server = server; - this.comment = comment; - this.initiator = initiator; - this.commandSource = commandSource; - } public RestoreHelper.RestoreableFile getFile() { return file; From 585dd01c02a55b2be1af29879af36130868a0b11 Mon Sep 17 00:00:00 2001 From: szymon Date: Wed, 7 Jul 2021 14:28:51 +0200 Subject: [PATCH 07/18] Moved one perWorldBackup to the top so that General category appears on the top. I might rearrange other settings in more logical way --- .../szum123321/textile_backup/config/ConfigPOJO.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java index 04e5035..f3f755b 100644 --- a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java +++ b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java @@ -29,6 +29,11 @@ import java.util.*; @Config(name = TextileBackup.MOD_ID) public class ConfigPOJO implements ConfigData { + @Comment("\nShould every world have its own backup folder?\n") + @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Excluded + public boolean perWorldBackup = true; + @Comment(""" \nTime between automatic backups in seconds When set to 0 backups will not be performed automatically @@ -57,17 +62,12 @@ public class ConfigPOJO implements ConfigData { @ConfigEntry.Category("Restore") public boolean backupOldWorlds = true; - @Comment("\nShould every world have its own backup folder?\n") - @ConfigEntry.Gui.NoTooltip() - @ConfigEntry.Gui.Excluded - public boolean perWorldBackup = true; - @Comment("\nA path to the backup folder\n") @ConfigEntry.Gui.NoTooltip() public String path = "backup/"; @Comment(""" - \nThis setting allows you to exclude files form being backedup. + \nThis setting allows you to exclude files form being backed-up. Be very careful when setting it, as it is easy corrupt your world! """) @ConfigEntry.Gui.NoTooltip() From 121d6269cd27c1927100fb1d84bb088c0abf0448 Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 8 Jul 2021 21:45:58 +0200 Subject: [PATCH 08/18] Added missing copyright headers --- .../commands/manage/BlacklistCommand.java | 18 ++++++++++++++++++ .../commands/manage/WhitelistCommand.java | 18 ++++++++++++++++++ .../textile_backup/core/LivingServer.java | 18 ++++++++++++++++++ .../core/NoSpaceLeftOnDeviceException.java | 18 ++++++++++++++++++ .../mixin/DedicatedServerWatchdogMixin.java | 18 ++++++++++++++++++ .../mixin/MinecraftServerSessionAccessor.java | 18 ++++++++++++++++++ 6 files changed, 108 insertions(+) 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 f7c1669..5baaedd 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 @@ -1,3 +1,21 @@ +/* + * 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.commands.manage; import com.mojang.brigadier.builder.LiteralArgumentBuilder; 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 1ba5eae..c5da2f4 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 @@ -1,3 +1,21 @@ +/* + * 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.commands.manage; import com.mojang.brigadier.builder.LiteralArgumentBuilder; diff --git a/src/main/java/net/szum123321/textile_backup/core/LivingServer.java b/src/main/java/net/szum123321/textile_backup/core/LivingServer.java index 7032d12..0011d6b 100644 --- a/src/main/java/net/szum123321/textile_backup/core/LivingServer.java +++ b/src/main/java/net/szum123321/textile_backup/core/LivingServer.java @@ -1,3 +1,21 @@ +/* + * 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.core; public interface LivingServer { diff --git a/src/main/java/net/szum123321/textile_backup/core/NoSpaceLeftOnDeviceException.java b/src/main/java/net/szum123321/textile_backup/core/NoSpaceLeftOnDeviceException.java index b9158c2..3f71e4b 100644 --- a/src/main/java/net/szum123321/textile_backup/core/NoSpaceLeftOnDeviceException.java +++ b/src/main/java/net/szum123321/textile_backup/core/NoSpaceLeftOnDeviceException.java @@ -1,3 +1,21 @@ +/* + * 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.core; import java.io.IOException; diff --git a/src/main/java/net/szum123321/textile_backup/mixin/DedicatedServerWatchdogMixin.java b/src/main/java/net/szum123321/textile_backup/mixin/DedicatedServerWatchdogMixin.java index 91393b2..d6b37ac 100644 --- a/src/main/java/net/szum123321/textile_backup/mixin/DedicatedServerWatchdogMixin.java +++ b/src/main/java/net/szum123321/textile_backup/mixin/DedicatedServerWatchdogMixin.java @@ -1,3 +1,21 @@ +/* + * 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.mixin; import net.minecraft.server.dedicated.DedicatedServerWatchdog; diff --git a/src/main/java/net/szum123321/textile_backup/mixin/MinecraftServerSessionAccessor.java b/src/main/java/net/szum123321/textile_backup/mixin/MinecraftServerSessionAccessor.java index 047c1fb..91a8696 100644 --- a/src/main/java/net/szum123321/textile_backup/mixin/MinecraftServerSessionAccessor.java +++ b/src/main/java/net/szum123321/textile_backup/mixin/MinecraftServerSessionAccessor.java @@ -1,3 +1,21 @@ +/* + * 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.mixin; import net.minecraft.server.MinecraftServer; From d6430c9bef9750ccb28253051ac33e8dd63cb9ee Mon Sep 17 00:00:00 2001 From: szymon Date: Thu, 8 Jul 2021 21:46:22 +0200 Subject: [PATCH 09/18] version bump --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6b00a4c..f6d31a4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,6 @@ modmenu_version=2.0.2 lazydfu_version=0.1.2 # Mod Properties -mod_version = 2.1.0 +mod_version = 2.2.0 maven_group = net.szum123321 archives_base_name = textile_backup \ No newline at end of file From 8fe0cae73ac2af82b658f9fea2fc19c695149cb2 Mon Sep 17 00:00:00 2001 From: szymon Date: Fri, 9 Jul 2021 22:43:47 +0200 Subject: [PATCH 10/18] Added dependency info to fabric.mod.json --- src/main/resources/fabric.mod.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0af516a..0a6cb2b 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -40,8 +40,13 @@ "fabricloader": ">=0.11", "fabric": "*", "minecraft": "1.17.*", + "autoconfig1u": "*", "java": ">=16" }, + "recommends": { + "cloth-config2": "*", + "modmenu": "*" + }, "custom": { "modupdater": { From 111fe12ae78f38bb417451bee0690375024fe95e Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 21:26:11 +0200 Subject: [PATCH 11/18] Moved close to finally --- .../core/create/compressors/AbstractCompressor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 63498ed..21c19a2 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 @@ -76,9 +76,11 @@ public abstract class AbstractCompressor { } catch (Exception e) { if(ctx.getInitiator() == ActionInitiator.Player) log.sendError(ctx, "Something went wrong while compressing files!"); + } finally { + close(); } - close(); + // close(); log.sendInfoAL(ctx, "Compression took: {} seconds.", Utilities.formatDuration(Duration.between(start, Instant.now()))); } From 33f01e81899e435933fdebdb184beecb15e35949 Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 21:26:42 +0200 Subject: [PATCH 12/18] Dep update --- build.gradle | 2 +- gradle.properties | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index e2418ff..7186f2b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'fabric-loom' version '0.8-SNAPSHOT' + id 'fabric-loom' version '0.9-SNAPSHOT' id 'maven-publish' } diff --git a/gradle.properties b/gradle.properties index f6d31a4..20e75da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,18 +2,19 @@ org.gradle.jvmargs=-Xmx1G minecraft_version=1.17.1 -yarn_mappings=1.17.1+build.1 +yarn_mappings=1.17.1+build.32 loader_version=0.11.6 #Fabric api -fabric_version=0.36.1+1.17 +fabric_version=0.37.0+1.17 #Cloth Config -cloth_version=5.0.34 +cloth_version=5.0.37 #ModMenu -modmenu_version=2.0.2 +modmenu_version=2.0.4 +#Lazy DFU for faster dev start lazydfu_version=0.1.2 # Mod Properties From bf5f0469857d45b11d2dc9fccffe84499ef524b0 Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 21:27:10 +0200 Subject: [PATCH 13/18] This was stupid --- .../java/net/szum123321/textile_backup/Statics.java | 2 -- .../net/szum123321/textile_backup/TextileBackup.java | 12 ------------ .../szum123321/textile_backup/core/Utilities.java | 10 ---------- .../core/create/MakeBackupRunnable.java | 2 +- 4 files changed, 1 insertion(+), 25 deletions(-) diff --git a/src/main/java/net/szum123321/textile_backup/Statics.java b/src/main/java/net/szum123321/textile_backup/Statics.java index 3cf6d90..61c20f1 100644 --- a/src/main/java/net/szum123321/textile_backup/Statics.java +++ b/src/main/java/net/szum123321/textile_backup/Statics.java @@ -36,6 +36,4 @@ public class Statics { public static boolean disableWatchdog = false; public static AwaitThread restoreAwaitThread = null; public static Optional untouchableFile = Optional.empty(); - - public static boolean tmpAvailable; } diff --git a/src/main/java/net/szum123321/textile_backup/TextileBackup.java b/src/main/java/net/szum123321/textile_backup/TextileBackup.java index 1434d93..7cabff7 100644 --- a/src/main/java/net/szum123321/textile_backup/TextileBackup.java +++ b/src/main/java/net/szum123321/textile_backup/TextileBackup.java @@ -38,7 +38,6 @@ 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; @@ -58,17 +57,6 @@ public class TextileBackup implements ModInitializer { ConfigHelper.updateInstance(AutoConfig.register(ConfigPOJO.class, JanksonConfigSerializer::new)); - //TODO: finish writing wiki - if(config.get().format == ConfigPOJO.ArchiveFormat.ZIP) { - Statics.tmpAvailable = Utilities.isTmpAvailable(); - if(!Statics.tmpAvailable) { - 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"""); - } - } - ServerTickEvents.END_SERVER_TICK.register(new BackupScheduler()::tick); //Restart Executor Service in singleplayer 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 6131490..c999d19 100644 --- a/src/main/java/net/szum123321/textile_backup/core/Utilities.java +++ b/src/main/java/net/szum123321/textile_backup/core/Utilities.java @@ -59,16 +59,6 @@ public class Utilities { return path; } - //This is quite pointless - public static boolean isTmpAvailable() { - try { - File tmp = File.createTempFile("textile_backup_tmp_test", String.valueOf(Instant.now().getEpochSecond())); - return tmp.delete(); - } catch (IOException ignored) {} - - return false; - } - public static void disableWorldSaving(MinecraftServer server) { for (ServerWorld serverWorld : server.getWorlds()) { if (serverWorld != null && !serverWorld.savingDisabled) 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 5879060..f50f971 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 @@ -90,7 +90,7 @@ public class MakeBackupRunnable implements Runnable { switch (config.get().format) { case ZIP -> { - if (Statics.tmpAvailable && coreCount > 1) + if (coreCount > 1) ParallelZipCompressor.getInstance().createArchive(world, outFile, context, coreCount); else ZipCompressor.getInstance().createArchive(world, outFile, context, coreCount); From 76d7326237a84ec19f69d9b6827436cfd71bac02 Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 22:12:18 +0200 Subject: [PATCH 14/18] Locked parallel gzip version --- build.gradle | 4 ++-- gradle.properties | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 7186f2b..282ea69 100644 --- a/build.gradle +++ b/build.gradle @@ -51,8 +51,8 @@ dependencies { include "org.tukaani:xz:1.8" //Gzip compression, parallel, GITHUB - modImplementation 'com.github.shevek:parallelgzip:master-SNAPSHOT' - include 'com.github.shevek:parallelgzip:master-SNAPSHOT' + modImplementation "com.github.shevek:parallelgzip:${project.pgzip_commit_hash}" + include "com.github.shevek:parallelgzip:${project.pgzip_commit_hash}" // 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}") { diff --git a/gradle.properties b/gradle.properties index 20e75da..f1a6bf9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,6 +17,9 @@ modmenu_version=2.0.4 #Lazy DFU for faster dev start lazydfu_version=0.1.2 +#Hash of commit form which parallel gzip will be build +pgzip_commit_hash=af5f5c297e735f3f2df7aa4eb0e19a5810b8aff6 + # Mod Properties mod_version = 2.2.0 maven_group = net.szum123321 From 2fab8c67f38cd482aacad11fd5b5d095b47855ff Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 22:12:36 +0200 Subject: [PATCH 15/18] Repaired fabric.mod.json --- src/main/resources/fabric.mod.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 0a6cb2b..7a78961 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -40,11 +40,11 @@ "fabricloader": ">=0.11", "fabric": "*", "minecraft": "1.17.*", - "autoconfig1u": "*", + "cloth-config2": "*", "java": ">=16" }, "recommends": { - "cloth-config2": "*", + "modmenu": "*" }, From a6881b68cd24fdc905719314eb8725f6b58a019f Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 22:13:00 +0200 Subject: [PATCH 16/18] Text correction --- Copyright_Notice | 2 +- .../szum123321/textile_backup/core/create/BackupContext.java | 3 +-- .../core/create/compressors/AbstractCompressor.java | 4 ++-- src/main/resources/assets/textile_backup/lang/en_us.json | 4 ++-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Copyright_Notice b/Copyright_Notice index f6cfe9f..ca107d9 100644 --- a/Copyright_Notice +++ b/Copyright_Notice @@ -2,7 +2,7 @@ This project uses third party libraries as its dependencies and includes them in Apache Commons Compress licensed under Apache License Version 2.0 which can be found at http://www.apache.org/licenses/ Cotton config, Cotton logging, and Jankson-Fabric all by Cotton team licensed under MIT license which can be found at https://github.com/CottonMC/Cotton XZ for Java by Tukaani released as public domain. https://tukaani.org/xz/java.html - parallelgzip by shevek under Apache 2.0 http://www.apache.org/licenses/ + parallelgzip by shevek (https://github.com/shevek/parallelgzip) under Apache 2.0 http://www.apache.org/licenses/ To save on space Parallel BZip2 was unpacked Parallel BZip2 compression by Karl Gustafsson at http://at4j.sourceforge.net/ under GPL v3 diff --git a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java index 3455c4d..6ea7298 100644 --- a/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java +++ b/src/main/java/net/szum123321/textile_backup/core/create/BackupContext.java @@ -117,11 +117,10 @@ public record BackupContext(@NotNull MinecraftServer server, if (server == null) { if (commandSource != null) setServer(commandSource.getServer()); else - throw new RuntimeException("Both MinecraftServer and ServerCommandSource weren't provided!"); + throw new RuntimeException("Neither MinecraftServer or ServerCommandSource were provided!"); } return new BackupContext(server, commandSource, initiator, save, comment); } } - } 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 21c19a2..4f7aacf 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 @@ -62,10 +62,10 @@ public abstract class AbstractCompressor { } catch(NoSpaceLeftOnDeviceException e) { log.error(""" CRITICAL ERROR OCCURRED! - The backup is corrupted.; + The backup is corrupt! Don't panic! This is a known issue! For help see: https://github.com/Szum123321/textile_backup/wiki/ZIP-Problems - In case this isn't it here's also the exception itself!""", e); + In case this isn't it here's also the exception itself""", e); if(ctx.getInitiator() == ActionInitiator.Player) { log.sendError(ctx, "Backup failed. The file is corrupt."); diff --git a/src/main/resources/assets/textile_backup/lang/en_us.json b/src/main/resources/assets/textile_backup/lang/en_us.json index 3ae07fe..0dc134f 100644 --- a/src/main/resources/assets/textile_backup/lang/en_us.json +++ b/src/main/resources/assets/textile_backup/lang/en_us.json @@ -21,7 +21,7 @@ "text.autoconfig.textile_backup.option.path": "Path to backup folder", - "text.autoconfig.textile_backup.option.fileBlacklist": "Blacklised files", + "text.autoconfig.textile_backup.option.fileBlacklist": "Blacklisted files", "text.autoconfig.textile_backup.option.deleteOldBackupAfterRestore": "Delete restored backup", @@ -39,7 +39,7 @@ "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.alwaysSingleplayerAllowed": "Always allow on single-player", "text.autoconfig.textile_backup.option.playerWhitelist": "Admin Whitelist", From 50db7efe080ff5687555ae6b6bbe0f54f79911c0 Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 23:19:02 +0200 Subject: [PATCH 17/18] lang update --- .../szum123321/textile_backup/config/ConfigPOJO.java | 10 +++++----- .../resources/assets/textile_backup/lang/en_us.json | 12 +++++++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java index f3f755b..c1b17ff 100644 --- a/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java +++ b/src/main/java/net/szum123321/textile_backup/config/ConfigPOJO.java @@ -43,7 +43,7 @@ public class ConfigPOJO implements ConfigData { public long backupInterval = 3600; @Comment("\nDelay in seconds between typing-in /backup restore and it actually starting\n") - @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Category("Restore") public int restoreDelay = 30; @@ -91,11 +91,11 @@ public class ConfigPOJO implements ConfigData { \nMaximum size of backup folder in kilo bytes (1024). If set to 0 then backups will not be deleted """) - @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Tooltip() public int maxSize = 0; @Comment("\nCompression level \n0 - 9\n Only affects zip compression.\n") - @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Tooltip() @ConfigEntry.BoundedDiscrete(max = 9) @ConfigEntry.Category("Create") public int compression = 7; @@ -104,7 +104,7 @@ public class ConfigPOJO implements ConfigData { \nLimit how many cores can be used for compression. 0 means that all available cores will be used """) - @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Category("Create") public int compressionCoreCountLimit = 0; @@ -116,7 +116,7 @@ public class ConfigPOJO implements ConfigData { LZMA - tar.xz using lzma compression TAR - .tar with no compression """) - @ConfigEntry.Gui.NoTooltip() + @ConfigEntry.Gui.Tooltip() @ConfigEntry.Category("Create") @ConfigEntry.Gui.EnumHandler(option = ConfigEntry.Gui.EnumHandler.EnumDisplayOption.BUTTON) public ArchiveFormat format = ArchiveFormat.ZIP; diff --git a/src/main/resources/assets/textile_backup/lang/en_us.json b/src/main/resources/assets/textile_backup/lang/en_us.json index 0dc134f..4512982 100644 --- a/src/main/resources/assets/textile_backup/lang/en_us.json +++ b/src/main/resources/assets/textile_backup/lang/en_us.json @@ -10,8 +10,9 @@ "text.autoconfig.textile_backup.option.backupInterval.@Tooltip": "Time between each automatic backup (in seconds)", "text.autoconfig.textile_backup.option.restoreDelay": "Restore Delay", + "text.autoconfig.textile_backup.option.restoreDelay.@Tooltip": "In seconds", - "text.autoconfig.textile_backup.option.doBackupsOnEmptyServer": "Do backups on empty server", + "text.autoconfig.textile_backup.option.doBackupsOnEmptyServer": "Make automatic backups on empty server", "text.autoconfig.textile_backup.option.shutdownBackup": "Make a backup on shutdown", @@ -28,16 +29,21 @@ "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.maxAge.@Tooltip": "In seconds since creation", "text.autoconfig.textile_backup.option.maxSize": "Max size of backup folder", + "text.autoconfig.textile_backup.option.maxSize.@Tooltip": "In KBytes", - "text.autoconfig.textile_backup.option.compression": "Compression level (Zip only)", + "text.autoconfig.textile_backup.option.compression": "Compression level", + "text.autoconfig.textile_backup.option.compression.@Tooltip": "Only affects zip", "text.autoconfig.textile_backup.option.compressionCoreCountLimit": "Max number of cores used for compression", + "text.autoconfig.textile_backup.option.compressionCoreCountLimit.@Tooltip": "Set to 0 to use all available cores", "text.autoconfig.textile_backup.option.format": "Archive and compression format", + "text.autoconfig.textile_backup.option.format.@Tooltip": "See: https://github.com/Szum123321/textile_backup/wiki/Configuration#format", - "text.autoconfig.textile_backup.option.permissionLevel": "Min permission level required to run any command", + "text.autoconfig.textile_backup.option.permissionLevel": "Min permission level", "text.autoconfig.textile_backup.option.alwaysSingleplayerAllowed": "Always allow on single-player", From 5b152927f05314b924bc4cd967b7c8bd527170b8 Mon Sep 17 00:00:00 2001 From: Szum123321 Date: Tue, 3 Aug 2021 23:42:39 +0200 Subject: [PATCH 18/18] update copyright notice --- Copyright_Notice | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Copyright_Notice b/Copyright_Notice index ca107d9..f99bcc4 100644 --- a/Copyright_Notice +++ b/Copyright_Notice @@ -1,6 +1,6 @@ This project uses third party libraries as its dependencies and includes them in jar. Those are : Apache Commons Compress licensed under Apache License Version 2.0 which can be found at http://www.apache.org/licenses/ - Cotton config, Cotton logging, and Jankson-Fabric all by Cotton team licensed under MIT license which can be found at https://github.com/CottonMC/Cotton + Cloth config by Shedaniel(https://github.com/shedaniel/cloth-config) under GPL 3 XZ for Java by Tukaani released as public domain. https://tukaani.org/xz/java.html parallelgzip by shevek (https://github.com/shevek/parallelgzip) under Apache 2.0 http://www.apache.org/licenses/ @@ -9,4 +9,6 @@ To save on space Parallel BZip2 was unpacked Some code was partially or fully inspired by: Parallel zip compression: https://stackoverflow.com/questions/54624695/how-to-implement-parallel-zip-creation-with-scatterzipoutputstream-with-zip64-su - answer by: https://stackoverflow.com/users/2987755/dkb \ No newline at end of file + answer by: https://stackoverflow.com/users/2987755/dkb + + Cotton logging by Cotton team licensed under MIT license which can be found at https://github.com/CottonMC/Cotton \ No newline at end of file