aliases, Material icon, SettingValue... values) {
checkArgument(!aliases.isEmpty(), "aliases is empty");
this.aliases = ImmutableList.copyOf(aliases);
+ this.icon = icon;
this.values = values;
}
@@ -85,6 +126,15 @@ public SettingValue getDefaultValue() {
return getPossibleValues()[0];
}
+ /**
+ * Get the {@link Material} used to visually represent this setting in GUI menus.
+ *
+ * @return {@link Material} to visually represent setting.
+ */
+ public Material getIconMaterial() {
+ return icon;
+ }
+
@Override
public String toString() {
return getName();
diff --git a/core/src/main/java/tc/oc/pgm/api/setting/SettingValue.java b/core/src/main/java/tc/oc/pgm/api/setting/SettingValue.java
index c36d518e40..54cee49279 100644
--- a/core/src/main/java/tc/oc/pgm/api/setting/SettingValue.java
+++ b/core/src/main/java/tc/oc/pgm/api/setting/SettingValue.java
@@ -6,6 +6,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
+import org.bukkit.DyeColor;
import tc.oc.pgm.util.StringUtils;
/**
@@ -14,46 +15,51 @@
* @see SettingKey
*/
public enum SettingValue {
- CHAT_TEAM("chat", "team"), // Only send to members on the player's team
- CHAT_GLOBAL("chat", "global"), // Send to all players in the same match
- CHAT_ADMIN("chat", "admin"), // Send to all server operators
+ CHAT_TEAM("chat", "team", DyeColor.GREEN), // Only send to members on the player's team
+ CHAT_GLOBAL("chat", "global", DyeColor.ORANGE), // Send to all players in the same match
+ CHAT_ADMIN("chat", "admin", DyeColor.RED), // Send to all server operators
- DEATH_OWN("death", "own"), // Only send death messages involving self
- DEATH_ALL("death", "all"), // Send all death messages, highlight your own
+ DEATH_OWN("death", "own", DyeColor.RED), // Only send death messages involving self
+ DEATH_ALL("death", "all", DyeColor.GREEN), // Send all death messages, highlight your own
- PICKER_AUTO("picker", "auto"), // Display after cycle, or with permissions.
- PICKER_ON("picker", "on"), // Display the picker GUI always
- PICKER_OFF("picker", "off"), // Never display the picker GUI
+ PICKER_AUTO("picker", "auto", DyeColor.ORANGE), // Display after cycle, or with permissions.
+ PICKER_ON("picker", "on", DyeColor.GREEN), // Display the picker GUI always
+ PICKER_OFF("picker", "off", DyeColor.RED), // Never display the picker GUI
- JOIN_ON("join", "all"), // Send all join messages
- JOIN_OFF("join", "none"), // Never send join messages
+ JOIN_ON("join", "all", DyeColor.ORANGE), // Send all join messages
+ JOIN_OFF("join", "none", DyeColor.RED), // Never send join messages
- MESSAGE_ON("message", "on"), // Always accept direct messages
- MESSAGE_OFF("message", "off"), // Never accept direct messages
+ MESSAGE_ON("message", "on", DyeColor.GREEN), // Always accept direct messages
+ MESSAGE_OFF("message", "off", DyeColor.RED), // Never accept direct messages
- OBSERVERS_ON("observers", "on"), // Show observers
- OBSERVERS_OFF("observers", "off"), // Hide observers
+ OBSERVERS_ON("observers", "on", DyeColor.GREEN), // Show observers
+ OBSERVERS_OFF("observers", "off", DyeColor.RED), // Hide observers
- SOUNDS_ALL("sounds", "all"), // Play all sounds
- SOUNDS_DM("sounds", "messages"), // Only play DM sounds
- SOUNDS_NONE("sounds", "none"), // Never play sounds
+ SOUNDS_ALL("sounds", "all", DyeColor.GREEN), // Play all sounds
+ SOUNDS_DM("sounds", "messages", DyeColor.ORANGE), // Only play DM sounds
+ SOUNDS_NONE("sounds", "none", DyeColor.RED), // Never play sounds
- VOTE_ON("vote", "on"), // Show the vote book on cycle
- VOTE_OFF("vote", "off"), // Don't show the vote book on cycle
+ VOTE_ON("vote", "on", DyeColor.GREEN), // Show the vote book on cycle
+ VOTE_OFF("vote", "off", DyeColor.RED), // Don't show the vote book on cycle
- STATS_ON("stats", "on"), // Track stats
- STATS_OFF("stats", "off"), // Don't track stats
+ STATS_ON("stats", "on", DyeColor.GREEN), // Track stats
+ STATS_OFF("stats", "off", DyeColor.RED), // Don't track stats
- EFFECTS_ON("effects", "on"), // Display special particle effects
- EFFECTS_OFF("effects", "off"); // Don't display special particle effects
- ;
+ EFFECTS_ON("effects", "on", DyeColor.GREEN), // Display special particle effects
+ EFFECTS_OFF("effects", "off", DyeColor.RED), // Don't display special particle effects
+
+ TIME_AUTO("time", "auto", DyeColor.ORANGE), // Player time is in sync
+ TIME_DARK("time", "dark", DyeColor.GRAY), // Player time is always set to midday
+ TIME_LIGHT("time", "light", DyeColor.WHITE); // Player time is always set to midnight
private final String key;
private final String name;
+ private final DyeColor color;
- SettingValue(String group, String name) {
+ SettingValue(String group, String name, DyeColor color) {
this.key = checkNotNull(group);
this.name = checkNotNull(name);
+ this.color = checkNotNull(color);
}
/**
@@ -74,6 +80,16 @@ public String getName() {
return name;
}
+ /**
+ * Get {@link DyeColor} related to this setting value .
+ *
+ * @see {@link SettingMenu} for usage.
+ * @return {@link DyeColor} for this setting value.
+ */
+ public DyeColor getColor() {
+ return color;
+ }
+
@Override
public String toString() {
return getName();
diff --git a/core/src/main/java/tc/oc/pgm/command/SettingCommand.java b/core/src/main/java/tc/oc/pgm/command/SettingCommand.java
index 9f965d8cd6..aa2889f303 100644
--- a/core/src/main/java/tc/oc/pgm/command/SettingCommand.java
+++ b/core/src/main/java/tc/oc/pgm/command/SettingCommand.java
@@ -15,20 +15,28 @@
import tc.oc.pgm.api.setting.SettingValue;
import tc.oc.pgm.api.setting.Settings;
import tc.oc.pgm.observers.ObserverToolsMatchModule;
+import tc.oc.pgm.settings.SettingsMenu;
import tc.oc.pgm.util.text.TextFormatter;
// TODO: remove some of these when settings UI is released
public final class SettingCommand {
@Command(
- aliases = {"settings", "tools", "observertools", "ot"},
+ aliases = {"settings"},
desc = "Open the settings menu")
public void settings(MatchPlayer player) {
+ new SettingsMenu(player);
+ }
+
+ @Command(
+ aliases = {"tools", "observertools", "ot"},
+ desc = "Open the observer tools menu")
+ public void observerTools(MatchPlayer player) {
if (player.isObserving()) {
final ObserverToolsMatchModule tools =
player.getMatch().getModule(ObserverToolsMatchModule.class);
if (tools != null) {
- tools.openMenuManual(player);
+ tools.openMenu(player);
}
} else {
// TODO: reconsider when observer tools become settings
diff --git a/core/src/main/java/tc/oc/pgm/menu/InventoryMenu.java b/core/src/main/java/tc/oc/pgm/menu/InventoryMenu.java
new file mode 100644
index 0000000000..cb93367ddb
--- /dev/null
+++ b/core/src/main/java/tc/oc/pgm/menu/InventoryMenu.java
@@ -0,0 +1,97 @@
+package tc.oc.pgm.menu;
+
+import static net.kyori.adventure.text.Component.translatable;
+import static tc.oc.pgm.util.text.TextTranslations.translateLegacy;
+
+import fr.minuskube.inv.ClickableItem;
+import fr.minuskube.inv.SmartInventory;
+import fr.minuskube.inv.content.InventoryContents;
+import fr.minuskube.inv.content.InventoryProvider;
+import javax.annotation.Nullable;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.format.TextDecoration;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import tc.oc.pgm.api.PGM;
+import tc.oc.pgm.api.player.MatchPlayer;
+import tc.oc.pgm.util.inventory.ItemBuilder;
+
+/** A generic inventory menu * */
+public abstract class InventoryMenu implements InventoryProvider {
+
+ private final SmartInventory inventory;
+ private final MatchPlayer viewer;
+
+ public InventoryMenu(String titleKey, NamedTextColor titleColor, int rows, MatchPlayer viewer) {
+ this(titleKey, titleColor, rows, viewer, null);
+ }
+
+ public InventoryMenu(
+ String titleKey,
+ NamedTextColor titleColor,
+ int rows,
+ MatchPlayer viewer,
+ @Nullable SmartInventory parent) {
+ this(translatable(titleKey, titleColor, TextDecoration.BOLD), rows, viewer, parent);
+ }
+
+ public InventoryMenu(
+ Component title, int rows, MatchPlayer viewer, @Nullable SmartInventory parent) {
+ this.viewer = viewer;
+
+ SmartInventory.Builder builder =
+ SmartInventory.builder()
+ .manager(PGM.get().getInventoryManager())
+ .title(translateLegacy(title, getBukkit()))
+ .size(rows, 9)
+ .provider(this);
+
+ if (parent != null) {
+ builder.parent(parent);
+ }
+
+ this.inventory = builder.build();
+ }
+
+ public void open() {
+ inventory.open(getBukkit());
+ }
+
+ public Player getBukkit() {
+ return viewer.getBukkit();
+ }
+
+ public MatchPlayer getViewer() {
+ return viewer;
+ }
+
+ public SmartInventory getInventory() {
+ return inventory;
+ }
+
+ public void addBackButton(
+ InventoryContents contents, Component parentMenuTitle, int row, int col) {
+ Component back = translatable("menu.page.return", NamedTextColor.GRAY, parentMenuTitle);
+
+ contents.set(
+ row,
+ col,
+ ClickableItem.of(
+ new ItemBuilder()
+ .material(Material.BARRIER)
+ .name(translateLegacy(back, getBukkit()))
+ .build(),
+ c -> {
+ getInventory()
+ .getParent()
+ .ifPresent(
+ parent -> {
+ parent.open(getBukkit());
+ });
+ }));
+ }
+
+ @Override
+ public void update(Player player, InventoryContents contents) {}
+}
diff --git a/util/src/main/java/tc/oc/pgm/util/menu/InventoryMenuItem.java b/core/src/main/java/tc/oc/pgm/menu/MenuItem.java
similarity index 53%
rename from util/src/main/java/tc/oc/pgm/util/menu/InventoryMenuItem.java
rename to core/src/main/java/tc/oc/pgm/menu/MenuItem.java
index 0f77be3833..38e0d7e4b0 100644
--- a/util/src/main/java/tc/oc/pgm/util/menu/InventoryMenuItem.java
+++ b/core/src/main/java/tc/oc/pgm/menu/MenuItem.java
@@ -1,18 +1,21 @@
-package tc.oc.pgm.util.menu;
+package tc.oc.pgm.menu;
+import fr.minuskube.inv.ClickableItem;
import java.util.List;
+import java.util.function.Consumer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
+import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import tc.oc.pgm.util.text.TextTranslations;
-/** @see InventoryMenu */
-public interface InventoryMenuItem {
+/** @see InventoryMenu * */
+public interface MenuItem {
/**
* Gets the display name of this item, can be localized, colored, and decorated (will
@@ -27,10 +30,28 @@ public interface InventoryMenuItem {
Material getMaterial(Player player);
/**
- * If this method is in a {@link InventoryMenu} this method will be called automatically by the
- * menu
+ * Action that should be performed once item is clicked
+ *
+ * @param player The player who clicked
+ * @param type The type of click
*/
- void onInventoryClick(InventoryMenu menu, Player player, ClickType clickType);
+ void onClick(Player player, ClickType type);
+
+ /**
+ * Gets the action to perform when this item is clicked in an inventory menu.
+ *
+ * Note: only override if you need access to the {@link InventoryClickEvent} otherwise use
+ * {@link MenuItem#onClick(Player, ClickType)}
+ *
+ * @return a consumer for the inventory click event
+ */
+ default Consumer getAction() {
+ return context -> {
+ Player player = (Player) context.getWhoClicked();
+ onClick(player, context.getClick());
+ context.setCurrentItem(createItem(player));
+ };
+ }
/**
* Called by {@link #createItem(Player)} after standard changes has been done. When possible this
@@ -40,6 +61,16 @@ default ItemMeta modifyMeta(ItemMeta meta) {
return meta;
}
+ /**
+ * Creates a {@link ClickableItem} for the given player Item & action are linked together here
+ *
+ * @param player The player to display this item to
+ * @return a clickable item used in inventory menus
+ */
+ default ClickableItem getClickableItem(Player player) {
+ return ClickableItem.of(createItem(player), getAction());
+ }
+
default ItemStack createItem(Player player) {
ItemStack stack = new ItemStack(getMaterial(player));
ItemMeta meta = stack.getItemMeta();
diff --git a/core/src/main/java/tc/oc/pgm/menu/PagedInventoryMenu.java b/core/src/main/java/tc/oc/pgm/menu/PagedInventoryMenu.java
new file mode 100644
index 0000000000..f9d2abbf9c
--- /dev/null
+++ b/core/src/main/java/tc/oc/pgm/menu/PagedInventoryMenu.java
@@ -0,0 +1,138 @@
+package tc.oc.pgm.menu;
+
+import static net.kyori.adventure.text.Component.translatable;
+import static tc.oc.pgm.util.text.TextTranslations.translateLegacy;
+
+import fr.minuskube.inv.ClickableItem;
+import fr.minuskube.inv.SmartInventory;
+import fr.minuskube.inv.content.InventoryContents;
+import fr.minuskube.inv.content.Pagination;
+import fr.minuskube.inv.content.SlotIterator;
+import fr.minuskube.inv.content.SlotPos;
+import net.kyori.adventure.text.Component;
+import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.format.TextDecoration;
+import org.bukkit.Material;
+import org.bukkit.entity.Player;
+import org.bukkit.inventory.ItemFlag;
+import org.bukkit.inventory.ItemStack;
+import tc.oc.pgm.api.player.MatchPlayer;
+import tc.oc.pgm.util.bukkit.BukkitUtils;
+import tc.oc.pgm.util.inventory.ItemBuilder;
+
+/** A specialized inventory menu for easy pagination * */
+public abstract class PagedInventoryMenu extends InventoryMenu {
+
+ private static final Material PAGE_MATERIAL = Material.ARROW;
+
+ private final int itemsPerPage;
+ private final int startingRow;
+ private final int startingCol;
+
+ public PagedInventoryMenu(
+ Component title,
+ int rows,
+ MatchPlayer viewer,
+ SmartInventory parent,
+ int itemsPerPage,
+ int startingRow,
+ int startingCol) {
+ super(title, rows, viewer, parent);
+ this.itemsPerPage = itemsPerPage;
+ this.startingRow = startingRow;
+ this.startingCol = startingCol;
+ }
+
+ /**
+ * Automatic setup of page contents
+ *
+ * To enable paged setup call in {@link #init(Player, InventoryContents)}
+ *
+ * @param player {@link Player} viewing the inventory
+ * @param contents {@link InventoryContents} of menu
+ */
+ public void setupPageContents(Player player, InventoryContents contents) {
+ ClickableItem[] items = getPageContents(player);
+
+ // If no items are found, display empty contents button
+ if (items == null || items.length == 0) {
+ contents.set(getEmptyPageSlot(), getEmptyContentsButton(player));
+ return;
+ }
+
+ // Setup pagination
+ Pagination page = contents.pagination();
+ page.setItems(items);
+ page.setItemsPerPage(itemsPerPage);
+ page.addToIterator(
+ contents.newIterator(SlotIterator.Type.HORIZONTAL, startingRow, startingCol));
+
+ // Previous button
+ if (!page.isFirst()) {
+ contents.set(
+ getPreviousPageSlot(), getPageItem(player, page.getPage() - 1, "menu.page.previous"));
+ }
+
+ // Next button
+ if (!page.isLast()) {
+ contents.set(getNextPageSlot(), getPageItem(player, page.getPage() + 1, "menu.page.next"));
+ }
+ }
+
+ /**
+ * The position of the previous page button.
+ *
+ * @return a {@link SlotPos} where previous page button will be located.
+ */
+ public abstract SlotPos getPreviousPageSlot();
+
+ /**
+ * The position of the next page button.
+ *
+ * @return a {@link SlotPos} where next page button will be located.
+ */
+ public abstract SlotPos getNextPageSlot();
+
+ /**
+ * The position of the no page contents button, only displayed when page contents is empty or
+ * null.
+ *
+ * @see #getPageContents(Player)
+ * @return a {@link SlotPos} where no page button will be located.
+ */
+ public abstract SlotPos getEmptyPageSlot();
+
+ /**
+ * An array of {@link ClickableItem}s that will populate the paged inventory
+ *
+ * @param viewer The {@link Player} viewer who each item will be rendered for
+ * @return an array of clickable items
+ */
+ public abstract ClickableItem[] getPageContents(Player viewer);
+
+ protected ClickableItem getEmptyContentsButton(Player viewer) {
+ Component name = translatable("menu.page.empty", NamedTextColor.DARK_RED, TextDecoration.BOLD);
+ return ClickableItem.empty(
+ new ItemBuilder().material(Material.BARRIER).name(translateLegacy(name, viewer)).build());
+ }
+
+ protected ClickableItem getPageItem(Player player, int page, String key) {
+ Component text = translatable(key, NamedTextColor.YELLOW, TextDecoration.BOLD);
+ return ClickableItem.of(
+ getPageIcon(translateLegacy(text, player), page + 1),
+ c -> getInventory().open(player, page));
+ }
+
+ private final ItemStack getPageIcon(String text, int page) {
+ return getNamedItem(text, PAGE_MATERIAL, page);
+ }
+
+ private ItemStack getNamedItem(String text, Material material, int amount) {
+ return new ItemBuilder()
+ .material(material)
+ .amount(amount)
+ .name(BukkitUtils.colorize(text))
+ .flags(ItemFlag.values())
+ .build();
+ }
+}
diff --git a/core/src/main/java/tc/oc/pgm/modules/PlayerTimeMatchModule.java b/core/src/main/java/tc/oc/pgm/modules/PlayerTimeMatchModule.java
new file mode 100644
index 0000000000..8311f403d8
--- /dev/null
+++ b/core/src/main/java/tc/oc/pgm/modules/PlayerTimeMatchModule.java
@@ -0,0 +1,47 @@
+package tc.oc.pgm.modules;
+
+import org.bukkit.event.EventHandler;
+import org.bukkit.event.Listener;
+import tc.oc.pgm.api.match.Match;
+import tc.oc.pgm.api.match.MatchModule;
+import tc.oc.pgm.api.match.MatchScope;
+import tc.oc.pgm.api.player.MatchPlayer;
+import tc.oc.pgm.api.player.event.MatchPlayerAddEvent;
+import tc.oc.pgm.api.setting.SettingKey;
+import tc.oc.pgm.api.setting.SettingValue;
+import tc.oc.pgm.events.ListenerScope;
+
+@ListenerScope(MatchScope.LOADED)
+public class PlayerTimeMatchModule implements MatchModule, Listener {
+
+ private final Match match;
+
+ public PlayerTimeMatchModule(Match match) {
+ this.match = match;
+ }
+
+ @EventHandler
+ public void onPlayerAdded(MatchPlayerAddEvent event) {
+ updatePlayerTime(event.getPlayer());
+ // Upon being added to a match, set the player's preferred time
+ }
+
+ public static void updatePlayerTime(MatchPlayer player) {
+ if (player.getSettings().getValue(SettingKey.TIME).equals(SettingValue.TIME_AUTO)) {
+ player.getBukkit().resetPlayerTime();
+ return;
+ }
+ player.getBukkit().setPlayerTime(getPreferencedTime(player), false);
+ }
+
+ private static long getPreferencedTime(MatchPlayer player) {
+ switch (player.getSettings().getValue(SettingKey.TIME)) {
+ case TIME_DARK:
+ return 18000; // Midnight
+ case TIME_LIGHT:
+ return 6000; // Midday
+ default:
+ return player.getWorld().getFullTime();
+ }
+ }
+}
diff --git a/core/src/main/java/tc/oc/pgm/observers/ObserverToolsInventoryMenuItem.java b/core/src/main/java/tc/oc/pgm/observers/ObserverToolsInventoryMenuItem.java
deleted file mode 100644
index 34e29bf119..0000000000
--- a/core/src/main/java/tc/oc/pgm/observers/ObserverToolsInventoryMenuItem.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package tc.oc.pgm.observers;
-
-import static net.kyori.adventure.text.Component.translatable;
-
-import com.google.common.collect.Lists;
-import java.util.List;
-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.ClickType;
-import tc.oc.pgm.util.menu.InventoryMenu;
-import tc.oc.pgm.util.menu.InventoryMenuItem;
-import tc.oc.pgm.util.text.TextTranslations;
-
-public class ObserverToolsInventoryMenuItem implements InventoryMenuItem {
-
- private final InventoryMenu observerToolsMenu;
-
- public ObserverToolsInventoryMenuItem(InventoryMenu observerToolsMenu) {
- this.observerToolsMenu = observerToolsMenu;
- }
-
- @Override
- public Component getDisplayName() {
- return translatable("setting.displayName", NamedTextColor.AQUA);
- }
-
- @Override
- public List getLore(Player player) {
- return Lists.newArrayList(
- TextTranslations.translateLegacy(
- translatable("setting.lore", NamedTextColor.GRAY), player));
- }
-
- @Override
- public Material getMaterial(Player player) {
- return ObserverToolsMatchModule.TOOL_MATERIAL;
- }
-
- @Override
- public void onInventoryClick(InventoryMenu menu, Player player, ClickType clickType) {
- observerToolsMenu.display(player);
- }
-}
diff --git a/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMatchModule.java b/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMatchModule.java
index b2ec3e2342..492d0307d3 100644
--- a/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMatchModule.java
+++ b/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMatchModule.java
@@ -2,15 +2,16 @@
import static net.kyori.adventure.text.Component.translatable;
-import com.google.common.collect.ImmutableList;
-import java.util.List;
+import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
+import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Material;
+import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
-import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerInteractEvent;
+import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import tc.oc.pgm.api.match.Match;
import tc.oc.pgm.api.match.MatchModule;
@@ -19,14 +20,9 @@
import tc.oc.pgm.api.module.exception.ModuleLoadException;
import tc.oc.pgm.api.player.MatchPlayer;
import tc.oc.pgm.events.ListenerScope;
-import tc.oc.pgm.observers.tools.FlySpeedTool;
-import tc.oc.pgm.observers.tools.GamemodeTool;
-import tc.oc.pgm.observers.tools.NightVisionTool;
-import tc.oc.pgm.observers.tools.VisibilityTool;
import tc.oc.pgm.spawns.events.ObserverKitApplyEvent;
-import tc.oc.pgm.util.menu.InventoryMenu;
-import tc.oc.pgm.util.menu.InventoryMenuItem;
-import tc.oc.pgm.util.menu.pattern.SingleRowMenuArranger;
+import tc.oc.pgm.util.inventory.ItemBuilder;
+import tc.oc.pgm.util.text.TextTranslations;
@ListenerScope(MatchScope.LOADED)
public class ObserverToolsMatchModule implements MatchModule, Listener {
@@ -38,31 +34,16 @@ public ObserverToolsMatchModule createMatchModule(Match match) throws ModuleLoad
}
}
- // Slot where tool item is placed
- public static final int TOOL_BUTTON_SLOT = 8;
-
- // Material of tool item item
+ public static final int TOOL_SLOT = 8;
public static final Material TOOL_MATERIAL = Material.DIAMOND;
+ public static final Component TOOL_NAME =
+ translatable("setting.displayName", NamedTextColor.AQUA, TextDecoration.BOLD);
+ public static final Component TOOL_LORE = translatable("setting.lore", NamedTextColor.GRAY);
private final Match match;
- private final InventoryMenu menu;
- private final InventoryMenuItem toolItem;
public ObserverToolsMatchModule(Match match) {
this.match = match;
-
- final List tools =
- ImmutableList.of(
- new FlySpeedTool(), new NightVisionTool(), new VisibilityTool(), new GamemodeTool());
-
- this.menu =
- new InventoryMenu(
- match.getWorld(),
- translatable("setting.title", NamedTextColor.AQUA),
- tools,
- new SingleRowMenuArranger());
-
- this.toolItem = new ObserverToolsInventoryMenuItem(this.menu);
}
@EventHandler
@@ -75,30 +56,39 @@ public void onToolClick(PlayerInteractEvent event) {
if (isRightClick(event.getAction())) {
ItemStack item = event.getPlayer().getItemInHand();
MatchPlayer player = match.getPlayer(event.getPlayer());
-
- if (item.getType().equals(TOOL_MATERIAL) && player != null && canUse(player)) {
- this.toolItem.onInventoryClick(null, event.getPlayer(), ClickType.RIGHT);
+ if (player != null && item != null && item.isSimilar(createItem(player.getBukkit()))) {
+ openMenu(player);
}
}
}
- public void openMenuManual(MatchPlayer player) {
+ public void openMenu(MatchPlayer player) {
if (canUse(player)) {
- menu.display(player.getBukkit());
+ new ObserverToolsMenu(player);
}
}
- private boolean canUse(MatchPlayer player) {
- return player.isObserving();
- }
-
private void refreshKit(MatchPlayer player) {
if (canUse(player)) {
- player.getInventory().setItem(TOOL_BUTTON_SLOT, toolItem.createItem(player.getBukkit()));
+ player.getInventory().setItem(TOOL_SLOT, createItem(player.getBukkit()));
}
}
+ private boolean canUse(MatchPlayer player) {
+ return player.isObserving();
+ }
+
private boolean isRightClick(Action action) {
return action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK;
}
+
+ private ItemStack createItem(Player player) {
+ return new ItemBuilder()
+ .material(TOOL_MATERIAL)
+ .amount(1)
+ .name(TextTranslations.translateLegacy(TOOL_NAME, player))
+ .lore(TextTranslations.translateLegacy(TOOL_LORE, player))
+ .flags(ItemFlag.values())
+ .build();
+ }
}
diff --git a/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMenu.java b/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMenu.java
new file mode 100644
index 0000000000..38bffebf62
--- /dev/null
+++ b/core/src/main/java/tc/oc/pgm/observers/ObserverToolsMenu.java
@@ -0,0 +1,36 @@
+package tc.oc.pgm.observers;
+
+import com.google.common.collect.Lists;
+import fr.minuskube.inv.content.InventoryContents;
+import java.util.List;
+import net.kyori.adventure.text.format.NamedTextColor;
+import org.bukkit.entity.Player;
+import tc.oc.pgm.api.player.MatchPlayer;
+import tc.oc.pgm.menu.InventoryMenu;
+import tc.oc.pgm.menu.MenuItem;
+import tc.oc.pgm.observers.tools.FlySpeedTool;
+import tc.oc.pgm.observers.tools.GamemodeTool;
+import tc.oc.pgm.observers.tools.NightVisionTool;
+import tc.oc.pgm.observers.tools.SettingsTool;
+
+public class ObserverToolsMenu extends InventoryMenu {
+
+ private List