summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java (renamed from src/main/java/com/keuin/kbackupfabric/KBRegister.java)6
-rw-r--r--src/main/java/com/keuin/kbackupfabric/KBCommands.java4
-rw-r--r--src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java17
-rw-r--r--src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java75
5 files changed, 91 insertions, 12 deletions
diff --git a/README.md b/README.md
index 3125323..5536dbb 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,6 @@ commands:
To-Do List:
-- Add backup name completion.
- Optimize the backup name output. (add datetime output automatically, name is essential and is separated from the datetime)
- More thorough test.
- Enhance ZipUtil for hashing sub-files and generating incremental diff-table (A:Add, M:Modification, D:Deletion)
diff --git a/src/main/java/com/keuin/kbackupfabric/KBRegister.java b/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java
index 11f05a1..ec67a64 100644
--- a/src/main/java/com/keuin/kbackupfabric/KBRegister.java
+++ b/src/main/java/com/keuin/kbackupfabric/KBCommandRegister.java
@@ -1,15 +1,17 @@
package com.keuin.kbackupfabric;
+import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider;
import com.keuin.kbackupfabric.util.PermissionValidator;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.StringArgumentType;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
-public final class KBRegister {
+public final class KBCommandRegister {
// First make method to register
public static void registerCommands(CommandDispatcher<ServerCommandSource> dispatcher) {
// register /kb and /kb help for help menu
+
dispatcher.register(CommandManager.literal("kb").executes(KBCommands::help));
dispatcher.register(CommandManager.literal("kb").then(CommandManager.literal("help").executes(KBCommands::help)));
@@ -20,7 +22,7 @@ public final class KBRegister {
dispatcher.register(CommandManager.literal("kb").then(CommandManager.literal("backup").then(CommandManager.argument("backupName", StringArgumentType.string()).requires(PermissionValidator::op).executes(KBCommands::backup)).requires(PermissionValidator::op).executes(KBCommands::backupWithDefaultName)));
// register /kb restore <name> for performing restore. OP is required.
- dispatcher.register(CommandManager.literal("kb").then(CommandManager.literal("restore").then(CommandManager.argument("backupName", StringArgumentType.string()).requires(PermissionValidator::op).executes(KBCommands::restore)).executes(KBCommands::list)));
+ dispatcher.register(CommandManager.literal("kb").then(CommandManager.literal("restore").then(CommandManager.argument("backupName", StringArgumentType.string()).suggests(BackupNameSuggestionProvider.getSuggestionProvider()).requires(PermissionValidator::op).executes(KBCommands::restore)).executes(KBCommands::list)));
// register /kb confirm for confirming the execution. OP is required.
dispatcher.register(CommandManager.literal("kb").then(CommandManager.literal("confirm").requires(PermissionValidator::op).executes(KBCommands::confirm)));
diff --git a/src/main/java/com/keuin/kbackupfabric/KBCommands.java b/src/main/java/com/keuin/kbackupfabric/KBCommands.java
index c636a0d..b932c80 100644
--- a/src/main/java/com/keuin/kbackupfabric/KBCommands.java
+++ b/src/main/java/com/keuin/kbackupfabric/KBCommands.java
@@ -111,7 +111,7 @@ public final class KBCommands {
// Update confirm pending variable
restoreBackupNameToBeConfirmed = backupName;
- msgWarn(context, String.format("WARNING: You will LOST YOUR CURRENT WORLD COMPLETELY! It will be replaced with the backup %s . Please use /kb confirm to proceed executing.", restoreBackupNameToBeConfirmed), true);
+ msgWarn(context, String.format("WARNING: You will LOSE YOUR CURRENT WORLD PERMANENTLY! The worlds will be replaced with backup %s . Use /kb confirm to start or /kb cancel to abort.", restoreBackupNameToBeConfirmed), true);
return SUCCESS;
}
@@ -124,7 +124,7 @@ public final class KBCommands {
*/
public static int backupWithDefaultName(CommandContext<ServerCommandSource> context) {
//KBMain.backup("name")
- DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss");
String timeString = LocalDateTime.now().format(formatter);
return doBackup(context, timeString);
}
diff --git a/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java b/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java
index 4f0f1ff..a1ffcad 100644
--- a/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java
+++ b/src/main/java/com/keuin/kbackupfabric/KBPluginEvents.java
@@ -1,6 +1,8 @@
package com.keuin.kbackupfabric;
import com.keuin.kbackupfabric.data.BackupMetadata;
+import com.keuin.kbackupfabric.util.BackupFilesystemUtil;
+import com.keuin.kbackupfabric.util.BackupNameSuggestionProvider;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.server.ServerStartCallback;
import net.fabricmc.fabric.api.registry.CommandRegistry;
@@ -24,18 +26,19 @@ import static org.apache.commons.io.FileUtils.forceDelete;
public final class KBPluginEvents implements ModInitializer, ServerStartCallback {
@Override
public void onInitialize() {
- System.out.println("Initializing KBackup...");
- CommandRegistry.INSTANCE.register(false, KBRegister::registerCommands);
+ System.out.println("KBackup: Binding events and commands ...");
+ CommandRegistry.INSTANCE.register(false, KBCommandRegister::registerCommands);
ServerStartCallback.EVENT.register(this);
}
@Override
public void onStartServer(MinecraftServer server) {
- // When the server starts, we check if we have just recovered from a backup.
- // If so, then we print some message.
- debug("KBackup onStartServer");
- // TODO:
- // Check
+ debug("KBackup: Initializing ...");
+
+ // Update backup suggestion list
+ BackupNameSuggestionProvider.setBackupSaveDirectory(BackupFilesystemUtil.getBackupSaveDirectory(server).getPath());
+
+ // Check if we have just recovered from a previous backup. If so, print message.
try {
File levelDirectory = new File(server.getRunDirectory(), server.getLevelName());
File metadataFile = new File(levelDirectory, BackupMetadata.metadataFileName);
diff --git a/src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java b/src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java
new file mode 100644
index 0000000..08e12b2
--- /dev/null
+++ b/src/main/java/com/keuin/kbackupfabric/util/BackupNameSuggestionProvider.java
@@ -0,0 +1,75 @@
+package com.keuin.kbackupfabric.util;
+
+import com.mojang.brigadier.suggestion.SuggestionProvider;
+import com.mojang.brigadier.suggestion.Suggestions;
+import com.mojang.brigadier.suggestion.SuggestionsBuilder;
+import net.minecraft.server.command.ServerCommandSource;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.concurrent.CompletableFuture;
+
+public class BackupNameSuggestionProvider {
+ private static final List<String> candidateCacheList = new ArrayList<>();
+ private static final Object syncSetDirectory = new Object();
+ private static final Object syncUpdate = new Object();
+ private static final long CACHE_TTL = 10000;
+ private static String backupSaveDirectory;
+ private static long cacheUpdateTime = 0;
+
+ public static void setBackupSaveDirectory(String backupSaveDirectory) {
+ synchronized (syncSetDirectory) {
+ BackupNameSuggestionProvider.backupSaveDirectory = backupSaveDirectory;
+ }
+ // Immediately perform a update
+ updateCandidateList();
+ }
+
+ public static void updateCandidateList() {
+ synchronized (syncUpdate) {
+ try {
+ File file = new File(backupSaveDirectory);
+ candidateCacheList.clear();
+ File[] files = file.listFiles();
+ if (files == null)
+ return;
+ for (File f : files)
+ candidateCacheList.add(BackupFilesystemUtil.getBackupName(f.getName()));
+ cacheUpdateTime = System.currentTimeMillis();
+ } catch (NullPointerException ignored) {
+ }
+ }
+ }
+
+// private static void updateCandidateList(Collection<String> stringCollection) {
+// candidateList.clear();
+// candidateList.addAll(stringCollection);
+// }
+
+ public static SuggestionProvider<ServerCommandSource> getSuggestionProvider() {
+ return (context, builder) -> getCompletableFuture(builder);
+ }
+
+ private static CompletableFuture<Suggestions> getCompletableFuture(SuggestionsBuilder builder) {
+ if (isCacheExpired())
+ updateCandidateList();
+ String remaining = builder.getRemaining().toLowerCase(Locale.ROOT);
+
+ if (candidateCacheList.isEmpty()) { // If the list is empty then return no suggestions
+ return Suggestions.empty(); // No suggestions
+ }
+
+ for (String string : candidateCacheList) { // Iterate through the supplied list
+ if (string.toLowerCase(Locale.ROOT).startsWith(remaining)) {
+ builder.suggest(string); // Add every single entry to suggestions list.
+ }
+ }
+ return builder.buildFuture(); // Create the CompletableFuture containing all the suggestions
+ }
+
+ private static boolean isCacheExpired() {
+ return System.currentTimeMillis() - cacheUpdateTime > CACHE_TTL;
+ }
+}