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
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cd guiAPI
./gradlew build
```

The built jar is at `build/libs/guiapi-1.0.5.jar`.
The built jar is at `build/libs/guiapi-1.0.7.jar`.

To run in a local Minecraft instance, use Fabric's `runServer` task or drop the jar into a test server's `mods/` folder.

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ No client mod required. No macros. No external dependencies beyond Fabric API.

## Installation

1. Drop `guiapi-1.0.6+26.2.jar` into your `mods/` folder.
1. Drop `guiapi-1.0.7+26.2.jar` into your `mods/` folder.
2. Drop your datapack into `world/datapacks/`.
3. Run `/reload` or `/guiapi reload`.

Expand Down Expand Up @@ -220,7 +220,7 @@ Please refer to the updated `example-datapack` directory in the repository sourc
```bash
chmod +x gradlew
./gradlew build
# Output: build/libs/guiapi-1.0.6+26.2.jar
# Output: build/libs/guiapi-1.0.7+26.2.jar
```

Requires **Java 25**.
Expand Down
82 changes: 82 additions & 0 deletions example-datapack/data/example/gui/widgets_demo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"title": "§bWidgets & Conditional Item Demo",
"rows": 4,
"tick_rate": 20,
"filler": {
"item": "minecraft:black_stained_glass_pane",
"name": " ",
"hide_tooltip": true
},

"buttons": [
{
"slot": 4,
"item": "minecraft:diamond_sword",
"name": "§b1. Conditional Item (else_item)",
"lore": [
"§7Same button — item flips automatically",
"§7based on whether you have enough gold.",
"§7Try: /scoreboard players set @s gold_nuggets 5"
],
"condition": { "type": "has_item", "value": "minecraft:gold_nugget:5" },
"actions": [
{ "type": "take_item", "value": "minecraft:gold_nugget:5" },
{ "type": "run_command", "value": "give @s minecraft:diamond", "run_with": "console" },
{ "type": "sound", "value": "minecraft:entity.villager.yes" },
{ "type": "action_bar", "value": "§aPurchased!" },
{ "type": "refresh" }
],
"else_item": {
"item": "minecraft:barrier",
"name": "§c1. Conditional Item §7(Locked)",
"lore": [
"§7Cost: §e5 Gold Nuggets",
"§cYou don't have enough gold!",
"§7This slot is visible but §cnot clickable",
"§7while the condition is false."
]
}
},

{
"slot": 31,
"item": "minecraft:barrier",
"name": "§cClose",
"actions": [{ "type": "close" }]
}
],

"progress_bars": [
{
"start_slot": 10,
"length": 7,
"value_source": "score:coins",
"max_value": 100,
"filled_item": "minecraft:lime_stained_glass_pane",
"empty_item": "minecraft:gray_stained_glass_pane",
"name": "§e2. Coin Progress: {score:coins}/100",
"lore": ["§7Fills automatically — recalculated on every refresh."]
}
],

"displays": [
{
"slot": 22,
"item": "minecraft:paper",
"name": "§b3. Static Display",
"lore": [
"§7Player: §f{player}",
"§7Coins: §e{score:coins}",
"§7This item is read-only — clicking it does nothing."
]
},
{
"slot": 13,
"item": "minecraft:golden_apple",
"name": "§6VIP Status Active",
"lore": ["§7Shown only while you have the vip tag."],
"glint": true,
"condition": { "type": "has_tag", "value": "vip" }
}
]
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ org.gradle.parallel=true
org.gradle.configuration-cache=false

# Project
mod_version=1.0.6+26.2
mod_version=1.0.7+26.2
maven_group=dev.toolkitmc
archives_base_name=guiapi

Expand Down
33 changes: 31 additions & 2 deletions src/main/java/dev/toolkitmc/guiapi/command/GuiCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -196,19 +196,48 @@ private static int showHelp(CommandContext<CommandSourceStack> ctx) {
"\n" +
"Macro functions: define reusable action blocks in JSON with \"macros\": {}\n" +
" actions: run_function:<macro_name>\n" +
" random: run_random_function:<name>[*weight](,<name>[*weight]...)\n" +
" e.g. run_random_function:common*70,rare*25,legendary*5\n" +
"\n" +
"Anvil input: anvil_input action saves text to a variable and {input}\n" +
" Example: {\"type\": \"anvil_input\", \"var\": \"myVar\", \"value\": \"Enter name|Default\"}\n" +
"\n" +
"Item/XP actions:\n" +
" give_item:<itemId>:<amount> - give item(s), overflow drops at feet\n" +
" take_item:<itemId>:<amount> - remove item(s) from inventory\n" +
" add_xp:<n> - add n XP points\n" +
" add_xp:L<n> - add n XP levels (prefix with L)\n" +
"\n" +
"Button JSON fields:\n" +
" slot, page, item, name, lore, glint\n" +
" click_type: any | left | right | shift\n" +
" condition: has_tag | not_tag | score_gt | score_lt | score_eq\n" +
" var_eq | var_gt | var_lt | var_set\n" +
" actions: run_command | close | open_gui | message | sound\n" +
" has_item | not_item | level_gt | level_lt\n" +
" health_gt | health_lt | food_gt | food_lt\n" +
" permission:<0-4> (checks player's command permission level)\n" +
" actions: run_command | close | open_gui | message | sound | action_bar\n" +
" next_page | prev_page | goto_page | run_function\n" +
" run_random_function | give_item | take_item | add_xp\n" +
" set_var | add_var | sub_var | reset_var | clear_vars\n" +
" anvil_input" ;
" set_score | add_score | sub_score\n" +
" add_effect | remove_effect | clear_effects\n" +
" anvil_input\n" +
"\n" +
"Conditional item display: add \"else_item\" (same fields as a button)\n" +
" alongside \"condition\" to show an alternate item instead of hiding\n" +
" the button when the condition is false. Button stays inert while\n" +
" showing else_item (clicks are ignored, not the normal actions).\n" +
"\n" +
"Non-button widgets (top-level GUI JSON fields):\n" +
" progress_bars: [{ start_slot, length, page, value_source,\n" +
" max_value, filled_item, empty_item, name, lore }]\n" +
" value_source: \"score:<objective>\" or \"var:<key>\"\n" +
" Fills [start_slot, start_slot+length) proportionally, recalculated\n" +
" on every open/refresh (e.g. via tick_rate). Read-only, not clickable.\n" +
" displays: [{ slot, page, item, name, lore, glint, amount, condition }]\n" +
" A single read-only info item. Supports the same condition types as\n" +
" buttons. Clicks on a display slot are always ignored.";
ctx.getSource().sendSuccess(() -> Component.literal(help), false);
return 1;
}
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/dev/toolkitmc/guiapi/config/GuiApiConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public final class GuiApiConfig {
private String chatPrefix = "§8[§6GuiAPI§8] §f"; // 8. New Config
private int soundVolume = 100; // 9. New Config
private String commandExecuteMode = "CHAT"; // 10. New Config
private boolean allowGamemodeChange = true; // 11. New Config

private GuiApiConfig() {}

Expand Down Expand Up @@ -92,6 +93,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("allow_gamemode_change"))
allowGamemodeChange = obj.get("allow_gamemode_change").getAsBoolean();

} catch (IOException e) {
GuiApiMod.LOGGER.error("[GuiAPI] Failed to load config: {}", e.getMessage());
Expand All @@ -117,6 +120,7 @@ public void save() {
obj.addProperty("chat_prefix", chatPrefix);
obj.addProperty("sound_volume", soundVolume);
obj.addProperty("command_execute_mode", commandExecuteMode);
obj.addProperty("allow_gamemode_change", allowGamemodeChange);
try {
Files.writeString(CONFIG_PATH, GSON.toJson(obj));
} catch (IOException e) {
Expand Down Expand Up @@ -174,4 +178,7 @@ public void save() {

public String getCommandExecuteMode() { return commandExecuteMode; }
public void setCommandExecuteMode(String v) { commandExecuteMode = v; }

public boolean isAllowGamemodeChange() { return allowGamemodeChange; }
public void setAllowGamemodeChange(boolean v) { allowGamemodeChange = v; }
}
Loading