Skip to content

Commit

Permalink
Minor refactor; Merge Menu and ActiveMenu into one class; Add WIP Jav…
Browse files Browse the repository at this point in the history
…adocs; Merge BedrockSafeMenuBuilder into MenuBuilder
  • Loading branch information
x86-39 committed Mar 29, 2024
1 parent b8aafdf commit fbf2b44
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 163 deletions.
10 changes: 9 additions & 1 deletion src/main/java/me/diademiemi/invuilib/input/ChatListener.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package me.diademiemi.invuilib.input;

import me.diademiemi.invuilib.InvUILib;
import me.diademiemi.invuilib.menu.Menu;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerQuitEvent;

public class ChatListener implements Listener {
@EventHandler
Expand All @@ -14,5 +16,11 @@ public void onChatMessage(AsyncPlayerChatEvent e) {
e.setCancelled(true);
}
}

@EventHandler
public void onPlayerQUit(PlayerQuitEvent e) {
ChatTextInput input = ChatTextInput.getInputs().get(e.getPlayer());
if (input != null) {
input.remove();
}
}
}
77 changes: 0 additions & 77 deletions src/main/java/me/diademiemi/invuilib/menu/ActiveMenu.java

This file was deleted.

9 changes: 8 additions & 1 deletion src/main/java/me/diademiemi/invuilib/menu/Dialog.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

import org.bukkit.entity.Player;

