Add more command operation types, add panel item cooldown

This commit is contained in:
halogly 2025-10-28 16:25:34 +08:00
parent c1edb95f8a
commit fe8699d6af
14 changed files with 190 additions and 299 deletions

3
.idea/.gitignore vendored
View File

@ -1,3 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml

View File

@ -3,8 +3,6 @@
<component name="Encoding">
<file url="file://$PROJECT_DIR$/panels" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource_editor" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/resource_example" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src" charset="UTF-8" />
</component>
</project>

View File

@ -1,16 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="MismatchedCollectionQueryUpdate" enabled="false" level="WARNING" enabled_by_default="false">
<option name="queryNames">
<value />
</option>
<option name="updateNames">
<value />
</option>
<option name="ignoredClasses">
<value />
</option>
</inspection_tool>
</profile>
</component>

View File

@ -11,31 +11,6 @@
<option name="name" value="jitpack.io" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="jeff-media-public" />
<option name="name" value="jeff-media-public" />
<option name="url" value="https://hub.jeff-media.com/nexus/repository/jeff-media-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="io.papermc" />
<option name="name" value="io.papermc" />
<option name="url" value="https://papermc.io/repo/repository/maven-releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="sonatype" />
<option name="name" value="sonatype" />
<option name="url" value="https://oss.sonatype.org/content/groups/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="io.papermc" />
<option name="name" value="io.papermc" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="codemc-repo" />
<option name="name" value="codemc-repo" />
<option name="url" value="https://repo.codemc.io/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="opencollab-snapshot" />
<option name="name" value="opencollab-snapshot" />
@ -46,66 +21,16 @@
<option name="name" value="placeholderapi" />
<option name="url" value="https://repo.extendedclip.com/content/repositories/placeholderapi/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="oraxen" />
<option name="name" value="Oraxen Repository" />
<option name="url" value="https://repo.oraxen.com/#/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="phoenix" />
<option name="name" value="phoenix" />
<option name="url" value="https://nexus.phoenixdevt.fr/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BenCodez Repo" />
<option name="name" value="BenCodez Repo" />
<option name="url" value="https://nexus.bencodez.com/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="oraxen" />
<option name="name" value="Oraxen Repository" />
<option name="url" value="https://repo.oraxen.com/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="papermc" />
<option name="name" value="papermc" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="jitpack-repo" />
<option name="name" value="jitpack-repo" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="ess-repo" />
<option name="name" value="ess-repo" />
<option name="url" value="https://repo.essentialsx.net/releases/" />
</remote-repository>
<remote-repository>
<option name="id" value="spigot-repo" />
<option name="name" value="spigot-repo" />
<option name="url" value="https://hub.spigotmc.org/nexus/content/repositories/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="skript-releases" />
<option name="name" value="Skript Repository" />
<option name="url" value="https://repo.skriptlang.org/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="jeff-media-public" />
<option name="name" value="jeff-media-public" />
<option name="url" value="https://repo.jeff-media.com/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="reposilite-repository-releases" />
<option name="name" value="Reposilite Repository" />
<option name="url" value="https://repo.nexomc.com/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
@ -117,9 +42,14 @@
<option name="url" value="https://maven.devs.beer/" />
</remote-repository>
<remote-repository>
<option name="id" value="minecraft-repo" />
<option name="name" value="minecraft-repo" />
<option name="url" value="https://libraries.minecraft.net/" />
<option name="id" value="phoenix" />
<option name="name" value="phoenix" />
<option name="url" value="https://nexus.phoenixdevt.fr/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="papermc" />
<option name="name" value="papermc" />
<option name="url" value="https://repo.papermc.io/repository/maven-public/" />
</remote-repository>
</component>
</project>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: net.kyori:adventure-api:4.11.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-api/4.11.0/adventure-api-4.11.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-api/4.11.0/adventure-api-4.11.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-api/4.11.0/adventure-api-4.11.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: net.kyori:adventure-key:4.11.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-key/4.11.0/adventure-key-4.11.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-key/4.11.0/adventure-key-4.11.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-key/4.11.0/adventure-key-4.11.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,13 +0,0 @@
<component name="libraryTable">
<library name="Maven: net.kyori:adventure-text-minimessage:4.11.0">
<CLASSES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-text-minimessage/4.11.0/adventure-text-minimessage-4.11.0.jar!/" />
</CLASSES>
<JAVADOC>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-text-minimessage/4.11.0/adventure-text-minimessage-4.11.0-javadoc.jar!/" />
</JAVADOC>
<SOURCES>
<root url="jar://$MAVEN_REPOSITORY$/net/kyori/adventure-text-minimessage/4.11.0/adventure-text-minimessage-4.11.0-sources.jar!/" />
</SOURCES>
</library>
</component>

