88import org .jetbrains .annotations .ApiStatus .Internal ;
99import org .jspecify .annotations .Nullable ;
1010import xyz .xenondevs .invui .Click ;
11- import xyz .xenondevs .invui .internal .Viewer ;
1211import xyz .xenondevs .invui .internal .ViewerAtSlot ;
1312import xyz .xenondevs .invui .internal .util .*;
1413import xyz .xenondevs .invui .inventory .Inventory ;
1514import xyz .xenondevs .invui .inventory .ObscuredInventory ;
1615import xyz .xenondevs .invui .inventory .event .ItemPreUpdateEvent ;
1716import xyz .xenondevs .invui .inventory .event .PlayerUpdateReason ;
1817import xyz .xenondevs .invui .inventory .event .UpdateReason ;
19- import xyz .xenondevs .invui .item .*;
18+ import xyz .xenondevs .invui .item .BoundItem ;
19+ import xyz .xenondevs .invui .item .Item ;
20+ import xyz .xenondevs .invui .item .ItemProvider ;
21+ import xyz .xenondevs .invui .item .ItemWrapper ;
2022import xyz .xenondevs .invui .util .ItemUtils ;
2123import xyz .xenondevs .invui .window .AbstractWindow ;
2224import xyz .xenondevs .invui .window .Window ;
3234 */
3335@ Internal
3436public sealed abstract class AbstractGui
35- implements Gui , Viewer
37+ implements Gui
3638 permits NormalGuiImpl , AbstractPagedGui , AbstractScrollGui , TabGuiImpl
3739{
3840
3941 private final int width ;
4042 private final int height ;
4143 private final int size ;
4244 private final @ Nullable SlotElement [] slotElements ;
43- private final @ Nullable Set <ViewerAtSlot <?> >[] viewers ;
45+ private final @ Nullable Set <ViewerAtSlot >[] viewers ;
4446
4547 private boolean frozen ;
4648 private boolean ignoreObscuredInventorySlots = true ;
@@ -78,8 +80,8 @@ public void handleBundleSelect(Player player, int slot, int bundleSlot) {
7880 return ;
7981
8082 SlotElement slotElement = slotElements [slot ];
81- switch (slotElement ) {
82- case SlotElement .GuiLink le -> ((AbstractGui )le .gui ()).handleBundleSelect (player , le .slot (), bundleSlot );
83+ switch (slotElement ) {
84+ case SlotElement .GuiLink le -> ((AbstractGui ) le .gui ()).handleBundleSelect (player , le .slot (), bundleSlot );
8385 case SlotElement .Item ie -> ie .item ().handleBundleSelect (player , bundleSlot );
8486 case SlotElement .InventoryLink ie -> handleInvBundleSelect (player , ie .inventory (), ie .slot (), bundleSlot );
8587 case null -> {}
@@ -240,10 +242,10 @@ private void handleInvNumberKey(Click click, Inventory inventory, int slot) {
240242 AbstractWindow <?> window = (AbstractWindow <?>) WindowManager .getInstance ().getOpenWindow (player );
241243 assert window != null ;
242244
243- Pair < AbstractGui , Integer > pair = window .getGuiAtHotbar (click .hotbarButton ());
244- if (pair == null )
245+ SlotElement . GuiLink link = window .getGuiAtHotbar (click .hotbarButton ());
246+ if (link == null )
245247 return ;
246- SlotElement hotbarElement = pair . first ().getSlotElement (pair . second ());
248+ SlotElement hotbarElement = link . gui ().getSlotElement (link . slot ());
247249 if (hotbarElement == null )
248250 return ;
249251 hotbarElement = hotbarElement .getHoldingElement ();
@@ -413,18 +415,6 @@ public SequencedCollection<? extends Inventory> getInventories(Inventory... igno
413415 }
414416 //</editor-fold>
415417
416- @ Override
417- public void notifyUpdate (int slot ) {
418- synchronized (viewers ) {
419- var viewers = this .viewers [slot ];
420- if (viewers != null ) {
421- for (var viewer : viewers ) {
422- viewer .notifyUpdate ();
423- }
424- }
425- }
426- }
427-
428418 @ Override
429419 public void notifyWindows () {
430420 synchronized (viewers ) {
@@ -455,72 +445,55 @@ public void notifyWindows(int index) {
455445 }
456446 }
457447
458- public void addViewer (Viewer who , int what , int how ) {
448+ public void addViewer (AbstractWindow <?> who , int what , int how ) {
459449 synchronized (viewers ) {
460450 var viewerSet = this .viewers [what ];
461451 if (viewerSet == null ) {
462452 viewerSet = new HashSet <>();
463453 this .viewers [what ] = viewerSet ;
464454 }
465- viewerSet .add (new ViewerAtSlot <> (who , how ));
455+ viewerSet .add (new ViewerAtSlot (who , how ));
466456 }
467457 }
468458
469- public void removeViewer (Viewer who , int what , int how ) {
459+ public void removeViewer (AbstractWindow <?> who , int what , int how ) {
470460 synchronized (viewers ) {
471461 var viewerSet = this .viewers [what ];
472462 if (viewerSet != null ) {
473- viewerSet .remove (new ViewerAtSlot <> (who , how ));
463+ viewerSet .remove (new ViewerAtSlot (who , how ));
474464 if (viewerSet .isEmpty ())
475465 this .viewers [what ] = null ;
476466 }
477467 }
478468 }
479469
480470 @ Override
481- public List <Window > findAllWindows () {
482- // no need for synchronization on viewers because this method is called on-main and read-only
483- var windows = new ArrayList <Window >();
484-
485- var explored = new HashSet <Viewer >();
486- var queue = new LinkedList <Viewer >();
487- queue .add (this );
488-
489- while (!queue .isEmpty ()) {
490- var current = queue .poll ();
491- explored .add (current );
492-
493- if (current instanceof AbstractGui viewable ) {
494- for (var viewers : viewable .viewers ) {
495- if (viewers == null )
496- continue ;
497-
498- for (var viewerAtSlot : viewers ) {
499- var viewer = viewerAtSlot .viewer ();
500- if (!explored .contains (viewer )) {
501- queue .add (viewer );
502- }
471+ public Collection <Window > getWindows () {
472+ synchronized (viewers ) {
473+ var windows = new HashSet <Window >();
474+ for (var viewerSet : viewers ) {
475+ if (viewerSet != null ) {
476+ for (var viewerAtSlot : viewerSet ) {
477+ windows .add (viewerAtSlot .window ());
503478 }
504479 }
505- } else if (current instanceof Window window ) {
506- windows .add (window );
507480 }
481+
482+ return Collections .unmodifiableSet (windows );
508483 }
509-
510- return windows ;
511484 }
512485
513486 @ Override
514- public Set <Player > findAllCurrentViewers () {
515- return findAllWindows ().stream ()
487+ public Collection <Player > getCurrentViewers () {
488+ return getWindows ().stream ()
516489 .filter (Window ::isOpen )
517490 .map (Window ::getViewer )
518- .collect (Collectors .toSet ());
491+ .collect (Collectors .toUnmodifiableSet ());
519492 }
520493
521494 @ Override
522495 public void closeForAllViewers () {
523- findAllCurrentViewers ().forEach (Player ::closeInventory );
496+ getCurrentViewers ().forEach (Player ::closeInventory );
524497 }
525498
526499 @ Override
@@ -573,7 +546,6 @@ public void cancelAnimation() {
573546
574547 @ Override
575548 public void setSlotElement (int index , @ Nullable SlotElement slotElement ) {
576- SlotElement oldElement = slotElements [index ];
577549 slotElements [index ] = slotElement ;
578550
579551 // set the gui if it is a bound item
@@ -583,16 +555,6 @@ public void setSlotElement(int index, @Nullable SlotElement slotElement) {
583555 }
584556 }
585557
586- // remove this gui as a viewer from the old slot element's gui
587- if (oldElement instanceof SlotElement .GuiLink (Gui gui , int slot )) {
588- ((AbstractGui ) gui ).removeViewer (this , slot , index );
589- }
590-
591- // add this gui as a viewer to the new slot element's viewable
592- if (slotElement instanceof SlotElement .GuiLink (Gui gui , int slot )) {
593- ((AbstractGui ) gui ).addViewer (this , slot , index );
594- }
595-
596558 // notify parents that a slot element has been changed
597559 var viewers = this .viewers [index ];
598560 if (viewers != null ) {
0 commit comments