Skip to content

Commit 403b7f9

Browse files
mtbarrdevnatan
andauthored
feat: add player quit event handling to close viewer context (#810)
Co-authored-by: Natan <[email protected]>
1 parent d6a9068 commit 403b7f9

File tree

2 files changed

+80
-40
lines changed

2 files changed

+80
-40
lines changed

inventory-framework-platform-bukkit/src/main/java/me/devnatan/inventoryframework/IFInventoryListener.java

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import org.bukkit.event.inventory.InventoryType;
1717
import org.bukkit.event.player.PlayerDropItemEvent;
1818
import org.bukkit.event.player.PlayerPickupItemEvent;
19+
import org.bukkit.event.player.PlayerQuitEvent;
1920
import org.bukkit.event.server.PluginDisableEvent;
2021
import org.bukkit.inventory.Inventory;
2122
import org.bukkit.inventory.PlayerInventory;
@@ -35,28 +36,51 @@ public void onPluginDisable(final PluginDisableEvent event) {
3536
viewFrame.unregister();
3637
}
3738

38-
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
39-
public void onInventoryClick(final InventoryClickEvent event) {
40-
if (!(event.getWhoClicked() instanceof Player)) return;
41-
42-
final Player player = (Player) event.getWhoClicked();
39+
@EventHandler
40+
public void onPlayerQuit(PlayerQuitEvent event) {
41+
final Player player = (Player) event.getPlayer();
4342
final Viewer viewer = viewFrame.getViewer(player);
4443
if (viewer == null) return;
4544

46-
final IFRenderContext context = viewer.getActiveContext();
47-
final Component clickedComponent = context.getComponentsAt(event.getRawSlot()).stream()
48-
.filter(Component::isVisible)
49-
.findFirst()
50-
.orElse(null);
51-
final ViewContainer clickedContainer = event.getClickedInventory() instanceof PlayerInventory
52-
? viewer.getSelfContainer()
53-
: context.getContainer();
54-
45+
final IFRenderContext context = viewer.getCurrentContext();
5546
final RootView root = context.getRoot();
56-
final IFSlotClickContext clickContext = root.getElementFactory()
57-
.createSlotClickContext(event.getRawSlot(), viewer, clickedContainer, clickedComponent, event, false);
47+
final IFCloseContext closeContext = root.getElementFactory().createCloseContext(viewer, context, event);
5848

59-
root.getPipeline().execute(StandardPipelinePhases.CLICK, clickContext);
49+
root.getPipeline().execute(StandardPipelinePhases.CLOSE, closeContext);
50+
}
51+
52+
@EventHandler(priority = EventPriority.LOW, ignoreCancelled = true)
53+
public void onInventoryClick(final InventoryClickEvent event) {
54+
if (!(event.getWhoClicked() instanceof Player)) return;
55+
56+
final Player player = (Player) event.getWhoClicked();
57+
try {
58+
final Viewer viewer = viewFrame.getViewer(player);
59+
if (viewer == null) return;
60+
61+
final IFRenderContext context = viewer.getActiveContext();
62+
final Component clickedComponent = context.getComponentsAt(event.getRawSlot()).stream()
63+
.filter(Component::isVisible)
64+
.findFirst()
65+
.orElse(null);
66+
final ViewContainer clickedContainer = event.getClickedInventory() instanceof PlayerInventory
67+
? viewer.getSelfContainer()
68+
: context.getContainer();
69+
70+
final RootView root = context.getRoot();
71+
final IFSlotClickContext clickContext = root.getElementFactory()
72+
.createSlotClickContext(
73+
event.getRawSlot(), viewer, clickedContainer, clickedComponent, event, false);
74+
75+
root.getPipeline().execute(StandardPipelinePhases.CLICK, clickContext);
76+
} catch (Exception e) {
77+
// TODO custom error handling to customize on error behavior
78+
viewFrame
79+
.getOwner()
80+
.getLogger()
81+
.severe("An error occurred while processing an inventory click event: " + e.getMessage());
82+
player.closeInventory();
83+
}
6084
}
6185

6286
@SuppressWarnings("unused")

inventory-framework-platform/src/main/java/me/devnatan/inventoryframework/PlatformView.java

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
import java.util.concurrent.CompletableFuture;
1212
import java.util.function.Function;
1313
import java.util.function.Supplier;
14-
import me.devnatan.inventoryframework.component.*;
14+
15+
import me.devnatan.inventoryframework.component.ComponentFactory;
16+
import me.devnatan.inventoryframework.component.ItemComponentBuilder;
17+
import me.devnatan.inventoryframework.component.Pagination;
18+
import me.devnatan.inventoryframework.component.PaginationStateBuilder;
19+
import me.devnatan.inventoryframework.component.PaginationValueConsumer;
1520
import me.devnatan.inventoryframework.context.IFCloseContext;
1621
import me.devnatan.inventoryframework.context.IFConfinedContext;
1722
import me.devnatan.inventoryframework.context.IFContext;
@@ -70,6 +75,7 @@ protected PlatformView() {
7075
}
7176

7277
// region Open & Close
78+
7379
/**
7480
* Closes all contexts that are currently active in this view.
7581
*/
@@ -111,32 +117,38 @@ final String open(List<Viewer> viewers, Object initialData) {
111117
/**
112118
* Opens an already active context to a viewer.
113119
*
114-
* @param contextId The id of the context.
115-
* @param viewer The viewer to open the context to.
120+
* @param contextId The id of the context.
121+
* @param viewer The viewer to open the context to.
116122
* @param initialData Initial data.
117123
*/
118124
@SuppressWarnings("unchecked")
119125
final void open(String contextId, Viewer viewer, Object initialData) {
120-
IFRenderContext targetContext = null;
121-
for (final IFContext context : getInternalContexts()) {
122-
if (context.getId().toString().equals(contextId)) {
123-
targetContext = (IFRenderContext) context;
124-
break;
126+
try {
127+
IFRenderContext targetContext = null;
128+
for (final IFContext context : getInternalContexts()) {
129+
if (context.getId().toString().equals(contextId)) {
130+
targetContext = (IFRenderContext) context;
131+
break;
132+
}
125133
}
126-
}
127134

128-
if (targetContext == null) throw new IllegalArgumentException("Context not found: " + contextId);
129-
if (!targetContext.isActive()) throw new IllegalStateException("Invalidated");
130-
131-
viewer.setActiveContext(targetContext);
132-
onViewerAdded((TContext) targetContext, (TViewer) viewer.getPlatformInstance(), initialData);
133-
targetContext.addViewer(viewer);
134-
getFramework().addViewer(viewer);
135-
viewer.open(targetContext.getContainer());
135+
if (targetContext == null) throw new IllegalArgumentException("Context not found: " + contextId);
136+
if (!targetContext.isActive()) throw new IllegalStateException("Invalidated");
137+
138+
viewer.setActiveContext(targetContext);
139+
onViewerAdded((TContext) targetContext, (TViewer) viewer.getPlatformInstance(), initialData);
140+
targetContext.addViewer(viewer);
141+
getFramework().addViewer(viewer);
142+
viewer.open(targetContext.getContainer());
143+
} catch (Exception e) {
144+
viewer.close();
145+
e.printStackTrace(); // todo use custom error handler
146+
}
136147
}
137148
// endregion
138149

139150
// region Navigation
151+
140152
/**
141153
* <p><b><i>This is an internal inventory-framework API that should not be used from outside of
142154
* this library. No compatibility guarantees are provided.</i></b>
@@ -236,6 +248,7 @@ public final void back(@NotNull Viewer viewer, Object initialData) {
236248
}
237249

238250
// region Contexts
251+
239252
/**
240253
* Returns the context that is linked to the specified viewer in this view.
241254
* <p>
@@ -387,14 +400,15 @@ public final Iterator<TContext> iterator() {
387400
}
388401

389402
// region Refs API
403+
390404
/**
391405
* Creates a new unassigned reference instance.
392406
* <p>
393407
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
394408
* such API may be changed or may be removed completely in any further release. </i></b>
395409
*
396-
* @return A new unassigned {@link Ref} instance.
397410
* @param <E> Type of the element hold by this reference.
411+
* @return A new unassigned {@link Ref} instance.
398412
* @see <a href="https://github.com/DevNatan/inventory-framework/wiki/refs-api">Refs API on Wiki</a>
399413
*/
400414
@ApiStatus.Experimental
@@ -408,8 +422,8 @@ protected final <E> Ref<E> ref() {
408422
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
409423
* such API may be changed or may be removed completely in any further release. </i></b>
410424
*
411-
* @return A new unassigned {@link Ref} instance.
412425
* @param <E> Type of the element hold by this reference.
426+
* @return A new unassigned {@link Ref} instance.
413427
* @see <a href="https://github.com/DevNatan/inventory-framework/wiki/refs-api">Refs API on Wiki</a>
414428
*/
415429
@ApiStatus.Experimental
@@ -419,6 +433,7 @@ protected final <E> Ref<List<E>> multiRefs() {
419433
// endregion
420434

421435
// region Public Platform Handlers
436+
422437
/**
423438
* Called when the view is about to be configured, the returned object will be the view's
424439
* configuration.
@@ -516,9 +531,9 @@ public void onResume(@NotNull TContext origin, @NotNull TContext target) {}
516531
* <b><i> This API is experimental and is not subject to the general compatibility guarantees
517532
* such API may be changed or may be removed completely in any further release. </i></b>
518533
*
519-
* @param context The context.
520-
* @param viewer Who was added to the context.
521-
* @param data Initial data set wen the viewer was added.
534+
* @param context The context.
535+
* @param viewer Who was added to the context.
536+
* @param data Initial data set wen the viewer was added.
522537
*/
523538
@ApiStatus.OverrideOnly
524539
@ApiStatus.Experimental
@@ -533,14 +548,15 @@ public void onViewerAdded(@NotNull TContext context, @NotNull TViewer viewer, Ob
533548
* such API may be changed or may be removed completely in any further release. </i></b>
534549
*
535550
* @param context The context.
536-
* @param viewer Who was removed from the context.
551+
* @param viewer Who was removed from the context.
537552
*/
538553
@ApiStatus.OverrideOnly
539554
@ApiStatus.Experimental
540555
public void onViewerRemoved(@NotNull TContext context, @NotNull TViewer viewer) {}
541556
// endregion
542557

543558
// region Internals
559+
544560
/**
545561
* <p><b><i>This is an internal inventory-framework API that should not be used from outside of
546562
* this library. No compatibility guarantees are provided.</i></b>

0 commit comments

Comments
 (0)