From 68d37332b95f702095d57c52688ee3d30d27914a Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:00:41 +0300 Subject: [PATCH 1/2] Add files via upload --- .../toolkitmc/guiapi/config/GuiApiConfig.java | 13 +++++++++ .../guiapi/gui/BarrelGuiHandler.java | 12 ++++++++ .../toolkitmc/guiapi/gui/GuiActionParser.java | 29 ++++++++++++++++++- .../toolkitmc/guiapi/gui/GuiDefinition.java | 11 +++++-- .../guiapi/modmenu/GuiApiModMenuEntry.java | 8 +++++ 5 files changed, 70 insertions(+), 3 deletions(-) diff --git a/src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java b/src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java index 80a57a4..4e44ef6 100644 --- a/src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java +++ b/src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java @@ -44,6 +44,12 @@ public final class GuiApiConfig { private int soundVolume = 100; // 9. New Config private String commandExecuteMode = "CHAT"; // 10. New Config + /** + * guiapi:experimental — enables the {@code none} action type. + * When {@code false}, any button using {@code type: "none"} is skipped with a warning. + */ + private boolean enableNoneAction = false; + private GuiApiConfig() {} // ── Load / Save ────────────────────────────────────────────────────────── @@ -92,6 +98,8 @@ public void load() { soundVolume = Math.clamp(obj.get("sound_volume").getAsInt(), 0, 100); if (obj.has("command_execute_mode")) commandExecuteMode = obj.get("command_execute_mode").getAsString(); + if (obj.has("enable_none_action")) + enableNoneAction = obj.get("enable_none_action").getAsBoolean(); } catch (IOException e) { GuiApiMod.LOGGER.error("[GuiAPI] Failed to load config: {}", e.getMessage()); @@ -117,6 +125,7 @@ public void save() { obj.addProperty("chat_prefix", chatPrefix); obj.addProperty("sound_volume", soundVolume); obj.addProperty("command_execute_mode", commandExecuteMode); + obj.addProperty("enable_none_action", enableNoneAction); try { Files.writeString(CONFIG_PATH, GSON.toJson(obj)); } catch (IOException e) { @@ -174,4 +183,8 @@ public void save() { public String getCommandExecuteMode() { return commandExecuteMode; } public void setCommandExecuteMode(String v) { commandExecuteMode = v; } + + /** guiapi:experimental — {@code none} action type gate. */ + public boolean isEnableNoneAction() { return enableNoneAction; } + public void setEnableNoneAction(boolean v) { enableNoneAction = v; } } diff --git a/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java b/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java index 7a2cde6..937e4e9 100644 --- a/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java +++ b/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java @@ -858,6 +858,18 @@ static boolean executeAction(ServerPlayerEntity player, GuiDefinition def, } player.clearStatusEffects(); } + case NONE -> { + // Experimental no-op action. Requires enable_none_action = true in config. + if (!dev.toolkitmc.guiapi.config.GuiApiConfig.INSTANCE.isEnableNoneAction()) { + if (!dev.toolkitmc.guiapi.config.GuiApiConfig.INSTANCE.isMuteClickErrors()) { + GuiApiMod.LOGGER.warn( + "[GuiAPI] Action type 'none' is disabled. " + + "Set enable_none_action=true in config/guiapi.json to enable it (guiapi:experimental)." + ); + } + } + // Whether enabled or disabled: always no-op. Do nothing, do not break chain. + } } return false; } diff --git a/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java b/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java index c3f16f6..7eae7a4 100644 --- a/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java +++ b/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java @@ -6,7 +6,14 @@ public class GuiActionParser { public static GuiDefinition.ButtonAction parseActionFromString(String str) { - String[] parts = str.trim().split(":", 3); + str = str.trim(); + // Handle bare type names that require no value (e.g. "none", "clear_vars") + GuiDefinition.ActionType bareType = tryParseBareType(str); + if (bareType != null) { + return new GuiDefinition.ButtonAction(bareType, "", GuiDefinition.RunWith.PLAYER, "", 0); + } + + String[] parts = str.split(":", 3); if (parts.length >= 2) { GuiDefinition.ActionType type = GuiDefinition.ActionType.fromString(parts[0]); String val = parts[1]; @@ -26,6 +33,20 @@ public static GuiDefinition.ButtonAction parseActionFromString(String str) { return new GuiDefinition.ButtonAction(GuiDefinition.ActionType.CLOSE, ""); } + /** + * Returns the ActionType if the entire string is a no-value action keyword, + * otherwise returns null. + */ + private static GuiDefinition.ActionType tryParseBareType(String s) { + return switch (s.toLowerCase()) { + case "none" -> GuiDefinition.ActionType.NONE; + case "clear_vars" -> GuiDefinition.ActionType.CLEAR_VARS; + case "clear_effects" -> GuiDefinition.ActionType.CLEAR_EFFECTS; + case "refresh" -> GuiDefinition.ActionType.REFRESH; + default -> null; + }; + } + public static String serializeActionsToString(List actions) { List list = new ArrayList<>(); for (GuiDefinition.ButtonAction act : actions) { @@ -34,6 +55,12 @@ public static String serializeActionsToString(List a act.type() == GuiDefinition.ActionType.ADD_VAR || act.type() == GuiDefinition.ActionType.SUB_VAR) { list.add(prefix + ":" + act.var() + ":" + act.value()); + } else if (act.type() == GuiDefinition.ActionType.NONE || + act.type() == GuiDefinition.ActionType.CLEAR_VARS || + act.type() == GuiDefinition.ActionType.CLEAR_EFFECTS || + act.type() == GuiDefinition.ActionType.REFRESH) { + // No-value actions: serialize without trailing colon + list.add(prefix); } else { list.add(prefix + ":" + act.value()); } diff --git a/src/main/java/dev/toolkitmc/guiapi/gui/GuiDefinition.java b/src/main/java/dev/toolkitmc/guiapi/gui/GuiDefinition.java index 6ea6aa4..ca64163 100644 --- a/src/main/java/dev/toolkitmc/guiapi/gui/GuiDefinition.java +++ b/src/main/java/dev/toolkitmc/guiapi/gui/GuiDefinition.java @@ -37,7 +37,13 @@ public enum ActionType { RUN_COMMAND, CLOSE, OPEN_GUI, MESSAGE, NEXT_PAGE, PREV_PAGE, GOTO_PAGE, SOUND, SET_VAR, ADD_VAR, SUB_VAR, RESET_VAR, CLEAR_VARS, REFRESH, TAKE_ITEM, SET_SCORE, ADD_SCORE, SUB_SCORE, ACTION_BAR, - ADD_EFFECT, REMOVE_EFFECT, CLEAR_EFFECTS; + ADD_EFFECT, REMOVE_EFFECT, CLEAR_EFFECTS, + /** + * No-op action. Does nothing. Requires {@code enable_none_action = true} in config + * (guiapi:experimental feature flag). If the flag is disabled, this action is + * silently skipped and a warning is logged. + */ + NONE; public static ActionType fromString(String s) { return switch (s.toLowerCase()) { @@ -63,7 +69,8 @@ public static ActionType fromString(String s) { case "add_effect" -> ADD_EFFECT; case "remove_effect" -> REMOVE_EFFECT; case "clear_effects" -> CLEAR_EFFECTS; - default -> CLOSE; + case "none" -> NONE; + default -> CLOSE; }; } } diff --git a/src/main/java/dev/toolkitmc/guiapi/modmenu/GuiApiModMenuEntry.java b/src/main/java/dev/toolkitmc/guiapi/modmenu/GuiApiModMenuEntry.java index 9810c21..c3100c5 100644 --- a/src/main/java/dev/toolkitmc/guiapi/modmenu/GuiApiModMenuEntry.java +++ b/src/main/java/dev/toolkitmc/guiapi/modmenu/GuiApiModMenuEntry.java @@ -116,6 +116,8 @@ public ScrollableElement(net.minecraft.client.gui.Drawable drawable, net.minecra private boolean showItemIdsDeveloper; private boolean muteClickErrors; private boolean enableCloseSound; + // guiapi:experimental + private boolean enableNoneAction; // Our 3 New Interactive Input Features private String chatPrefix; @@ -145,6 +147,7 @@ public ScrollableElement(net.minecraft.client.gui.Drawable drawable, net.minecra this.chatPrefix = cfg.getChatPrefix(); this.soundVolume = cfg.getSoundVolume(); this.commandExecuteMode = cfg.getCommandExecuteMode(); + this.enableNoneAction = cfg.isEnableNoneAction(); } private static String nextExecuteMode(String current) { @@ -223,6 +226,7 @@ protected void init() { cfg.setChatPrefix(chatPrefix); cfg.setSoundVolume(soundVolume); cfg.setCommandExecuteMode(commandExecuteMode); + cfg.setEnableNoneAction(enableNoneAction); cfg.save(); MinecraftClient.getInstance().setScreen(parent); }).dimensions(cx - 105, height - 25, 100, 20).build()); @@ -309,6 +313,10 @@ protected void init() { enableCloseSound, v -> enableCloseSound = v); y += 22; + addScrollableToggle(cx, y, "§6[Experimental] §fEnable 'none' action", + enableNoneAction, v -> enableNoneAction = v); + y += 22; + // ── 3 New Interactive Input Features ── // Input Type 1: Text Field for Chat Prefix From 7ba93f643223b1b27d83642295743b8e366ddb77 Mon Sep 17 00:00:00 2001 From: Legends11 <235496468+tickwarden@users.noreply.github.com> Date: Tue, 9 Jun 2026 10:06:33 +0300 Subject: [PATCH 2/2] Add files via upload --- .../java/dev/toolkitmc/guiapi/gui/GuiActionParser.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java b/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java index 7eae7a4..7265e5b 100644 --- a/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java +++ b/src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java @@ -55,11 +55,8 @@ public static String serializeActionsToString(List a act.type() == GuiDefinition.ActionType.ADD_VAR || act.type() == GuiDefinition.ActionType.SUB_VAR) { list.add(prefix + ":" + act.var() + ":" + act.value()); - } else if (act.type() == GuiDefinition.ActionType.NONE || - act.type() == GuiDefinition.ActionType.CLEAR_VARS || - act.type() == GuiDefinition.ActionType.CLEAR_EFFECTS || - act.type() == GuiDefinition.ActionType.REFRESH) { - // No-value actions: serialize without trailing colon + } else if (act.type() == GuiDefinition.ActionType.NONE) { + // NONE has no value — serialize without trailing colon list.add(prefix); } else { list.add(prefix + ":" + act.value());