diff --git a/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java b/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java index e49e6f1..1f804f7 100644 --- a/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java +++ b/src/main/java/dev/toolkitmc/guiapi/gui/BarrelGuiHandler.java @@ -113,7 +113,39 @@ public static boolean handleClick(ServerPlayerEntity player, GuiDefinition def, }; if (!matches) continue; + boolean isToggle = btn.toggle().isPresent(); List actions = resolveActions(player, btn); + + // For toggle buttons: apply the tag flip directly in Java (synchronous) + // before running custom actions and reopening. This avoids the race + // between command dispatcher execution and inventory rebuild. + if (isToggle) { + GuiDefinition.ToggleDefinition tgl = btn.toggle().get(); + boolean wasOn = player.getCommandTags().contains(tgl.tag()); + if (wasOn) { + player.removeCommandTag(tgl.tag()); + } else { + player.addCommandTag(tgl.tag()); + } + // Run any custom side-effect actions (skip default tag commands) + boolean chainBroken = false; + for (GuiDefinition.ButtonAction action : actions) { + // Skip the auto-generated tag add/remove defaults + if (action.runWith() == GuiDefinition.RunWith.CONSOLE + && (action.value().startsWith("tag @s add " + tgl.tag()) + || action.value().startsWith("tag @s remove " + tgl.tag()))) { + continue; + } + boolean shouldBreak = executeAction(player, def, page, action); + if (shouldBreak) { chainBroken = true; break; } + } + if (!chainBroken) { + player.closeHandledScreen(); + open(player, def, page); + } + return true; + } + for (GuiDefinition.ButtonAction action : actions) { boolean shouldBreak = executeAction(player, def, page, action); if (shouldBreak) break;