Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 ──────────────────────────────────────────────────────────
Expand Down Expand Up @@ -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());
Expand All @@ -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) {
Expand Down Expand Up @@ -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; }
}
12 changes: 12 additions & 0 deletions src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
26 changes: 25 additions & 1 deletion src/main/java/dev/toolkitmc/guiapi/gui/GuiActionParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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<GuiDefinition.ButtonAction> actions) {
List<String> list = new ArrayList<>();
for (GuiDefinition.ButtonAction act : actions) {
Expand All @@ -34,6 +55,9 @@ public static String serializeActionsToString(List<GuiDefinition.ButtonAction> 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) {
// NONE has no value — serialize without trailing colon
list.add(prefix);
} else {
list.add(prefix + ":" + act.value());
}
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/dev/toolkitmc/guiapi/gui/GuiDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand All @@ -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;
};
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand Down