ChestCommands/plugin/src/main/java/me/filoghost/chestcommands/listener/InventoryListener.java

107 lines
3.7 KiB
Java

/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.chestcommands.listener;
import me.filoghost.chestcommands.ChestCommands;
import me.filoghost.chestcommands.api.ClickResult;
import me.filoghost.chestcommands.api.Icon;
import me.filoghost.chestcommands.api.Menu;
import me.filoghost.chestcommands.config.Settings;
import me.filoghost.chestcommands.inventory.DefaultMenuView;
import me.filoghost.chestcommands.logging.Errors;
import me.filoghost.chestcommands.menu.InternalMenu;
import me.filoghost.chestcommands.menu.MenuManager;
import me.filoghost.fcommons.logging.Log;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.Inventory;
import java.util.Map;
import java.util.WeakHashMap;
public class InventoryListener implements Listener {
private final Map<Player, Long> antiClickSpam = new WeakHashMap<>();
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = false)
public void onInteract(PlayerInteractEvent event) {
if (event.hasItem() && event.getAction() != Action.PHYSICAL) {
MenuManager.openMenuByItem(event.getPlayer(), event.getItem(), event.getAction());
}
}
@EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = false)
public void onEarlyInventoryClick(InventoryClickEvent event) {
if (MenuManager.isMenuInventory(event.getInventory())) {
// Cancel the event as early as possible
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = false)
public void onLateInventoryClick(InventoryClickEvent event) {
Inventory inventory = event.getInventory();
DefaultMenuView menuView = MenuManager.getOpenMenuView(inventory);
if (menuView == null) {
return;
}
// Cancel the event again just in case a plugin un-cancels it
event.setCancelled(true);
int slot = event.getRawSlot();
Player clicker = (Player) event.getWhoClicked();
Icon icon = menuView.getIcon(slot);
if (icon == null) {
return;
}
Long cooldownUntil = antiClickSpam.get(clicker);
long now = System.currentTimeMillis();
int minDelay = Settings.anti_click_spam_delay;
if (minDelay > 0) {
if (cooldownUntil != null && cooldownUntil > now) {
return;
} else {
antiClickSpam.put(clicker, now + minDelay);
}
}
// Only handle the click AFTER the event has finished
Bukkit.getScheduler().runTask(ChestCommands.getInstance(), () -> {
try {
ClickResult result = icon.onClick(menuView, clicker);
if (result == ClickResult.CLOSE) {
clicker.closeInventory();
}
} catch (Throwable t) {
handleIconClickException(menuView.getMenu(), t);
}
});
}
private void handleIconClickException(Menu menu, Throwable throwable) {
String menuDescription;
if (menu.getPlugin() == ChestCommands.getInstance()) {
menuDescription = "the menu \"" + Errors.formatPath(((InternalMenu) menu).getSourceFile()) + "\"";
} else {
menuDescription = "a menu created by the plugin \"" + menu.getPlugin().getName() + "\"";
}
Log.severe("Encountered exception while handling a click inside " + menuDescription, throwable);
}
}