/**
* A dialog is a wrapper around a menu that is intended to be shown to a player.
* It is a way to encapsulate the creation and showing of a menu.
* It is intended as a safe way to show a menu to a player, ensuring that the player's current menu is closed before showing the new menu.
* The recommended way to use this is to implement this class and override the create method to return the menu you want to show.
* MenuBuilder is provided to help with creating menus.
*/
public interface Dialog {
default void show(Player player, Object... args) {
try {
Expand All @@ -17,7 +24,7 @@ default void show(Player player, Object... args) {
}

default void close(Player player) {
ActiveMenu.getActiveMenu(player).close();
Menu.getMenu(player).close();
}

Menu create(Player p, Object... args);
Expand Down
142 changes: 139 additions & 3 deletions src/main/java/me/diademiemi/invuilib/menu/Menu.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,69 @@
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.Inventory;

import java.awt.*;
import java.util.HashMap;
import java.util.Map;

public class Menu extends ActiveMenu {
/**
* A menu is a wrapper for an inventory that allows for easy creation and manipulation of GUIs
* Menus contain "buttons" which are the clickable items in the GUI. These can be added with the addButton method.
* Menus can be opened and closed with the open and close methods.
* This also contains a static map of every menu that is currently open, which can be accessed with getMenuMap.
* Menus are linked to a player, this is to prevent exploits where a player could force open a menu without permission
* Menus can be set to prevent closing, this is useful for menus that require a player to complete an action before closing
*/
public class Menu {
public static HashMap<Player, Menu> menuMap = new HashMap<Player, Menu>();
public HashMap<Integer, MenuButton> buttons;
public Inventory inventory;
public Player player;
public String title;
public boolean preventClose = false;

/**
* @param activeMenu GUI to add
*/
public void addMenu(Menu activeMenu) {
menuMap.put(player, activeMenu);
}

/**
* @param activeMenu GUI to remove
*/
public void removeMenu(Menu activeMenu) {
menuMap.remove(player, activeMenu);
}

/**
* @return all loaded GUIs
*/
public static HashMap<Player, Menu> getMenuMap() {
return menuMap;
}

/**
* @param player the player to get the GUI of
* @return the GUI of the given inventory and player
*/
public static Menu getMenu(Player player) {
return menuMap.get(player);
}

/**
* Create menu
* @param size the size of the GUI
* @param title the title of the GUI
* @param player the Player for the GUI
* @param buttons the buttons of the GUI
*/
public Menu(Player player, MenuSize size, String title, HashMap<Integer, MenuButton> buttons) {
public Menu(Player player, MenuSize size, String title, HashMap<Integer, MenuButton> buttons, boolean preventClose) {
this.title = title;
this.player = player;
this.buttons = buttons;
this.preventClose = preventClose;

if (size == MenuSize.HALF_ROW) {
this.inventory = Bukkit.getServer().createInventory(null, InventoryType.HOPPER, title);
Expand All @@ -26,7 +74,95 @@ public Menu(Player player, MenuSize size, String title, HashMap<Integer, MenuBut
}

this.bakeButtons();
guiMap.put(player, this);
menuMap.put(player, this);
}

/**
* Open the GUI for the player
*/
public void open() {
player.openInventory(inventory);
}

/**
* Close the GUI and remove it from the GUI map
*/
public void close() {
removeMenu(this);
player.closeInventory();
}

/**
* @param slot the slot to get the button of
* @return the button of the given slot
*/
public MenuButton getButton(int slot) {
return buttons.get(slot);
}

/**
* @param slot the slot to update the button of
* @param button the button to update
* @throws IndexOutOfBoundsException if the slot is out of bounds
*/
public void updateButton(int slot, MenuButton button) throws IndexOutOfBoundsException {
if (slot >= inventory.getSize()) {
throw new IndexOutOfBoundsException("Slot is out of bounds");
} else {
buttons.put(slot, button);
}
}

/**
* @param button the button to add
* @param slot the slots to add the button to
* @throws IndexOutOfBoundsException if the slot is out of bounds
*/
public void addButton(MenuButton button, int... slot) throws IndexOutOfBoundsException {
if (slot.length == 0) {
buttons.put(buttons.size() + 1, button); // If no slot is specified, add to the next available slot. NOT RECOMMENDED
} else {
for (int i : slot) {
buttons.put(i, button);
}
}
}

/**
* @param slot the slot to remove the button from
*/
public void removeButton(int slot) {
buttons.remove(slot);
}

/**
* Bake the buttons into the inventory
*/
public void bakeButtons() {
for (Map.Entry<Integer, MenuButton> entry : buttons.entrySet()) {
inventory.setItem(entry.getKey(), entry.getValue().getItemStack());
}
}

/**
* @param preventClose whether to prevent the GUI from closing
*/
public void setPreventClose(boolean preventClose) {
this.preventClose = preventClose;
}

/**
* @return whether the GUI is set to prevent closing
*/
public boolean isPreventClose() {
return preventClose;
}

/**
* @return the inventory of the GUI
*/
public Inventory getInventory() {
return inventory;
}

}
69 changes: 68 additions & 1 deletion src/main/java/me/diademiemi/invuilib/menu/MenuBuilder.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package me.diademiemi.invuilib.menu;

import me.diademiemi.invuilib.util.PlayerUtil;
import org.bukkit.entity.Player;

import java.util.HashMap;
Expand All @@ -11,6 +12,7 @@ public class MenuBuilder {
public Player player;

public HashMap<Integer, MenuButton> buttons;
private boolean preventClose;

public MenuBuilder(String title, MenuSize size, Player player) {
this.title = title;
Expand All @@ -23,6 +25,10 @@ public void setTitle(String title) {
this.title = title;
}

public void setPreventClose(boolean preventClose) {
this.preventClose = preventClose;
}

public void setSize(MenuSize size) {
this.size = size;
}
Expand All @@ -37,8 +43,69 @@ public void addButton(MenuButton button, int... slot) {
}
}

private int slotByColumnRow(int column, int row) {
// Starting on the top left
return column + row * 9;
}

private int slotByColumnRow(int column, int row, PlayerUtil.MenuType menuType) {
// Starting on the top left
// If the player is on Bedrock edition with POCKET menu, we use 7 columns instead of 9
// For Java and Bedrock CLASSIC, we use 9 columns
// For these, we add +1 for the first row and +2 for every other row, to skip the outer columns
// E.g.
// column 0 row 0 on Bedrock is 0, on Java is 1
// column 1 row 0 on Bedrock is 1, on Java is 2
// column 0 row 1 on Bedrock is 7, on Java is 9
// column 1 row 1 on Bedrock is 8, on Java is 10
// This goes up to column 6 row 5.

// For Java edition, this means the leftmost column and rightmost column are skipped
// For Bedrock edition, this means the bottom two rows are skipped
// This sadly is a sacrifice to make the menu look good on both editions
// Later I will provide a menu type that can have two different layouts for Java and Bedrock

// Limit to 6 columns and 5 rows
if (column > 6) {
column = 6;
}
if (row > 5) {
row = 5;
}

if (menuType == PlayerUtil.MenuType.POCKET) {
return column + row * 7;
} else {
// 1 + column *
return 1 + column + row * 9;
}
}

/**
* Add a button to the menu by column and row
* @param button the button to add
* @param column the column to add the button to
* @param row the row to add the button to
* @param bedrockSafe if the menu should be bedrock safe. This limits the menu to 7 columns and 3 or 6 rows (depending on the menu size)
*/
public void addButtonByColumnRow(MenuButton button, int column, int row, boolean bedrockSafe) {
if (bedrockSafe) {
PlayerUtil.MenuType menuType = PlayerUtil.getMenuType(player);
addButton(button, slotByColumnRow(column, row, menuType));
} else {
addButton(button, slotByColumnRow(column, row));
}
}

public void addButtonByColumnRow(MenuButton button, int column, int row) {
addButtonByColumnRow(button, column, row, false);
}




public Menu build() {
return new Menu(player, size, title, buttons);
return new Menu(player, size, title, buttons, preventClose);
}

}
Loading

0 comments on commit fbf2b44

Please sign in to comment.