Skip to content

Commit 8b734f6

Browse files
committed
Add archive and dialog configuration commands for PackCore
1 parent d0dea3a commit 8b734f6

File tree

13 files changed

+930
-4
lines changed

13 files changed

+930
-4
lines changed

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ loader_version=0.16.14
1010
loom_version=1.10-SNAPSHOT
1111

1212
# Mod Properties
13-
mod_version=2.0.0-1.21.5-fabric
13+
mod_version=2.1.0-1.21.5-fabric
1414
maven_group=com.kd_gaming1
1515
archives_base_name=packcore
1616

src/main/java/com/kd_gaming1/PackCore.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.kd_gaming1;
22

3+
import com.kd_gaming1.commands.PackCoreCommands;
34
import com.kd_gaming1.screen.SEMainMenu;
45
import net.fabricmc.api.ModInitializer;
56
import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents;
@@ -13,7 +14,7 @@ public class PackCore implements ModInitializer {
1314

1415
@Override
1516
public void onInitialize() {
16-
LOGGER.info("Hello Fabric world!");
17+
PackCoreCommands.registerCommands();
1718

1819
// Register screen event to replace the main menu after initialization
1920
ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> {
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
package com.kd_gaming1.commands;
2+
3+
import com.kd_gaming1.copysystem.ZipArchiver;
4+
import com.mojang.brigadier.CommandDispatcher;
5+
import com.mojang.brigadier.arguments.StringArgumentType;
6+
import com.mojang.brigadier.context.CommandContext;
7+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
8+
import net.fabricmc.loader.api.FabricLoader;
9+
import net.minecraft.server.command.CommandManager;
10+
import net.minecraft.server.command.ServerCommandSource;
11+
import net.minecraft.text.Text;
12+
13+
import java.io.File;
14+
import java.nio.file.Path;
15+
import java.util.ArrayList;
16+
import java.util.List;
17+
import java.util.concurrent.CompletableFuture;
18+
19+
/**
20+
* Command to create ZIP archives of selected Minecraft files and folders.
21+
* Usage: /packcore archive <preset|folder_name> [filename]
22+
* Presets: vanilla-configs, mod-configs, all-configs
23+
*/
24+
public class ArchiveCommand {
25+
26+
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
27+
dispatcher.register(CommandManager.literal("packcore")
28+
.then(CommandManager.literal("archive")
29+
.then(CommandManager.argument("target", StringArgumentType.word())
30+
.suggests((context, builder) -> {
31+
// Auto-complete suggestions for presets
32+
String[] presets = {"vanilla-configs", "mod-configs", "all-configs"};
33+
for (String preset : presets) {
34+
builder.suggest(preset);
35+
}
36+
// Could also suggest common folder names
37+
String[] commonFolders = {"config", "resourcepacks", "shaderpacks", "screenshots"};
38+
for (String folder : commonFolders) {
39+
builder.suggest(folder);
40+
}
41+
return builder.buildFuture();
42+
})
43+
.executes(context -> executeArchive(context, null))
44+
.then(CommandManager.argument("filename", StringArgumentType.greedyString())
45+
.executes(context -> executeArchive(context,
46+
StringArgumentType.getString(context, "filename")))))));
47+
}
48+
49+
private static int executeArchive(CommandContext<ServerCommandSource> context, String customFilename)
50+
throws CommandSyntaxException {
51+
52+
String target = StringArgumentType.getString(context, "target");
53+
ServerCommandSource source = context.getSource();
54+
55+
// Send initial message
56+
source.sendFeedback(() -> Text.literal("§6Starting archive creation for: §e" + target), false);
57+
58+
// Run archive creation asynchronously to avoid blocking the game thread
59+
CompletableFuture.runAsync(() -> {
60+
try {
61+
createArchive(source, target, customFilename);
62+
} catch (Exception e) {
63+
source.sendFeedback(() -> Text.literal("§cError creating archive: " + e.getMessage()), false);
64+
e.printStackTrace();
65+
}
66+
});
67+
68+
return 1;
69+
}
70+
71+
private static void createArchive(ServerCommandSource source, String target, String customFilename) {
72+
File minecraftRoot = FabricLoader.getInstance().getGameDir().toFile();
73+
File skyblockFolder = new File(minecraftRoot, "Skyblock Enhanced");
74+
File customConfigFolder = new File(skyblockFolder, "CustomConfigs");
75+
76+
// Ensure CustomConfigs folder exists
77+
if (!customConfigFolder.exists()) {
78+
customConfigFolder.mkdirs();
79+
}
80+
81+
// Generate filename if not provided
82+
String filename = customFilename != null ? customFilename : generateFilename(target);
83+
if (!filename.endsWith(".zip")) {
84+
filename += ".zip";
85+
}
86+
87+
// Get paths based on target (preset or folder name)
88+
List<Path> pathsToArchive = getPathsForTarget(target, minecraftRoot, source);
89+
90+
if (pathsToArchive.isEmpty()) {
91+
source.sendFeedback(() -> Text.literal("§cNo valid paths found for: " + target), false);
92+
return;
93+
}
94+
95+
// Create the archive
96+
source.sendFeedback(() -> Text.literal("§6Creating archive with " + pathsToArchive.size() + " items..."), false);
97+
98+
boolean success = ZipArchiver.createZipArchive(
99+
filename,
100+
customConfigFolder.getAbsolutePath(),
101+
pathsToArchive,
102+
minecraftRoot,
103+
new ZipArchiver.ArchiveProgressListener() {
104+
private int lastReportedProgress = 0;
105+
106+
@Override
107+
public void onProgress(int percentComplete) {
108+
// Report progress every 20%
109+
if (percentComplete >= lastReportedProgress + 20) {
110+
lastReportedProgress = percentComplete;
111+
source.sendFeedback(() -> Text.literal("§6Archive progress: §e" + percentComplete + "%"), false);
112+
}
113+
}
114+
}
115+
);
116+
117+
if (success) {
118+
String finalFilename = filename;
119+
source.sendFeedback(() -> Text.literal("§aArchive created successfully: §f" + finalFilename), false);
120+
source.sendFeedback(() -> Text.literal("§aLocation: §f" + customConfigFolder.getAbsolutePath()), false);
121+
} else {
122+
source.sendFeedback(() -> Text.literal("§cFailed to create archive. Check console for errors."), false);
123+
}
124+
}
125+
126+
private static List<Path> getPathsForTarget(String target, File minecraftRoot, ServerCommandSource source) {
127+
List<Path> paths = new ArrayList<>();
128+
Path rootPath = minecraftRoot.toPath();
129+
130+
switch (target.toLowerCase()) {
131+
case "vanilla-configs":
132+
// Vanilla Minecraft configuration files
133+
addIfExists(paths, rootPath.resolve("options.txt"), source);
134+
addIfExists(paths, rootPath.resolve("servers.dat"), source);
135+
break;
136+
137+
case "mod-configs":
138+
// Only the config folder (mod configurations)
139+
addIfExists(paths, rootPath.resolve("config"), source);
140+
break;
141+
142+
case "all-configs":
143+
// Both vanilla and mod configs
144+
addIfExists(paths, rootPath.resolve("options.txt"), source);
145+
addIfExists(paths, rootPath.resolve("servers.dat"), source);
146+
addIfExists(paths, rootPath.resolve("config"), source);
147+
break;
148+
149+
default:
150+
// Treat as folder name
151+
Path targetPath = rootPath.resolve(target);
152+
if (targetPath.toFile().exists()) {
153+
paths.add(targetPath);
154+
source.sendFeedback(() -> Text.literal("§6Found folder: §e" + target), false);
155+
} else {
156+
source.sendFeedback(() -> Text.literal("§cFolder not found: §e" + target), false);
157+
}
158+
break;
159+
}
160+
161+
return paths;
162+
}
163+
164+
private static void addIfExists(List<Path> paths, Path path, ServerCommandSource source) {
165+
if (path.toFile().exists()) {
166+
paths.add(path);
167+
source.sendFeedback(() -> Text.literal("§6Found: §e" + path.getFileName()), false);
168+
} else {
169+
source.sendFeedback(() -> Text.literal("§7Skipped (not found): §e" + path.getFileName()), false);
170+
}
171+
}
172+
173+
private static String generateFilename(String target) {
174+
String timestamp = String.valueOf(System.currentTimeMillis());
175+
return target.replace("-", "_") + "_backup_" + timestamp;
176+
}
177+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.kd_gaming1.commands;
2+
3+
import com.kd_gaming1.config.ModConfig;
4+
import com.mojang.brigadier.CommandDispatcher;
5+
import com.mojang.brigadier.arguments.BoolArgumentType;
6+
import com.mojang.brigadier.context.CommandContext;
7+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
8+
import net.minecraft.server.command.CommandManager;
9+
import net.minecraft.server.command.ServerCommandSource;
10+
import net.minecraft.text.Text;
11+
12+
/**
13+
* Command to configure the dialog window settings.
14+
* Usage: /packcore dialog <true|false>
15+
*/
16+
public class DialogConfigCommand {
17+
18+
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
19+
dispatcher.register(CommandManager.literal("packcore")
20+
.then(CommandManager.literal("dialog")
21+
.then(CommandManager.argument("enabled", BoolArgumentType.bool())
22+
.executes(DialogConfigCommand::executeDialogConfig))
23+
.executes(DialogConfigCommand::showDialogStatus)));
24+
}
25+
26+
private static int executeDialogConfig(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
27+
boolean enabled = BoolArgumentType.getBool(context, "enabled");
28+
ServerCommandSource source = context.getSource();
29+
30+
// Update the config
31+
ModConfig.setPromptSetDefaultConfig(enabled);
32+
33+
// Send feedback
34+
String status = enabled ? "§aenabled" : "§cdisabled";
35+
source.sendFeedback(() -> Text.literal("§6Dialog window has been " + status + "§6."), false);
36+
37+
if (enabled) {
38+
source.sendFeedback(() -> Text.literal("§7The selection dialog will now appear on next startup if multiple config files are found."), false);
39+
} else {
40+
source.sendFeedback(() -> Text.literal("§7The selection dialog will be skipped and auto-extract single configs."), false);
41+
}
42+
43+
return 1;
44+
}
45+
46+
private static int showDialogStatus(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
47+
ServerCommandSource source = context.getSource();
48+
boolean currentStatus = ModConfig.getPromptSetDefaultConfig();
49+
50+
String status = currentStatus ? "§aenabled" : "§cdisabled";
51+
source.sendFeedback(() -> Text.literal("§6Dialog window is currently " + status + "§6."), false);
52+
source.sendFeedback(() -> Text.literal("§7Use §f/packcore dialog <true|false> §7to change this setting."), false);
53+
54+
return 1;
55+
}
56+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.kd_gaming1.commands;
2+
3+
import com.mojang.brigadier.CommandDispatcher;
4+
import com.mojang.brigadier.context.CommandContext;
5+
import com.mojang.brigadier.exceptions.CommandSyntaxException;
6+
import net.minecraft.server.command.CommandManager;
7+
import net.minecraft.server.command.ServerCommandSource;
8+
import net.minecraft.text.Text;
9+
10+
/**
11+
* Help command for PackCore.
12+
* Usage: /packcore help
13+
*/
14+
public class HelpCommand {
15+
16+
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
17+
dispatcher.register(CommandManager.literal("packcore")
18+
.executes(HelpCommand::executeHelp)
19+
.then(CommandManager.literal("help")
20+
.executes(HelpCommand::executeHelp)));
21+
}
22+
23+
private static int executeHelp(CommandContext<ServerCommandSource> context) throws CommandSyntaxException {
24+
ServerCommandSource source = context.getSource();
25+
26+
source.sendFeedback(() -> Text.literal("§6=== PackCore Commands ==="), false);
27+
source.sendFeedback(() -> Text.literal("§e/packcore §7- Show this help"), false);
28+
source.sendFeedback(() -> Text.literal("§e/packcore archive <target> [filename]"), false);
29+
source.sendFeedback(() -> Text.literal(" §7Archive presets:"), false);
30+
source.sendFeedback(() -> Text.literal(" §f- options §7(options.txt, servers.dat)"), false);
31+
source.sendFeedback(() -> Text.literal(" §f- vanilla-configs §7(all vanilla MC configs)"), false);
32+
source.sendFeedback(() -> Text.literal(" §f- mod-configs §7(config folder only)"), false);
33+
source.sendFeedback(() -> Text.literal(" §f- all-configs §7(vanilla + mod configs)"), false);
34+
source.sendFeedback(() -> Text.literal(" §7Or specify any folder name"), false);
35+
source.sendFeedback(() -> Text.literal(""), false);
36+
source.sendFeedback(() -> Text.literal("§e/packcore dialog [true|false]"), false);
37+
source.sendFeedback(() -> Text.literal(" §7Enable/disable the config selection dialog"), false);
38+
source.sendFeedback(() -> Text.literal(""), false);
39+
source.sendFeedback(() -> Text.literal("§7Archives are saved to: §fSkyblock Enhanced/CustomConfigs/"), false);
40+
41+
return 1;
42+
}
43+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.kd_gaming1.commands;
2+
3+
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
4+
5+
/**
6+
* Registers all PackCore commands with the Fabric command system.
7+
*/
8+
public class PackCoreCommands {
9+
10+
public static void registerCommands() {
11+
CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> {
12+
HelpCommand.register(dispatcher);
13+
ArchiveCommand.register(dispatcher);
14+
DialogConfigCommand.register(dispatcher);
15+
});
16+
}
17+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.kd_gaming1.copysystem;
2+
3+
import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint;
4+
import net.fabricmc.loader.api.FabricLoader;
5+
import com.kd_gaming1.copysystem.ZipSelectionDialog;
6+
import java.io.File;
7+
8+
public class PreLaunchInitializer implements PreLaunchEntrypoint {
9+
@Override
10+
public void onPreLaunch() {
11+
// Get Minecraft root directory
12+
File minecraftRoot = FabricLoader.getInstance().getGameDir().toFile();
13+
14+
// Show the dialog and wait for user selection
15+
ZipSelectionDialog.showDialog(minecraftRoot);
16+
17+
System.out.println("Configuration selection completed, continuing with Minecraft startup...");
18+
}
19+
}

0 commit comments

Comments
 (0)