Skip to content
9 changes: 5 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,11 @@ dependencies {

compileOnly(libs.papi)

implementation(libs.nashorn)
implementation(libs.adventure.platform)
implementation(libs.adventure.minimessage)
implementation(libs.bstats)
implementation(libs.nashorn)
implementation(libs.adventure.platform)
implementation(libs.adventure.minimessage)
implementation(libs.adventure.legacy)
implementation(libs.bstats)

compileOnly("org.jetbrains:annotations:23.0.0")
}
Expand Down
12 changes: 7 additions & 5 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ bstats = "3.1.0"

# Implementation
nashorn = "15.6"
adventure-platform = "4.4.1"
adventure-minimessage = "4.24.0"
adventure-platform = "4.4.1"
adventure-minimessage = "4.24.0"
adventure-legacy = "4.24.0"

[libraries]
# Compile only
Expand All @@ -39,6 +40,7 @@ sig = { module = "io.github.valerashimchuck:simpleitemgenerator-api", version.re

# Implementation
nashorn = { module = "org.openjdk.nashorn:nashorn-core", version.ref = "nashorn" }
adventure-platform = { module = "net.kyori:adventure-platform-bukkit", version.ref = "adventure-platform" }
adventure-minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure-minimessage" }
bstats = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" }
adventure-platform = { module = "net.kyori:adventure-platform-bukkit", version.ref = "adventure-platform" }
adventure-minimessage = { module = "net.kyori:adventure-text-minimessage", version.ref = "adventure-minimessage" }
adventure-legacy = { module = "net.kyori:adventure-text-serializer-legacy", version.ref = "adventure-legacy" }
bstats = { module = "org.bstats:bstats-bukkit", version.ref = "bstats" }
35 changes: 24 additions & 11 deletions src/main/java/com/extendedclip/deluxemenus/DeluxeMenus.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import com.extendedclip.deluxemenus.command.DeluxeMenusCommand;
import com.extendedclip.deluxemenus.config.DeluxeMenusConfig;
import com.extendedclip.deluxemenus.config.GeneralConfig;
import com.extendedclip.deluxemenus.dupe.DupeFixer;
import com.extendedclip.deluxemenus.dupe.MenuItemMarker;
import com.extendedclip.deluxemenus.hooks.*;
import com.extendedclip.deluxemenus.dupe.DupeFixer;
import com.extendedclip.deluxemenus.dupe.MenuItemMarker;
import com.extendedclip.deluxemenus.editor.MenuEditorListener;
import com.extendedclip.deluxemenus.editor.WebEditorServer;
import com.extendedclip.deluxemenus.hooks.*;
import com.extendedclip.deluxemenus.listener.PlayerListener;
import com.extendedclip.deluxemenus.menu.Menu;
import com.extendedclip.deluxemenus.menu.MenuItem;
Expand Down Expand Up @@ -65,7 +67,8 @@ public class DeluxeMenus extends JavaPlugin {
private Map<String, ItemHook> itemHooks;

private final GeneralConfig generalConfig = new GeneralConfig(this);
private DeluxeMenusConfig menuConfig;
private DeluxeMenusConfig menuConfig;
private WebEditorServer webEditorServer;

@NotNull
private final TaskScheduler scheduler = UniversalScheduler.getScheduler(this);
Expand Down Expand Up @@ -109,7 +112,9 @@ public void onEnable() {
debug(DebugLevel.HIGHEST, Level.WARNING, "Failed to load from config.yml. Use /dm reload after fixing your errors.");
}

new PlayerListener(this).register();
this.webEditorServer = new WebEditorServer(this);
new PlayerListener(this).register();
new MenuEditorListener(this).register();
if (!new DeluxeMenusCommand(this).register()) {
debug(DebugLevel.HIGHEST, Level.SEVERE, "Could not register the DeluxeMenus command!");
}
Expand All @@ -131,9 +136,13 @@ public void onDisable() {
this.audiences = null;
}

Menu.unloadForShutdown(this);

itemHooks.clear();
Menu.unloadForShutdown(this);
if (this.webEditorServer != null) {
this.webEditorServer.stop();
this.webEditorServer = null;
}

itemHooks.clear();

HandlerList.unregisterAll(this);
}
Expand Down Expand Up @@ -197,9 +206,13 @@ public MenuItemMarker getMenuItemMarker() {
return menuItemMarker;
}

public DeluxeMenusConfig getConfiguration() {
return menuConfig;
}
public DeluxeMenusConfig getConfiguration() {
return menuConfig;
}

public WebEditorServer getWebEditorServer() {
return webEditorServer;
}

public VaultHook getVault() {
return vaultHook;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,11 @@ public enum ActionType {
"- [message] <message>"),
LOG("[log]", "Log a message to the console", "- [log] <level> <message>"),
BROADCAST("[broadcast]", "Broadcast a message to the server", "- '[broadcast] <message>"),
CHAT("[chat]", "Send a chat message as the player performing the action", "- '[chat] <message>"),
OPEN_GUI_MENU("[openguimenu]", "Open a GUI menu", "- '[openguimenu] <menu-name>'"),
OPEN_MENU("[openmenu]", "Open a GUI menu", "- '[openmenu] <menu-name>'"),
CHAT("[chat]", "Send a chat message as the player performing the action", "- '[chat] <message>"),
OPEN_GUI_MENU("[openguimenu]", "Open a GUI menu", "- '[openguimenu] <menu-name>'"),
OPEN_GUI_INVENTORY("[open_gui_inventory]", "Open a GUI menu in the player inventory area",
"- '[open_gui_inventory] <menu-name>'"),
OPEN_MENU("[openmenu]", "Open a GUI menu", "- '[openmenu] <menu-name>'"),
CONNECT("[connect]", "Connect to the specified bungee server", "- '[connect] <serverName>'"),
CLOSE("[close]", "Close the viewers open menu", "- '[close]"),
REFRESH("[refresh]", "Refresh items in the current menu view", "- '[refresh]"),
Expand Down
199 changes: 116 additions & 83 deletions src/main/java/com/extendedclip/deluxemenus/action/ClickActionTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,12 @@ public class ClickActionTask extends UniversalRunnable {

private final DeluxeMenus plugin;
private final TaskScheduler scheduler;
private final UUID uuid;
private final ActionType actionType;
private final String exec;
// Ugly hack to get around the fact that arguments are not available at task execution time
private final Map<String, String> arguments;
private final boolean parsePlaceholdersInArguments;
private final boolean parsePlaceholdersAfterArguments;
private final UUID uuid;
private final ActionType actionType;
private final String exec;
private final Map<String, String> arguments;
private final boolean parsePlaceholdersInArguments;
private final boolean parsePlaceholdersAfterArguments;

public ClickActionTask(
@NotNull final DeluxeMenus plugin,
Expand Down Expand Up @@ -168,10 +167,10 @@ public void run() {
Menu.closeMenu(plugin, player, true, true);
break;

case OPEN_GUI_MENU:
case OPEN_MENU:
final String temporaryExecutable = executable.replaceAll("\\s+", " ").replace(" ", " ");
final String[] executableParts = temporaryExecutable.split(" ", 2);
case OPEN_GUI_MENU:
case OPEN_MENU:
final String temporaryExecutable = executable.replaceAll("\\s+", " ").replace(" ", " ");
final String[] executableParts = temporaryExecutable.split(" ", 2);

if (executableParts.length == 0) {
plugin.debug(DebugLevel.HIGHEST, Level.WARNING, "Could not find and open menu " + executable);
Expand All @@ -187,9 +186,10 @@ public void run() {
break;
}

final Menu menuToOpen = optionalMenuToOpen.get();

final List<String> menuArgumentNames = menuToOpen.options().arguments();
final Menu menuToOpen = optionalMenuToOpen.get();
final Menu playerInventoryMenuToKeep = getPlayerInventoryMenuToKeep(holder, menuToOpen);

final List<String> menuArgumentNames = menuToOpen.options().arguments();

String[] passedArgumentValues = null;
if (executableParts.length > 1) {
Expand All @@ -204,26 +204,25 @@ public void run() {
"Arguments were given for menu " + menuName + " in action [openguimenu] or [openmenu], but the menu does not support arguments!"
);
}

if (holder.isEmpty()) {
menuToOpen.openMenu(player);
break;
}

menuToOpen.openMenu(player, holder.get().getTypedArgs(), holder.get().getPlaceholderPlayer());
break;
}

if (passedArgumentValues == null || passedArgumentValues.length == 0) {
// Replicate old behavior: If no arguments are given, open the menu with the arguments from the current menu
if (holder.isEmpty()) {
menuToOpen.openMenu(player);
break;
}

menuToOpen.openMenu(player, holder.get().getTypedArgs(), holder.get().getPlaceholderPlayer());
break;
}

if (holder.isEmpty()) {
menuToOpen.openMenu(player, null, null, null);
break;
}

menuToOpen.openMenu(player, holder.get().getTypedArgs(), holder.get().getPlaceholderPlayer(), playerInventoryMenuToKeep);
break;
}

if (passedArgumentValues == null || passedArgumentValues.length == 0) {
if (holder.isEmpty()) {
menuToOpen.openMenu(player, null, null, null);
break;
}

menuToOpen.openMenu(player, holder.get().getTypedArgs(), holder.get().getPlaceholderPlayer(), playerInventoryMenuToKeep);
break;
}

if (passedArgumentValues.length < menuArgumentNames.size()) {
plugin.debug(
Expand All @@ -234,47 +233,69 @@ public void run() {
break;
}

final Map<String, String> argumentsMap = new HashMap<>();
if (holder.isPresent() && holder.get().getTypedArgs() != null) {
// Pass the arguments from the current menu to the new menu. If the new menu has arguments with the
// same name, they will be overwritten
argumentsMap.putAll(holder.get().getTypedArgs());
}
final Map<String, String> argumentsMap = new HashMap<>();
if (holder.isPresent() && holder.get().getTypedArgs() != null) {
argumentsMap.putAll(holder.get().getTypedArgs());
}

for (int index = 0; index < menuArgumentNames.size(); index++) {
final String argumentName = menuArgumentNames.get(index);

if (passedArgumentValues.length <= index) {
// This should never be the case!
plugin.debug(
DebugLevel.HIGHEST,
Level.WARNING,
final String argumentName = menuArgumentNames.get(index);

if (passedArgumentValues.length <= index) {
plugin.debug(
DebugLevel.HIGHEST,
Level.WARNING,
"Not enough arguments given for menu " + menuName + " when opening using the [openguimenu] or [openmenu] action!"
);
break;
}

if (menuArgumentNames.size() == index + 1) {
// If this is the last argument, get all remaining values and join them
final String lastArgumentValue = String.join(" ", Arrays.asList(passedArgumentValues).subList(index, passedArgumentValues.length));
argumentsMap.put(argumentName, lastArgumentValue);
break;
}

if (menuArgumentNames.size() == index + 1) {
final String lastArgumentValue = String.join(" ", Arrays.asList(passedArgumentValues).subList(index, passedArgumentValues.length));
argumentsMap.put(argumentName, lastArgumentValue);
break;
}

argumentsMap.put(argumentName, passedArgumentValues[index]);
}

if (holder.isEmpty()) {
menuToOpen.openMenu(player, argumentsMap, null);
break;
}

menuToOpen.openMenu(player, argumentsMap, holder.get().getPlaceholderPlayer());
break;

case CONNECT:
plugin.connect(player, executable);
break;

if (holder.isEmpty()) {
menuToOpen.openMenu(player, argumentsMap, null, null);
break;
}

menuToOpen.openMenu(player, argumentsMap, holder.get().getPlaceholderPlayer(), playerInventoryMenuToKeep);
break;

case OPEN_GUI_INVENTORY:
if (holder.isEmpty()) {
plugin.debug(
DebugLevel.HIGHEST,
Level.WARNING,
"Cannot open player inventory menu " + executable + " because no DeluxeMenus menu is open."
);
break;
}

final String inventoryExecutable = executable.replaceAll("\\s+", " ").trim();
if (inventoryExecutable.isBlank()) {
plugin.debug(DebugLevel.HIGHEST, Level.WARNING, "Could not find and open player inventory menu " + executable);
break;
}

final String inventoryMenuName = inventoryExecutable.split(" ", 2)[0];
final Optional<Menu> optionalInventoryMenu = Menu.getSubMenuByName(inventoryMenuName);
if (optionalInventoryMenu.isEmpty()) {
plugin.debug(DebugLevel.HIGHEST, Level.WARNING, "Could not find and open player inventory menu " + executable);
break;
}

holder.get().openPlayerInventoryMenu(optionalInventoryMenu.get());
break;

case CONNECT:
plugin.connect(player, executable);
break;

case JSON_MESSAGE:
AdventureUtils.sendJson(plugin, player, executable);
Expand Down Expand Up @@ -508,26 +529,38 @@ public void run() {
}
break;

case PLAY_SOUND:
if (sound == null) {
plugin.debug(
DebugLevel.HIGHEST,
Level.WARNING,
"Sound name given for sound action: " + executable + ", is not a valid sound!"
);
break;
}
player.playSound(player.getLocation(), sound, volume, pitch);
break;
}
break;
case PLAY_SOUND:
if (sound == null) {
plugin.debug(
DebugLevel.HIGHEST,
Level.WARNING,
"Sound name given for sound action: " + executable + ", is not a valid sound!"
);
break;
}
player.playSound(player.getLocation(), sound, volume, pitch);
break;
}
break;

default:
break;
}
}

private boolean isRaw(ActionType actionType) {
return actionType == ActionType.PLAY_RAW_SOUND || actionType == ActionType.BROADCAST_RAW_SOUND || actionType == ActionType.BROADCAST_WORLD_RAW_SOUND;
}
}
private boolean isRaw(ActionType actionType) {
return actionType == ActionType.PLAY_RAW_SOUND || actionType == ActionType.BROADCAST_RAW_SOUND || actionType == ActionType.BROADCAST_WORLD_RAW_SOUND;
}

private Menu getPlayerInventoryMenuToKeep(final @NotNull Optional<MenuHolder> holder, final @NotNull Menu menuToOpen) {
if (menuToOpen.options().playerInventoryMenu().isPresent()) {
return null;
}

if (holder.isEmpty() || !holder.get().getMenuName().equalsIgnoreCase(menuToOpen.options().name())) {
return null;
}

return holder.flatMap(MenuHolder::getRenderedPlayerInventoryMenu).orElse(null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,16 @@ public List<String> onTabComplete(
private void registerSubCommands() {
final List<SubCommand> commands = List.of(
new DumpCommand(plugin),
new DebugCommand(plugin),
new EditCommand(plugin),
new ExecuteCommand(plugin),
new HelpCommand(plugin),
new ListCommand(plugin),
new MetaCommand(plugin),
new OpenCommand(plugin),
new RefreshCommand(plugin),
new ReloadCommand(plugin)
new ReloadCommand(plugin),
new WebEditorCommand(plugin)
);

for (final SubCommand subCommand : commands) {
Expand Down
Loading