diff options
| author | Peyton Brown <81496880+PeytonBrown@users.noreply.github.com> | 2025-07-09 02:02:45 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-09 02:02:45 -0400 |
| commit | f4487214301d32790e7ea2522bfa5aadc50257c9 (patch) | |
| tree | f615baf2ad2b4d57a35ab996b1aa9c9afb148d65 /src/main/java/de | |
| parent | 7e260b9baf431a82401bdca1555a6d42eb4937a7 (diff) | |
| download | Skyblocker-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.java | 117 |
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); + } +} |
