@@ -307,79 +307,74 @@ private class ListenUp implements Listener {
307307
308308 @ EventHandler
309309 public void onInventoryClick (InventoryClickEvent event ) {
310- if (!event .getInventory ().equals (inventory )) {
311- return ;
312- }
310+ if (!event .getInventory ().equals (inventory )) return ;
313311
314312 final int rawSlot = event .getRawSlot ();
315- // ignore items dropped outside the window
316- if (rawSlot == -999 ) return ;
313+ if (rawSlot == -999 ) return ; // outside
317314
318315 final Player clicker = (Player ) event .getWhoClicked ();
319316 final Inventory clickedInventory = event .getClickedInventory ();
320-
321- if (clickedInventory != null ) {
322- if (clickedInventory .equals (clicker .getInventory ())) {
323- // prevent players from merging items from the anvil inventory
324- if (event .getClick ().equals (ClickType .DOUBLE_CLICK )) {
325- event .setCancelled (true );
326- return ;
327- }
328- // prevent shift moving items from players inv to the anvil inventory
329- if (event .isShiftClick ()) {
330- event .setCancelled (true );
331- return ;
332- }
333- }
334- // prevent players from swapping items in the anvil gui
335- if ((event .getCursor () != null && event .getCursor ().getType () != Material .AIR )
336- && !interactableSlots .contains (rawSlot )
337- && event .getClickedInventory ().equals (inventory )) {
338- event .setCancelled (true );
339- return ;
340- }
317+ final InventoryAction action = event .getAction ();
318+ final ClickType clickType = event .getClick ();
319+
320+ // ---- 在庫移動系は全面禁止(どこをクリックしても潰す)----
321+ if (action == InventoryAction .MOVE_TO_OTHER_INVENTORY // Shift移動
322+ || action == InventoryAction .COLLECT_TO_CURSOR // ダブルクリック回収
323+ || action == InventoryAction .HOTBAR_MOVE_AND_READD // ホットバー移動
324+ || action == InventoryAction .HOTBAR_SWAP // ホットバースワップ
325+ || clickType == ClickType .DOUBLE_CLICK
326+ || clickType == ClickType .NUMBER_KEY ) {
327+ event .setCancelled (true );
328+ return ;
341329 }
342330
343- if (rawSlot < 3 && rawSlot >= 0 || event .getAction ().equals (InventoryAction .MOVE_TO_OTHER_INVENTORY )) {
344- event .setCancelled (!interactableSlots .contains (rawSlot ));
345- if (clickHandlerRunning && !concurrentClickHandlerExecution ) {
346- // A click handler is running, don't launch another one
331+ if (clickedInventory != null && clickedInventory .equals (inventory )) {
332+ // ---- AnvilGUI 側の全クリックは常にキャンセルしてアイテム移動を阻止 ----
333+ event .setCancelled (true );
334+
335+ // カーソルに何か持って非ボタンスロットを触るスワップも阻止(保険)
336+ if ((event .getCursor () != null && event .getCursor ().getType () != Material .AIR )
337+ && !interactableSlots .contains (rawSlot )) {
347338 return ;
348339 }
349340
350- final CompletableFuture <List <ResponseAction >> actionsFuture =
351- clickHandler .apply (rawSlot , StateSnapshot .fromAnvilGUI (AnvilGUI .this ));
352-
353- final Consumer <List <ResponseAction >> actionsConsumer = actions -> {
354- for (final ResponseAction action : actions ) {
355- action .accept (AnvilGUI .this , clicker );
341+ // ---- ボタンスロット(0〜2)は機能だけ実行(アイテムは動かない:cancel済み)----
342+ if (rawSlot >= 0 && rawSlot < 3 && interactableSlots .contains (rawSlot )) {
343+ if (clickHandlerRunning && !concurrentClickHandlerExecution ) return ;
344+
345+ final CompletableFuture <List <ResponseAction >> actionsFuture =
346+ clickHandler .apply (rawSlot , StateSnapshot .fromAnvilGUI (AnvilGUI .this ));
347+
348+ final Consumer <List <ResponseAction >> actionsConsumer = actions -> {
349+ for (final ResponseAction action2 : actions ) {
350+ action2 .accept (AnvilGUI .this , clicker );
351+ }
352+ };
353+
354+ if (actionsFuture .isDone ()) {
355+ actionsFuture .thenAccept (actionsConsumer ).join ();
356+ } else {
357+ clickHandlerRunning = true ;
358+ actionsFuture
359+ .thenAcceptAsync (actionsConsumer , mainThreadExecutor )
360+ .handle ((results , exception ) -> {
361+ if (exception != null ) {
362+ plugin .getLogger ()
363+ .log (
364+ Level .SEVERE ,
365+ "An exception occurred in the AnvilGUI clickHandler" ,
366+ exception );
367+ }
368+ clickHandlerRunning = false ;
369+ return null ;
370+ });
356371 }
357- };
358-
359- if (actionsFuture .isDone ()) {
360- // Fast-path without scheduling if clickHandler is performed in sync
361- // Because the future is already completed, .join() will not block the server thread
362- actionsFuture .thenAccept (actionsConsumer ).join ();
363- } else {
364- clickHandlerRunning = true ;
365- // If the plugin is disabled and the Executor throws an exception, the exception will be passed to
366- // the .handle method
367- actionsFuture
368- .thenAcceptAsync (actionsConsumer , mainThreadExecutor )
369- .handle ((results , exception ) -> {
370- if (exception != null ) {
371- plugin .getLogger ()
372- .log (
373- Level .SEVERE ,
374- "An exception occurred in the AnvilGUI clickHandler" ,
375- exception );
376- }
377- // Whether an exception occurred or not, set running to false
378- clickHandlerRunning = false ;
379- return null ;
380- });
381372 }
373+ return ; // Anvil側はここですべて処理完了(アイテムは動かない)
382374 }
375+
376+ // ---- プレイヤーインベントリ側も基本は何も動かさない(全面停止)----
377+ event .setCancelled (true );
383378 }
384379
385380 @ EventHandler
0 commit comments