diff --git a/.github/workflows/Publish.yml b/.github/workflows/Publish.yml index fc9bef5..8a7d1fd 100644 --- a/.github/workflows/Publish.yml +++ b/.github/workflows/Publish.yml @@ -5,8 +5,13 @@ on: [workflow_dispatch] jobs: publish: runs-on: ubuntu-latest + permissions: + contents: write + packages: write steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup JDK 21 uses: actions/setup-java@v4 with: @@ -19,4 +24,29 @@ jobs: run: ./gradlew publish env: PUBLISH_USER: ${{ secrets.PUBLISH_USER }} - PUBLISH_PASSWORD: ${{ secrets.PUBLISH_PASSWORD }} \ No newline at end of file + PUBLISH_PASSWORD: ${{ secrets.PUBLISH_PASSWORD }} + + - name: Extract Version + run: | + VERSION=$(grep "^version =" build.gradle | awk -F"'" '{print $2}') + echo "VERSION=$VERSION" >> $GITHUB_ENV + + - name: Generate Release Notes + run: | + LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") + if [ -z "$LAST_TAG" ]; then + echo "No previous tags found. Using full history." + git log --pretty=format:"- %s" > release_notes.txt + else + echo "Generating notes since $LAST_TAG" + git log ${LAST_TAG}..HEAD --pretty=format:"- %s" > release_notes.txt + fi + + - name: Create Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "$VERSION" \ + --title "$VERSION" \ + --notes-file release_notes.txt \ + build/libs/*.jar \ No newline at end of file diff --git a/bin/main/plugin.yml b/bin/main/plugin.yml new file mode 100644 index 0000000..c194720 --- /dev/null +++ b/bin/main/plugin.yml @@ -0,0 +1,6 @@ +name: MinecraftGUI +version: '1.0.0' +main: me.touchie771.minecraftGUI.MinecraftGUI +api-version: '1.21' +authors: [ Touchie771 ] +description: Minecraft library for creating GUIs more easily. \ No newline at end of file diff --git a/src/main/java/me/touchie771/minecraftGUI/api/Menu.java b/src/main/java/me/touchie771/minecraftGUI/api/Menu.java index 7280715..146c961 100644 --- a/src/main/java/me/touchie771/minecraftGUI/api/Menu.java +++ b/src/main/java/me/touchie771/minecraftGUI/api/Menu.java @@ -194,6 +194,13 @@ public void onClose(@NotNull Consumer closeHandler) { public void removeCloseHandler() { clickHandler.removeCloseHandler(); } + + /** + * Removes all click handlers and the close handler. + */ + public void clearHandlers() { + clickHandler.clear(); + } /** * Registers this menu's event handlers with Bukkit. diff --git a/src/main/java/me/touchie771/minecraftGUI/api/presets/ConfirmationMenu.java b/src/main/java/me/touchie771/minecraftGUI/api/presets/ConfirmationMenu.java new file mode 100644 index 0000000..be7cc61 --- /dev/null +++ b/src/main/java/me/touchie771/minecraftGUI/api/presets/ConfirmationMenu.java @@ -0,0 +1,71 @@ +package me.touchie771.minecraftGUI.api.presets; + +import me.touchie771.minecraftGUI.api.ClickHandler; +import me.touchie771.minecraftGUI.api.Menu; +import me.touchie771.minecraftGUI.api.SlotItem; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; + +/** + * A preset menu for confirmation dialogs. + * Provides a simple "Confirm" vs "Cancel" choice. + */ +public class ConfirmationMenu { + + private static final int SIZE = 27; + private static final int CONFIRM_SLOT = 11; + private static final int CANCEL_SLOT = 15; + + /** + * Creates a generic confirmation menu. + * + * @param plugin The plugin instance + * @param title The title of the menu + * @param onConfirm The action to run when confirmed + * @param onCancel The action to run when canceled + * @return A configured Menu instance + */ + public static Menu create(@NotNull Plugin plugin, @NotNull Component title, @NotNull Runnable onConfirm, @NotNull Runnable onCancel) { + SlotItem confirmItem = new SlotItem( + Component.text("Confirm", NamedTextColor.GREEN), + (short) CONFIRM_SLOT, + Material.LIME_WOOL, + 1 + ); + + SlotItem cancelItem = new SlotItem( + Component.text("Cancel", NamedTextColor.RED), + (short) CANCEL_SLOT, + Material.RED_WOOL, + 1 + ); + + ClickHandler confirmHandler = ClickHandler.newBuilder() + .callback(event -> { + event.getWhoClicked().closeInventory(); + onConfirm.run(); + }) + .autoCancel(true) + .build(); + + ClickHandler cancelHandler = ClickHandler.newBuilder() + .callback(event -> { + event.getWhoClicked().closeInventory(); + onCancel.run(); + }) + .autoCancel(true) + .build(); + + return Menu.newBuilder() + .plugin(plugin) + .size(SIZE) + .title(title) + .items(confirmItem, cancelItem) + .onClick(CONFIRM_SLOT, confirmHandler) + .onClick(CANCEL_SLOT, cancelHandler) + .build(); + } +} \ No newline at end of file diff --git a/src/main/java/me/touchie771/minecraftGUI/api/presets/PaginationMenu.java b/src/main/java/me/touchie771/minecraftGUI/api/presets/PaginationMenu.java new file mode 100644 index 0000000..ec3f9eb --- /dev/null +++ b/src/main/java/me/touchie771/minecraftGUI/api/presets/PaginationMenu.java @@ -0,0 +1,134 @@ +package me.touchie771.minecraftGUI.api.presets; + +import me.touchie771.minecraftGUI.api.ClickHandler; +import me.touchie771.minecraftGUI.api.Menu; +import me.touchie771.minecraftGUI.api.SlotItem; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * A preset for a paginated menu. + * Supports navigation between pages of items. + */ +public class PaginationMenu { + + private final Menu menu; + private final List items; + private int currentPage = 0; + + // Standard layout: 6 rows (54 slots). + // Slots 0-44 for content. + // Slot 45: Previous, Slot 53: Next. + private static final int SIZE = 54; + private static final int ITEMS_PER_PAGE = 45; + private static final int PREV_SLOT = 45; + private static final int NEXT_SLOT = 53; + + /** + * Creates a new PaginationMenu. + * + * @param plugin The plugin instance + * @param title The menu title + * @param items The list of items to display across pages + */ + public PaginationMenu(@NotNull Plugin plugin, @NotNull Component title, @NotNull List items) { + this.items = new ArrayList<>(items); + + this.menu = Menu.newBuilder() + .plugin(plugin) + .size(SIZE) + .title(title) + .build(); + + update(); + } + + /** + * Opens the menu for the specified player. + * + * @param player The player to open the menu for + */ + public void open(@NotNull Player player) { + player.openInventory(menu.getInventory()); + } + + private void update() { + menu.clear(); + menu.clearHandlers(); + + int totalPages = (int) Math.ceil((double) items.size() / ITEMS_PER_PAGE); + if (totalPages == 0) totalPages = 1; + + if (currentPage < 0) currentPage = 0; + if (currentPage >= totalPages) currentPage = totalPages - 1; + + int startIndex = currentPage * ITEMS_PER_PAGE; + int endIndex = Math.min(startIndex + ITEMS_PER_PAGE, items.size()); + + for (int i = startIndex; i < endIndex; i++) { + PageItem item = items.get(i); + int slot = i - startIndex; + + menu.addItems(new SlotItem(item.name(), (short) slot, item.material(), item.quantity())); + + if (item.action() != null) { + menu.onClick(slot, ClickHandler.newBuilder() + .callback(item.action()) + .autoCancel(true) + .build()); + } + } + + if (currentPage > 0) { + menu.addItems(new SlotItem( + Component.text("Previous Page", NamedTextColor.YELLOW), + (short) PREV_SLOT, + Material.ARROW, + 1 + )); + menu.onClick(PREV_SLOT, ClickHandler.newBuilder() + .callback(e -> { + currentPage--; + update(); + }) + .autoCancel(true) + .build()); + } + + if (currentPage < totalPages - 1) { + menu.addItems(new SlotItem( + Component.text("Next Page", NamedTextColor.YELLOW), + (short) NEXT_SLOT, + Material.ARROW, + 1 + )); + menu.onClick(NEXT_SLOT, ClickHandler.newBuilder() + .callback(e -> { + currentPage++; + update(); + }) + .autoCancel(true) + .build()); + } + } + + /** + * Represents an item in a paginated menu. + * + * @param name The display name + * @param material The material + * @param quantity The quantity + * @param action The action to perform when clicked (optional) + */ + public record PageItem(@NotNull Component name, @NotNull Material material, int quantity, @Nullable Consumer action) {} +} \ No newline at end of file