2020
2121public final class GUIEvents implements Listener {
2222
23- private void handleDoubleClick (GUI gui , InventoryClickEvent event ) {
24- GUIEventHandler eventHandler = gui .getEventHandler ();
25-
26- Inventory guiInventory = gui .getInventory ();
27- int size = guiInventory .getSize ();
28- ItemStack cursor = event .getCursor ();
23+ private static InventoryClickEvent getClickEventWithSlot (InventoryClickEvent clickEvent , int slot ) {
24+ return new InventoryClickEvent (
25+ clickEvent .getView (),
26+ clickEvent .getSlotType (),
27+ slot ,
28+ clickEvent .getClick (),
29+ clickEvent .getAction ()
30+ );
31+ }
2932
30- if (event .getCurrentItem () != null )
33+ private static void handleDoubleClick (GUI gui , InventoryClickEvent clickEvent ) {
34+ if (clickEvent .getCurrentItem () != null ) {
3135 return ;
36+ }
3237
38+ Inventory inventory = gui .getInventory ();
39+ ItemStack cursor = clickEvent .getCursor ();
3340 int totalAmount = cursor .getAmount ();
34- List <InventoryClickEvent > clickEvents = new ArrayList <>();
41+ int maxAmount = cursor .getMaxStackSize ();
42+ int size = inventory .getSize ();
43+ List <Integer > changedSlots = new ArrayList <>();
3544 for (int slot = 0 ; slot < size ; slot ++) {
36- ItemStack item = guiInventory .getItem (slot );
37- if (item != null && item .isSimilar (cursor )) {
38- if (!gui .isChangeable (gui .convert (slot ))) {
39- event .setCancelled (true );
40- return ;
41- }
45+ ItemStack item = inventory .getItem (slot );
46+ if (item == null || !item .isSimilar (cursor )) { // not a candidate for merging
47+ continue ;
48+ }
4249
43- if (totalAmount < cursor .getMaxStackSize ()) {
44- InventoryClickEvent clickEvent = getClickEventWithSlot (event , slot );
45- clickEvents .add (clickEvent );
46- totalAmount += item .getAmount ();
47- }
50+ if (!gui .isChangeable (gui .convert (slot ))) { // would result in merging of an unchangeable slot
51+ clickEvent .setCancelled (true );
52+ return ;
53+ }
54+
55+ changedSlots .add (slot );
56+ totalAmount += item .getAmount ();
57+ if (totalAmount >= maxAmount ) { // no other slots will be changed
58+ break ;
4859 }
4960 }
50- for (InventoryClickEvent clickEvent : clickEvents ) {
51- eventHandler .onChange (clickEvent );
52- }
53- }
5461
55- private static InventoryClickEvent getClickEventWithSlot (InventoryClickEvent event , int slot ) {
56- return new InventoryClickEvent (
57- event .getView (),
58- event .getSlotType (),
59- slot ,
60- event .getClick (),
61- event .getAction ()
62- );
62+ GUIEventHandler eventHandler = gui .getEventHandler ();
63+ for (int slot : changedSlots ) {
64+ eventHandler .onChange (getClickEventWithSlot (clickEvent , slot ));
65+ }
6366 }
6467
6568 @ EventHandler (priority = EventPriority .LOWEST )
66- public void onInventoryClick (InventoryClickEvent event ) {
67- // Process this event if it's cancelled ONLY if the clicker is in Spectator Mode
68- if (event .getWhoClicked ().getGameMode () != GameMode .SPECTATOR && event .isCancelled ()) {
69+ public void onInventoryClick (InventoryClickEvent clickEvent ) {
70+ // Process this event if it's canceled ONLY if the clicker is in Spectator Mode
71+ if (clickEvent .getWhoClicked ().getGameMode () != GameMode .SPECTATOR && clickEvent .isCancelled ()) {
6972 return ;
7073 }
7174
7275 // Don't handle this event if it's from an unsupported click type
73- switch (event .getClick ()) {
76+ switch (clickEvent .getClick ()) {
7477 case WINDOW_BORDER_RIGHT :
7578 case WINDOW_BORDER_LEFT :
7679 case CREATIVE :
7780 return ;
7881 }
7982
8083 // No inventory was clicked
81- Inventory clickedInventory = event .getClickedInventory ();
84+ Inventory clickedInventory = clickEvent .getClickedInventory ();
8285 if (clickedInventory == null ) {
8386 return ;
8487 }
8588
8689 // Don't handle this event if there isn't a matching GUI for it
87- GUI gui = SkriptGUI .getGUIManager ().getGUI (event .getInventory ());
90+ GUI gui = SkriptGUI .getGUIManager ().getGUI (clickEvent .getInventory ());
8891 if (gui == null ) {
8992 return ;
9093 }
9194 GUIEventHandler eventHandler = gui .getEventHandler ();
9295
9396 // Don't process unknown clicks for safety reasons - cancel them to prevent unwanted GUI changes
94- if (event .getClick () == ClickType .UNKNOWN ) {
95- event .setCancelled (true );
97+ if (clickEvent .getClick () == ClickType .UNKNOWN ) {
98+ clickEvent .setCancelled (true );
9699 return ;
97100 }
98101
99102 // Don't handle this event if the clicked inventory is the bottom inventory, as we want users to be able to interact with their inventory
100103 // However, there are some cases where interaction with the bottom inventory may cause changes to the top inventory
101104 // Because of this, we will cancel the event for some click types
102- if (clickedInventory .equals (event .getView ().getBottomInventory ())) {
103- switch (event .getClick ()) {
105+ if (clickedInventory .equals (clickEvent .getView ().getBottomInventory ())) {
106+ switch (clickEvent .getClick ()) {
104107 case SHIFT_LEFT :
105108 case SHIFT_RIGHT :
106- ItemStack clicked = event .getCurrentItem ();
107- if (clicked != null ) {
108- Inventory guiInventory = gui .getInventory ();
109+ ItemStack clicked = clickEvent .getCurrentItem ();
110+ if (clicked == null ) {
111+ clickEvent .setCancelled (true );
112+ return ;
113+ }
109114
110- int size = guiInventory .getSize ();
111- int totalAmount = clicked .getAmount ();
115+ Inventory guiInventory = gui .getInventory ();
112116
113- for (int slot = 0 ; slot < size ; slot ++) {
114- if (totalAmount <= 0 ) {
115- return ;
116- }
117+ int size = guiInventory .getSize ();
118+ int totalAmount = clicked .getAmount ();
117119
118- ItemStack item = guiInventory .getItem (slot );
119- if (item != null && item .getType () != Material .AIR && item .isSimilar (clicked ) && item .getAmount () < item .getMaxStackSize ()) {
120- InventoryClickEvent clickEvent = getClickEventWithSlot (event , slot );
121-
122- if (!gui .isChangeable (gui .convert (slot ))) {
123- event .setCancelled (true );
124- return ;
125- } else {
126- eventHandler .onChange (clickEvent );
127- totalAmount -= item .getMaxStackSize () - item .getAmount ();
128- }
120+ List <Integer > changedSlots = new ArrayList <>();
121+ for (int slot = 0 ; slot < size ; slot ++) {
122+ ItemStack item = guiInventory .getItem (slot );
123+ if (item != null && item .getType () != Material .AIR && item .isSimilar (clicked ) && item .getAmount () < item .getMaxStackSize ()) {
124+ if (!gui .isChangeable (gui .convert (slot ))) { // Would result in a non-changeable slot being changed, thus block
125+ clickEvent .setCancelled (true );
126+ return ;
129127 }
130-
128+ // slot will have some amount distributed to it
129+ changedSlots .add (slot );
130+ totalAmount -= item .getMaxStackSize () - item .getAmount ();
131+ }
132+ if (totalAmount <= 0 ) {
133+ break ;
131134 }
135+ }
132136
137+ if (totalAmount > 0 ) {
133138 int firstEmpty = guiInventory .firstEmpty ();
134- if (firstEmpty != -1 && gui .isChangeable (gui .convert (firstEmpty ))) { // Safe to be moved into the GUI
135- InventoryClickEvent clickEvent = getClickEventWithSlot (event , firstEmpty );
136- eventHandler .onChange (clickEvent );
137- return ;
139+ if (firstEmpty != -1 ) {
140+ if (!gui .isChangeable (gui .convert (firstEmpty ))) { // slot would be illegally modified
141+ clickEvent .setCancelled (true );
142+ return ;
143+ }
144+ // the rest of the item can go in this slot
145+ changedSlots .add (firstEmpty );
138146 }
139-
140147 }
141148
142- event .setCancelled (true );
149+ for (int slot : changedSlots ) {
150+ eventHandler .onChange (getClickEventWithSlot (clickEvent , slot ));
151+ }
143152 return ;
144153 case DOUBLE_CLICK :
145- // Only cancel if this will cause a change to the GUI itself
146- // We are checking if our GUI contains an item that could be merged with the event item
147- // If that item is mergeable, but it isn't changeable, we will cancel the event now
148- handleDoubleClick (gui , event );
154+ handleDoubleClick (gui , clickEvent );
149155 return ;
150156 default :
151157 return ;
152158 }
153- } else {
154- // Call onChange if a slot is changed due to interactions within the gui itself
155- if (event .getClick () == ClickType .DOUBLE_CLICK ) {
156- if (!gui .isChangeable (gui .convert (event .getSlot ()))) { // Doesn't change the slots
157- event .setCancelled (true );
158- return ;
159- }
160-
161- handleDoubleClick (gui , event );
162- }
159+ } else if (clickEvent .getClick () == ClickType .DOUBLE_CLICK && gui .isChangeable (gui .convert (clickEvent .getSlot ()))) {
160+ // a double click (merge operation) can only occur if the source slot can be modified
161+ handleDoubleClick (gui , clickEvent );
163162 }
164163
165- gui .getEventHandler ().onClick (event );
164+ gui .getEventHandler ().onClick (clickEvent );
166165 }
167166
168167 @ EventHandler (priority = EventPriority .LOWEST , ignoreCancelled = true )
@@ -184,26 +183,26 @@ public void onInventoryDrag(InventoryDragEvent dragEvent) {
184183 }
185184
186185 @ EventHandler (priority = EventPriority .LOWEST , ignoreCancelled = true )
187- public void onInventoryOpen (InventoryOpenEvent event ) {
188- GUI gui = SkriptGUI .getGUIManager ().getGUI (event .getInventory ());
186+ public void onInventoryOpen (InventoryOpenEvent openEvent ) {
187+ GUI gui = SkriptGUI .getGUIManager ().getGUI (openEvent .getInventory ());
189188 if (gui != null ) {
190- gui .getEventHandler ().onOpen (event );
189+ gui .getEventHandler ().onOpen (openEvent );
191190 }
192191 }
193192
194193 @ EventHandler (priority = EventPriority .LOWEST )
195- public void onInventoryClose (InventoryCloseEvent event ) {
196- GUI gui = SkriptGUI .getGUIManager ().getGUI (event .getInventory ());
194+ public void onInventoryClose (InventoryCloseEvent closeEvent ) {
195+ GUI gui = SkriptGUI .getGUIManager ().getGUI (closeEvent .getInventory ());
197196 if (gui != null ) {
198- gui .getEventHandler ().onClose (event );
197+ gui .getEventHandler ().onClose (closeEvent );
199198 }
200199 }
201200
202201 @ EventHandler (priority = EventPriority .LOWEST , ignoreCancelled = true )
203- public void onRecipeBookClick (PlayerRecipeBookClickEvent event ) {
204- GUI gui = SkriptGUI .getGUIManager ().getGUI (event .getPlayer ().getOpenInventory ().getTopInventory ());
202+ public void onRecipeBookClick (PlayerRecipeBookClickEvent recipeEvent ) {
203+ GUI gui = SkriptGUI .getGUIManager ().getGUI (recipeEvent .getPlayer ().getOpenInventory ().getTopInventory ());
205204 if (gui != null ) {
206- event .setCancelled (true );
205+ recipeEvent .setCancelled (true );
207206 }
208207 }
209208
0 commit comments