@@ -56,77 +56,81 @@ void onInventoryClick(InventoryClickEvent event) {
5656 }
5757
5858 // If it's a modifiable inventory, apply specific restrictions for armor/off-hand slots.
59- if (event .getInventory ().getHolder () instanceof ModifiableInventoryHolder ) {
60- int clickedSlot = event .getRawSlot ();
61- ItemStack cursorItem = event .getCursor (); // Item held by the cursor
62- ItemStack currentItem = event .getCurrentItem (); // Item in the clicked slot
63- Player player = (Player ) event .getWhoClicked (); // The player who clicked
59+ if (!(event .getInventory ().getHolder () instanceof ModifiableInventoryHolder )) {
60+ return ;
61+ }
6462
65- // Define the special slots
66- boolean isSpecialSlot = (clickedSlot >= 36 && clickedSlot <= 40 ); // Armor (36-39) and Off-hand (40)
63+ int clickedSlot = event .getRawSlot ();
64+ ItemStack cursorItem = event .getCursor (); // Item held by the cursor
65+ ItemStack currentItem = event .getCurrentItem (); // Item in the clicked slot
66+ Player player = (Player ) event .getWhoClicked (); // The player who clicked
6767
68- // Determine if the slot is one of the padding slots (41-44)
69- boolean isPaddingSlot = (clickedSlot >= 41 && clickedSlot <= 44 );
68+ // Define the special slots
69+ boolean isSpecialSlot = (clickedSlot >= 36 && clickedSlot <= 40 ); // Armor (36-39) and Off-hand (40)
7070
71- if (isPaddingSlot ) {
72- // Clicks on padding slots are always cancelled and do nothing else.
73- event .setCancelled (true );
74- return ;
75- }
71+ // Determine if the slot is one of the padding slots (41-44)
72+ boolean isPaddingSlot = (clickedSlot >= 41 && clickedSlot <= 44 );
7673
77- // --- Logic for special slots (armor/off-hand) ---
78- if (isSpecialSlot ) {
79- boolean currentItemIsFiller = currentItem != null && inventoryGUIHelper .isFillerItem (currentItem );
74+ if (isPaddingSlot ) {
75+ // Clicks on padding slots are always cancelled and do nothing else.
76+ event .setCancelled (true );
77+ return ;
78+ }
8079
81- // Scenario 1: Player tries to pick up a filler item (cursor is empty)
82- if (currentItemIsFiller && (cursorItem == null || cursorItem .getType () == Material .AIR )) {
83- event .setCancelled (true );
84- return ; // Prevent pickup, filler stays in place
85- }
80+ // --- Logic for special slots (armor/off-hand) ---
81+ if (!isSpecialSlot ) {
82+ return ;
83+ }
8684
87- // Scenario 2: Player tries to place an invalid item into a special slot
88- if (cursorItem != null && cursorItem .getType () != Material .AIR && !inventoryGUIHelper .isValidItemForSlot (cursorItem , clickedSlot )) {
89- event .setCancelled (true );
90- return ; // Prevent invalid placement
91- }
85+ boolean currentItemIsFiller = currentItem != null && inventoryGUIHelper .isFillerItem (currentItem );
9286
93- // Scenario 3: Player places a valid item into a special slot that currently holds a filler or a valid item.
94- // Manually handle the swap to ensure fillers don't leave the GUI.
95- if (cursorItem != null && cursorItem .getType () != Material .AIR && inventoryGUIHelper .isValidItemForSlot (cursorItem , clickedSlot )) {
96- event .setCancelled (true ); // Take full control of the event
97-
98- // Place the new item from the cursor into the clicked slot
99- event .getInventory ().setItem (clickedSlot , cursorItem );
100-
101- // If the player tries to replace an item in the filler slot, check if the item is valid.
102- if (currentItem != null && currentItem .getType () != Material .AIR && !inventoryGUIHelper .isFillerItem (currentItem )) {
103- // If the original item was a real, non-filler item, put it on the player's cursor.
104- player .setItemOnCursor (currentItem );
105- } else {
106- // If the original item was null, air, or a filler, clear the player's cursor.
107- player .setItemOnCursor (null );
108- }
109-
110- player .updateInventory (); // Update client to reflect changes
111- return ; // Event handled
112- }
87+ // Scenario 1: Player tries to pick up a filler item (cursor is empty)
88+ if (currentItemIsFiller && (cursorItem == null || cursorItem .getType () == Material .AIR )) {
89+ event .setCancelled (true );
90+ return ; // Prevent pickup, filler stays in place
91+ }
11392
114- // Scenario 4: Player is shift-clicking a valid item from a special slot.
115- // Or picking up a valid item from a special slot.
116- // We need to ensure filler reappears if the slot becomes empty.
117- if (event .getAction () == InventoryAction .MOVE_TO_OTHER_INVENTORY ||
118- event .getAction () == InventoryAction .PICKUP_ALL ||
119- event .getAction () == InventoryAction .PICKUP_HALF ||
120- event .getAction () == InventoryAction .PICKUP_ONE ||
121- event .getAction () == InventoryAction .PICKUP_SOME ) {
122- Bukkit .getScheduler ().runTaskLater (inventories , () -> {
123- // After Bukkit processes the click, if the slot is now empty, put the filler back.
124- if (event .getInventory ().getItem (clickedSlot ) == null || event .getInventory ().getItem (clickedSlot ).getType () == Material .AIR ) {
125- event .getInventory ().setItem (clickedSlot , inventoryGUIHelper .createFillerItemForSlot (clickedSlot , true ));
126- }
127- }, 1L );
128- }
93+ // Scenario 2: Player tries to place an invalid item into a special slot
94+ if (cursorItem != null && cursorItem .getType () != Material .AIR && !inventoryGUIHelper .isValidItemForSlot (cursorItem , clickedSlot )) {
95+ event .setCancelled (true );
96+ return ; // Prevent invalid placement
97+ }
98+
99+ // Scenario 3: Player places a valid item into a special slot that currently holds a filler or a valid item.
100+ // Manually handle the swap to ensure fillers don't leave the GUI.
101+ if (cursorItem != null && cursorItem .getType () != Material .AIR && inventoryGUIHelper .isValidItemForSlot (cursorItem , clickedSlot )) {
102+ event .setCancelled (true ); // Take full control of the event
103+
104+ // Place the new item from the cursor into the clicked slot
105+ event .getInventory ().setItem (clickedSlot , cursorItem );
106+
107+ // If the player tries to replace an item in the filler slot, check if the item is valid.
108+ if (currentItem != null && currentItem .getType () != Material .AIR && !inventoryGUIHelper .isFillerItem (currentItem )) {
109+ // If the original item was a real, non-filler item, put it on the player's cursor.
110+ player .setItemOnCursor (currentItem );
111+ } else {
112+ // If the original item was null, air, or a filler, clear the player's cursor.
113+ player .setItemOnCursor (null );
129114 }
115+
116+ player .updateInventory (); // Update client to reflect changes
117+ return ; // Event handled
118+ }
119+
120+ // Scenario 4: Player is shift-clicking a valid item from a special slot.
121+ // Or picking up a valid item from a special slot.
122+ // We need to ensure filler reappears if the slot becomes empty.
123+ if (event .getAction () == InventoryAction .MOVE_TO_OTHER_INVENTORY ||
124+ event .getAction () == InventoryAction .PICKUP_ALL ||
125+ event .getAction () == InventoryAction .PICKUP_HALF ||
126+ event .getAction () == InventoryAction .PICKUP_ONE ||
127+ event .getAction () == InventoryAction .PICKUP_SOME ) {
128+ Bukkit .getScheduler ().runTaskLater (inventories , () -> {
129+ // After Bukkit processes the click, if the slot is now empty, put the filler back.
130+ if (event .getInventory ().getItem (clickedSlot ) == null || event .getInventory ().getItem (clickedSlot ).getType () == Material .AIR ) {
131+ event .getInventory ().setItem (clickedSlot , inventoryGUIHelper .createFillerItemForSlot (clickedSlot , true ));
132+ }
133+ }, 1L );
130134 }
131135 }
132136
@@ -140,91 +144,94 @@ void onInventoryDrag(InventoryDragEvent event) {
140144 }
141145
142146 // If it's a modifiable inventory, apply specific restrictions for armor/off-hand slots.
143- if (event .getInventory ().getHolder () instanceof ModifiableInventoryHolder ) {
144- ItemStack draggedItem = event .getCursor (); // The item being dragged (after the drag operation)
147+ if (!(event .getInventory ().getHolder () instanceof ModifiableInventoryHolder )) {
148+ return ;
149+ }
145150
146- // If nothing is being dragged, or dragging air, no restriction needed.
147- if (draggedItem == null || draggedItem .getType () == Material .AIR ) {
148- return ;
149- }
150- for (int slot : event .getRawSlots ()) {
151- // Define the special slots
152- boolean isSpecialSlot = (slot >= 36 && slot <= 40 );
151+ ItemStack draggedItem = event .getCursor (); // The item being dragged (after the drag operation)
153152
154- // Determine if the slot is one of the padding slots (41-44)
155- boolean isPaddingSlot = (slot >= 41 && slot <= 44 );
153+ // If nothing is being dragged, or dragging air, no restriction needed.
154+ if (draggedItem == null || draggedItem .getType () == Material .AIR ) {
155+ return ;
156+ }
156157
157- if (isPaddingSlot ) {
158- // Clicks on padding slots are always cancelled and do nothing else.
159- event .setCancelled (true );
160- return ;
161- }
158+ for (int slot : event .getRawSlots ()) {
159+ // Define the special slots
160+ boolean isSpecialSlot = (slot >= 36 && slot <= 40 );
162161
163- if ( isSpecialSlot ) {
164- // Check if the dragged item is valid for this special slot
165- if (! inventoryGUIHelper . isValidItemForSlot ( draggedItem , slot )) { // Use helper
166- event . setCancelled ( true );
167- return ; // Cancel the entire drag event
168- }
169- }
162+ // Determine if the slot is one of the padding slots (41-44)
163+ boolean isPaddingSlot = ( slot >= 41 && slot <= 44 );
164+
165+ if ( isPaddingSlot ) {
166+ // Clicks on padding slots are always cancelled and do nothing else.
167+ event . setCancelled ( true );
168+ return ;
170169 }
171170
172- // After a drag, check if any special slots became empty and replace with filler
173- Bukkit .getScheduler ().runTaskLater (inventories , () -> {
174- for (int slot : event .getRawSlots ()) {
175- if ((slot >= 36 && slot <= 40 ) && (event .getInventory ().getItem (slot ) == null || event .getInventory ().getItem (slot ).getType () == Material .AIR )) {
176- event .getInventory ().setItem (slot , inventoryGUIHelper .createFillerItemForSlot (slot , true )); // Use helper
177- }
178- }
179- }, 1L ); // Run one tick later
171+ // Check if the dragged item is valid for this special slot
172+ if (isSpecialSlot && !inventoryGUIHelper .isValidItemForSlot (draggedItem , slot )) {
173+ event .setCancelled (true );
174+ return ; // Cancel the entire drag event
175+ }
180176 }
177+
178+ // After a drag, check if any special slots became empty and replace with filler
179+ Bukkit .getScheduler ().runTaskLater (inventories , () -> {
180+ for (int slot : event .getRawSlots ()) {
181+ if ((slot >= 36 && slot <= 40 ) && (event .getInventory ().getItem (slot ) == null || event .getInventory ().getItem (slot ).getType () == Material .AIR )) {
182+ event .getInventory ().setItem (slot , inventoryGUIHelper .createFillerItemForSlot (slot , true )); // Use helper
183+ }
184+ }
185+ }, 1L ); // Run one tick later
181186 }
182187
183188 // Event handler for InventoryCloseEvent to save changes
184189 @ EventMethod
185190 @ DefaultEventPriority (EventPriority .NORMAL )
186191 void onInventoryClose (InventoryCloseEvent event ) {
187192 // Check if the closed inventory has the custom ModifiableInventoryHolder class
188- if (event .getInventory ().getHolder () instanceof ModifiableInventoryHolder holder ) {
189- final OfflinePlayer targetPlayer = holder .getTargetPlayer ();
190- final String worldName = holder .getWorldName ();
191- final ProfileType profileType = holder .getProfileType ();
192- final Inventory closedInventory = event .getInventory ();
193-
194- // Extract contents: 0-35 for inventory, 36-39 for armor, 40 for off-hand
195- ItemStack [] newContents = Arrays .copyOfRange (closedInventory .getContents (), 0 , 36 );
196- ItemStack [] newArmor = new ItemStack [4 ];
197- // Map GUI armor slots back to Multiverse-Inventories' expected order [helmet, chestplate, leggings, boots]
198- newArmor [3 ] = closedInventory .getItem (36 ); // Helmet
199- newArmor [2 ] = closedInventory .getItem (37 ); // Chestplate
200- newArmor [1 ] = closedInventory .getItem (38 ); // Leggings
201- newArmor [0 ] = closedInventory .getItem (39 ); // Boots
202- ItemStack newOffHand = closedInventory .getItem (40 );
203-
204- // Before saving, ensure any filler items are removed from the actual data
205- for (int i = 0 ; i < newArmor .length ; i ++) {
206- if (newArmor [i ] != null && inventoryGUIHelper .isFillerItem (newArmor [i ])) {
207- newArmor [i ] = null ; // Replace filler with null for saving
208- }
209- }
210- if (newOffHand != null && inventoryGUIHelper .isFillerItem (newOffHand )) {
211- newOffHand = null ; // Replace filler with null for saving
212- }
193+ if (!(event .getInventory ().getHolder () instanceof ModifiableInventoryHolder holder )) {
194+ return ;
195+ }
213196
214- // Delegate saving to InventoryDataProvider
215- inventoryDataProvider .savePlayerInventoryData (
216- targetPlayer ,
217- worldName ,
218- profileType ,
219- newContents ,
220- newArmor ,
221- newOffHand
222- ).exceptionally (throwable -> {
223- // Error logging is now handled within InventoryDataProvider, but we can add a general one here too
224- Logging .severe ("Error during inventory save process for " + targetPlayer .getName () + ": " + throwable .getMessage ());
225- throwable .printStackTrace ();
226- return null ;
227- });
197+ final OfflinePlayer targetPlayer = holder .getTargetPlayer ();
198+ final String worldName = holder .getWorldName ();
199+ final ProfileType profileType = holder .getProfileType ();
200+ final Inventory closedInventory = event .getInventory ();
201+
202+ // Extract contents: 0-35 for inventory, 36-39 for armor, 40 for off-hand
203+ ItemStack [] newContents = Arrays .copyOfRange (closedInventory .getContents (), 0 , 36 );
204+ ItemStack [] newArmor = new ItemStack [4 ];
205+ // Map GUI armor slots back to Multiverse-Inventories' expected order [helmet, chestplate, leggings, boots]
206+ newArmor [3 ] = closedInventory .getItem (36 ); // Helmet
207+ newArmor [2 ] = closedInventory .getItem (37 ); // Chestplate
208+ newArmor [1 ] = closedInventory .getItem (38 ); // Leggings
209+ newArmor [0 ] = closedInventory .getItem (39 ); // Boots
210+ ItemStack newOffHand = closedInventory .getItem (40 );
211+
212+ // Before saving, ensure any filler items are removed from the actual data
213+ for (int i = 0 ; i < newArmor .length ; i ++) {
214+ if (newArmor [i ] != null && inventoryGUIHelper .isFillerItem (newArmor [i ])) {
215+ newArmor [i ] = null ; // Replace filler with null for saving
216+ }
217+ }
218+ if (newOffHand != null && inventoryGUIHelper .isFillerItem (newOffHand )) {
219+ newOffHand = null ; // Replace filler with null for saving
228220 }
221+
222+ // Delegate saving to InventoryDataProvider
223+ inventoryDataProvider .savePlayerInventoryData (
224+ targetPlayer ,
225+ worldName ,
226+ profileType ,
227+ newContents ,
228+ newArmor ,
229+ newOffHand
230+ ).exceptionally (throwable -> {
231+ // Error logging is now handled within InventoryDataProvider, but we can add a general one here too
232+ Logging .severe ("Error during inventory save process for " + targetPlayer .getName () + ": " + throwable .getMessage ());
233+ throwable .printStackTrace ();
234+ return null ;
235+ });
229236 }
230- }
237+ }
0 commit comments