View File

@ -1,3 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
@ -7,5 +8,5 @@
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="21" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_24" project-jdk-name="21" project-jdk-type="JavaSDK" />
</project>

View File

@ -1,124 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.png" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.png" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.png" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.png" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

View File

@ -7,4 +7,15 @@
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
</content>
</component>
<component name="FacetManager">
<facet type="minecraft" name="Minecraft">
<configuration>
<autoDetectTypes>
<platformType>PAPER</platformType>
<platformType>ADVENTURE</platformType>
</autoDetectTypes>
<projectReimportVersion>1</projectReimportVersion>
</configuration>
</facet>
</component>
</module>

View File

@ -22,7 +22,7 @@ public class HeadDatabaseComponent implements MaterialComponent {
api = new HeadDatabaseAPI();
return api.getItemHead(head);
} else {
ctx.text.sendWarn(player, Message.REQUIRE_HEADDATABASE);
ctx.text.sendWarn(player, Message.REQUIRE_HEAD_DATABASE);
}
return null;
}

View File

@ -21,14 +21,15 @@ import java.util.List;
import java.util.Map;
public class InventoryPanel extends Panel implements InventoryHolder {
private final String rows;
private final Map<String, PanelItem> items = new HashMap<>();
private final Map<String, List<String>> slots = new HashMap<>();
private final CommandActions outside;
private final CommandActions close;
private final String rows;
private final String floodgate;
private final String inventoryLock;
private final String updateDelay;
private final String inventoryLock;
private final String itemCooldown;
public InventoryPanel(String name, YamlConfiguration config) {
super(name, config);
@ -37,6 +38,7 @@ public class InventoryPanel extends Panel implements InventoryHolder {
this.floodgate = config.getString("floodgate", "");
this.updateDelay = config.getString("update-delay", "20");
this.inventoryLock = config.getString("inventory-lock", "false");
this.itemCooldown = config.getString("item-cooldown", "0");
outside = new CommandActions(
config.getStringList("outside.requirements"),
@ -81,10 +83,9 @@ public class InventoryPanel extends Panel implements InventoryHolder {
}
}
if(isNewPanelSession) {
if (isNewPanelSession) {
// Don't open same panel if its already open
if(!canOpen(player, ctx)){
if (!canOpen(player, ctx)) {
return;
}
updatePanelData(ctx, player);
@ -93,7 +94,7 @@ public class InventoryPanel extends Panel implements InventoryHolder {
RequirementRunner requirements = new RequirementRunner(ctx);
CommandRunner commands = new CommandRunner(ctx);
CommandActions actions = this.getOpenCommands();
if(!requirements.processRequirements(this, player, actions.requirements())){
if (!requirements.processRequirements(this, player, actions.requirements())) {
commands.runCommands(this, player, actions.fail());
return;
}
@ -104,17 +105,13 @@ public class InventoryPanel extends Panel implements InventoryHolder {
PanelBuilder builder = new InventoryPanelBuilder(ctx, player);
builder.open(this);
if(isNewPanelSession) {
if (isNewPanelSession) {
// Start a panel updater
InventoryPanelUpdater updater = new InventoryPanelUpdater();
updater.start(ctx, player, this);
}
}
public String getRows() {
return rows;
}
public Map<String, PanelItem> getItems() {
return items;
}
@ -123,10 +120,6 @@ public class InventoryPanel extends Panel implements InventoryHolder {
return slots;
}
public String getUpdateDelay() {
return updateDelay;
}
public CommandActions getOutsideCommands() {
return outside;
}
@ -135,14 +128,25 @@ public class InventoryPanel extends Panel implements InventoryHolder {
return close;
}
public String getRows() {
return rows;
}
public String getUpdateDelay() {
return updateDelay;
}
public String getInventoryLock() {
return inventoryLock;
}
public String getItemCooldown() {
return itemCooldown;
}
// For InventoryHolder implementation
@Override
public Inventory getInventory() {
return null;
}
}

View File

@ -4,7 +4,9 @@ import me.rockyhawk.commandpanels.session.CommandActions;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public record PanelItem(
String id,
@ -17,10 +19,16 @@ public record PanelItem(
String animate,
String conditions,
CommandActions actions,
CommandActions mouseActions,
CommandActions keyActions,
CommandActions leftClick,
CommandActions rightClick,
CommandActions shiftLeftClick,
CommandActions shiftRightClick,
CommandActions drop,
CommandActions ctrlDrop,
CommandActions swapOffhand,
Map<Integer, CommandActions> numberKeys,
String damage,
String itemModel,
String customModelData,
@ -43,10 +51,16 @@ public record PanelItem(
String animate,
String conditions,
CommandActions actions,
CommandActions mouseActions,
CommandActions keyActions,
CommandActions leftClick,
CommandActions rightClick,
CommandActions shiftLeftClick,
CommandActions shiftRightClick,
CommandActions drop,
CommandActions ctrlDrop,
CommandActions swapOffhand,
Map<Integer, CommandActions> numberKeys,
String damage,
String itemModel,
String customModelData,
@ -68,10 +82,16 @@ public record PanelItem(
this.animate = animate;
this.conditions = conditions;
this.actions = actions;
this.mouseActions = mouseActions;
this.keyActions = keyActions;
this.leftClick = leftClick;
this.rightClick = rightClick;
this.shiftLeftClick = shiftLeftClick;
this.shiftRightClick = shiftRightClick;
this.drop = drop;
this.ctrlDrop = ctrlDrop;
this.swapOffhand = swapOffhand;
this.numberKeys = numberKeys;
this.damage = damage;
this.itemModel = itemModel;
this.customModelData = customModelData;
@ -95,10 +115,23 @@ public record PanelItem(
String conditions = section.getString("conditions", "");
CommandActions actions = CommandActions.fromSection(section.getConfigurationSection("actions"));
CommandActions mouseActions = CommandActions.fromSection(section.getConfigurationSection("mouse-actions"));
CommandActions keyActions = CommandActions.fromSection(section.getConfigurationSection("key-actions"));
CommandActions leftClick = CommandActions.fromSection(section.getConfigurationSection("left-click"));
CommandActions rightClick = CommandActions.fromSection(section.getConfigurationSection("right-click"));
CommandActions shiftLeftClick = CommandActions.fromSection(section.getConfigurationSection("shift-left-click"));
CommandActions shiftRightClick = CommandActions.fromSection(section.getConfigurationSection("shift-right-click"));
CommandActions drop = CommandActions.fromSection(section.getConfigurationSection("drop"));
CommandActions ctrlDrop = CommandActions.fromSection(section.getConfigurationSection("ctrl-drop"));
CommandActions swapOffhand = CommandActions.fromSection(section.getConfigurationSection("swap-offhand"));
Map<Integer, CommandActions> numberKeys = new HashMap<>();
for (int i = 1; i <= 9; i++) {
ConfigurationSection keySection = section.getConfigurationSection("key-" + i);
if (keySection != null) {
numberKeys.put(i, CommandActions.fromSection(keySection));
}
}
String damage = section.getString("damage", "0");
String itemModel = section.getString("item-model", null);
@ -123,10 +156,16 @@ public record PanelItem(
animate,
conditions,
actions,
mouseActions,
keyActions,
leftClick,
rightClick,
shiftLeftClick,
shiftRightClick,
drop,
ctrlDrop,
swapOffhand,
numberKeys,
damage,
itemModel,
customModelData,
@ -141,13 +180,38 @@ public record PanelItem(
}
public CommandActions getClickActions(ClickType clickType) {
if(!actions.requirements().isEmpty() || !actions.commands().isEmpty()) return actions;
if (!actions.requirements().isEmpty() || !actions.commands().isEmpty()) return actions;
boolean isMouseClick =
clickType == ClickType.LEFT ||
clickType == ClickType.RIGHT ||
clickType == ClickType.SHIFT_LEFT ||
clickType == ClickType.SHIFT_RIGHT;
if (isMouseClick && (!mouseActions.requirements().isEmpty() || !mouseActions.commands().isEmpty())) return mouseActions;
// Check keyboard actions
// Excluding number keys, which are handled separately
boolean isKeyClick =
clickType == ClickType.DROP ||
clickType == ClickType.CONTROL_DROP ||
clickType == ClickType.SWAP_OFFHAND;
if (isKeyClick && (!keyActions.requirements().isEmpty() || !keyActions.commands().isEmpty())) return keyActions;
// LEFT case defaults
return switch (clickType) {
case RIGHT -> rightClick;
case SHIFT_LEFT -> shiftLeftClick;
case SHIFT_RIGHT -> shiftRightClick;
case DROP -> drop;
case CONTROL_DROP -> ctrlDrop;
case SWAP_OFFHAND -> swapOffhand;
default -> leftClick;
};
}
public CommandActions getNumberKeyAction(int number) {
if (!actions.requirements().isEmpty() || !actions.commands().isEmpty()) return actions;
if (!keyActions.requirements().isEmpty() || !keyActions.commands().isEmpty()) return keyActions;
return numberKeys.getOrDefault(number, new CommandActions(List.of(), List.of(), List.of()));
}
}

View File

@ -1,6 +1,7 @@
package me.rockyhawk.commandpanels.session.inventory.listeners;
import me.rockyhawk.commandpanels.Context;
import me.rockyhawk.commandpanels.formatter.language.Message;
import me.rockyhawk.commandpanels.interaction.commands.CommandRunner;
import me.rockyhawk.commandpanels.interaction.commands.RequirementRunner;
import me.rockyhawk.commandpanels.session.CommandActions;
@ -40,9 +41,8 @@ public class ClickEvents implements Listener {
// Cancel player inventory click if locked
if (e.getClickedInventory() != null) {
boolean isLocked = Boolean.parseBoolean(
ctx.text.parseTextToString(player,panel.getInventoryLock()));
if(isLocked) e.setCancelled(true);
boolean isLocked = Boolean.parseBoolean(ctx.text.parseTextToString(player, panel.getInventoryLock()));
if (isLocked) e.setCancelled(true);
}
}
@ -54,7 +54,7 @@ public class ClickEvents implements Listener {
// Run outside command actions
CommandActions actions = panel.getOutsideCommands();
if(!requirements.processRequirements(panel, player, actions.requirements())){
if (!requirements.processRequirements(panel, player, actions.requirements())) {
commands.runCommands(panel, player, actions.fail());
return;
}
@ -92,12 +92,30 @@ public class ClickEvents implements Listener {
player.getPersistentDataContainer().set(lastClick, PersistentDataType.LONG, currentMillis);
String itemId = container.get(baseIdKey, PersistentDataType.STRING);
PanelItem panelItem = panel.getItems().get(itemId);
if (isItemOnCooldown(player, panel)) {
int remainingTicks = getRemainingCooldownTicks(player, panel);
if (remainingTicks > 0) {
double remainingSeconds = remainingTicks / 20.0;
ctx.text.sendError(player, Message.ITEM_COOLDOWN, String.format("%.1f", remainingSeconds));
}
return;
}
// Check valid interaction types
switch (e.getClick()) {
case LEFT, RIGHT, SHIFT_LEFT, SHIFT_RIGHT -> {
PanelItem panelItem = panel.getItems().get(itemId);
case LEFT, RIGHT, SHIFT_LEFT, SHIFT_RIGHT, DROP, CONTROL_DROP, SWAP_OFFHAND -> {
CommandActions actions = panelItem.getClickActions(e.getClick());
if(!requirements.processRequirements(panel, player, actions.requirements())){
if (!requirements.processRequirements(panel, player, actions.requirements())) {
commands.runCommands(panel, player, actions.fail());
return;
}
commands.runCommands(panel, player, actions.commands());
}
case NUMBER_KEY -> {
int numberKey = e.getHotbarButton() + 1;
CommandActions actions = panelItem.getNumberKeyAction(numberKey);
if (!requirements.processRequirements(panel, player, actions.requirements())) {
commands.runCommands(panel, player, actions.fail());
return;
}
@ -112,19 +130,16 @@ public class ClickEvents implements Listener {
@EventHandler
public void onInventoryDrag(InventoryDragEvent event) {
Inventory topInventory = event.getView().getTopInventory();
if(!(topInventory.getHolder() instanceof InventoryPanel)) return;
if (!(topInventory.getHolder() instanceof InventoryPanel)) return;
// Only care about drag targets in the top inventory
int topSize = topInventory.getSize();
boolean draggingOverPanelItem = event.getRawSlots().stream()
.filter(slot -> slot < topSize) // only slots in the top inventory
boolean draggingOverPanelItem = event.getRawSlots().stream().filter(slot -> slot < topSize) // only slots in the top inventory
.anyMatch(slot -> {
var item = topInventory.getItem(slot);
if (item == null || !item.hasItemMeta()) return false;
var meta = item.getItemMeta();
return meta.getPersistentDataContainer().has(
new NamespacedKey(ctx.plugin, "item_id"), PersistentDataType.STRING
);
return meta.getPersistentDataContainer().has(new NamespacedKey(ctx.plugin, "item_id"), PersistentDataType.STRING);
});
if (draggingOverPanelItem) {
@ -132,5 +147,55 @@ public class ClickEvents implements Listener {
}
}
public boolean isItemOnCooldown(Player player, InventoryPanel panel) {
int cooldownTicks = getItemCooldownTicks(player, panel);
if (cooldownTicks <= 0) return false;
NamespacedKey cooldownKey = new NamespacedKey(ctx.plugin, "item_cooldown");
PersistentDataContainer container = player.getPersistentDataContainer();
Long lastUseTime = container.get(cooldownKey, PersistentDataType.LONG);
long currentTime = System.currentTimeMillis();
if (lastUseTime != null) {
long elapsedTicks = (currentTime - lastUseTime) / 50;
if (elapsedTicks < cooldownTicks) return true;
}
container.set(cooldownKey, PersistentDataType.LONG, currentTime);
return false;
}
public int getRemainingCooldownTicks(Player player, InventoryPanel panel) {
NamespacedKey cooldownKey = new NamespacedKey(ctx.plugin, "item_cooldown");
PersistentDataContainer container = player.getPersistentDataContainer();
Long lastUseTime = container.get(cooldownKey, PersistentDataType.LONG);
if (lastUseTime == null) {
return 0;
}
long currentTime = System.currentTimeMillis();
long elapsedTicks = (currentTime - lastUseTime) / 50;
int cooldownTicks = getItemCooldownTicks(player, panel);
return Math.max(0, cooldownTicks - (int) elapsedTicks);
}
public int getItemCooldownTicks(Player player, InventoryPanel panel) {
if (panel == null) {
return 0;
}
String panelCooldownStr = ctx.text.parseTextToString(player, panel.getItemCooldown());
if (panelCooldownStr.trim().isEmpty()) {
return 0;
}
try {
return Math.max(0, Integer.parseInt(panelCooldownStr.trim()));
} catch (NumberFormatException e) {
return 0;
}
}
}