aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authorPeyton Brown <81496880+PeytonBrown@users.noreply.github.com>2025-07-09 02:02:45 -0400
committerGitHub <noreply@github.com>2025-07-09 02:02:45 -0400
commitf4487214301d32790e7ea2522bfa5aadc50257c9 (patch)
treef615baf2ad2b4d57a35ab996b1aa9c9afb148d65 /src/main/java/de
parent7e260b9baf431a82401bdca1555a6d42eb4937a7 (diff)
downloadSkyblocker-f4487214301d32790e7ea2522bfa5aadc50257c9.tar.gz
Skyblocker-f4487214301d32790e7ea2522bfa5aadc50257c9.tar.bz2
Skyblocker-f4487214301d32790e7ea2522bfa5aadc50257c9.zip
Disable All Command (#1454)
* Initial Implementation * Update to not use yacl
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/hysky/skyblocker/DisableAll.java117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/main/java/de/hysky/skyblocker/DisableAll.java b/src/main/java/de/hysky/skyblocker/DisableAll.java
new file mode 100644
index 00000000..9ddf9cda
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/DisableAll.java
@@ -0,0 +1,117 @@
+package de.hysky.skyblocker;
+
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.CommandDispatcher;
+import com.mojang.brigadier.context.CommandContext;
+import com.mojang.logging.LogUtils;
+import de.hysky.skyblocker.annotations.Init;
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.utils.Constants;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.text.ClickEvent;
+import net.minecraft.text.MutableText;
+import net.minecraft.text.Text;
+import org.slf4j.Logger;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * Command helper for disabling every configurable feature.
+ */
+public class DisableAll {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ private static final String CONFIGS_PACKAGE = "de.hysky.skyblocker.config.configs";
+
+ @Init
+ public static void init() {
+ ClientCommandRegistrationCallback.EVENT.register(DisableAll::registerCommand);
+ }
+
+ private static final long CONFIRM_TIMEOUT = 30_000L; // 30 seconds
+ private static long confirmAllowedUntil;
+
+ private static void registerCommand(CommandDispatcher<FabricClientCommandSource> dispatcher, net.minecraft.command.CommandRegistryAccess registryAccess) {
+ dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE)
+ .then(ClientCommandManager.literal("disableAll")
+ .executes(DisableAll::confirmMessage)
+ .then(ClientCommandManager.literal("confirm")
+ .executes(DisableAll::disableAll)))
+ );
+ }
+
+ private static int confirmMessage(CommandContext<FabricClientCommandSource> context) {
+ confirmAllowedUntil = System.currentTimeMillis() + CONFIRM_TIMEOUT;
+ MutableText confirm = Text.translatable("skyblocker.disableAll.confirmYes")
+ .styled(style -> style.withClickEvent(new ClickEvent.RunCommand("/" + SkyblockerMod.NAMESPACE + " disableAll confirm")));
+ context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.disableAll.confirm", confirm)));
+ return Command.SINGLE_SUCCESS;
+ }
+
+ private static int disableAll(CommandContext<FabricClientCommandSource> context) {
+ if (System.currentTimeMillis() > confirmAllowedUntil) {
+ context.getSource().sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.disableAll.notPending")));
+ return Command.SINGLE_SUCCESS;
+ }
+ confirmAllowedUntil = 0;
+ try {
+ SkyblockerConfigManager.update(config -> {
+ try {
+ disableBooleans(config);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ context.getSource().sendFeedback(Constants.PREFIX.get().append(Text.translatable("skyblocker.disableAll.success")));
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker DisableAll] Failed to disable all features", e);
+ context.getSource().sendError(Constants.PREFIX.get().append(Text.translatable("skyblocker.disableAll.failed")));
+ }
+ return Command.SINGLE_SUCCESS;
+ }
+
+ /**
+ * Recursively sets all boolean fields within our configuration classes to
+ * {@code false}. Previously this relied on the {@code SerialEntry} annotation
+ * from YACL, but the configuration system no longer uses it.
+ */
+ private static void disableBooleans(Object target) throws IllegalAccessException {
+ for (Field field : target.getClass().getDeclaredFields()) {
+ if (Modifier.isStatic(field.getModifiers())) continue;
+ field.setAccessible(true);
+ Object value = field.get(target);
+ Class<?> type = field.getType();
+ if (type == boolean.class) {
+ field.setBoolean(target, false);
+ } else if (type == Boolean.class) {
+ field.set(target, false);
+ } else if (value instanceof java.util.Map<?, ?>) {
+ @SuppressWarnings("unchecked")
+ java.util.Map<Object, Object> m = (java.util.Map<Object, Object>) value;
+ for (java.util.Map.Entry<Object, Object> entry : m.entrySet()) {
+ if (entry.getValue() instanceof Boolean) {
+ m.put(entry.getKey(), Boolean.FALSE);
+ }
+ }
+ } else if (value != null && isConfigClass(type)) {
+ disableBooleans(value);
+ }
+ }
+ }
+
+ /**
+ * Returns {@code true} if the given class represents one of our config
+ * classes. This prevents {@link #disableBooleans(Object)} from touching
+ * unrelated objects from other mods.
+ */
+ private static boolean isConfigClass(Class<?> clazz) {
+ return !clazz.isPrimitive()
+ && !clazz.isEnum()
+ && !clazz.isRecord()
+ && !clazz.equals(String.class)
+ && !Number.class.isAssignableFrom(clazz)
+ && clazz.getPackageName().startsWith(CONFIGS_PACKAGE);
+ }
+}