Skip to content

Commit 760dabc

Browse files
Add thread checks for Window#open and Window#close
1 parent 487cf61 commit 760dabc

3 files changed

Lines changed: 26 additions & 4 deletions

File tree

invui/src/main/java/xyz/xenondevs/invui/internal/menu/CustomContainerMenu.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import net.minecraft.world.item.ItemStack;
3333
import net.minecraft.world.item.Items;
3434
import net.minecraft.world.item.component.BundleContents;
35+
import org.bukkit.Bukkit;
3536
import org.bukkit.craftbukkit.entity.CraftPlayer;
3637
import org.bukkit.craftbukkit.inventory.CraftInventory;
3738
import org.bukkit.craftbukkit.inventory.CraftItemStack;
@@ -146,6 +147,8 @@ public Integer apply(TypedDataComponent<?> tdc) {
146147

147148
@Override
148149
public Integer apply(TypedDataComponent<?> tdc) {
150+
assert Bukkit.isOwnedByCurrentRegion(player);
151+
149152
var c = tdc.value();
150153
var cachedValue = cache.get(c);
151154
if (cachedValue.isPresent())
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package xyz.xenondevs.invui.internal.util;
2+
3+
import org.bukkit.Bukkit;
4+
import org.bukkit.entity.Entity;
5+
6+
public class ThreadCheck {
7+
8+
public static void checkOwnedBy(Entity entity) {
9+
if (Bukkit.isOwnedByCurrentRegion(entity))
10+
return;
11+
12+
throw new IllegalArgumentException(
13+
"A method was called from an incorrect thread. On Paper the correct thread is the server thread. " +
14+
"On Folia, the correct thread is the thread that owns the viewer (use the viewer's entity scheduler). " +
15+
"Note that the absence of this exception does not imply correctness. In general and unless otherwise documented, " +
16+
"nothing in InvUI is thread-safe and all methods should be called from the corresponding viewer's thread."
17+
);
18+
}
19+
20+
}

invui/src/main/java/xyz/xenondevs/invui/window/AbstractWindow.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@
2626
import xyz.xenondevs.invui.internal.menu.CustomContainerMenu;
2727
import xyz.xenondevs.invui.internal.menu.UpdateType;
2828
import xyz.xenondevs.invui.internal.menu.WindowEventListener;
29-
import xyz.xenondevs.invui.internal.util.CollectionUtils;
30-
import xyz.xenondevs.invui.internal.util.FakeInventoryView;
31-
import xyz.xenondevs.invui.internal.util.FuncUtils;
32-
import xyz.xenondevs.invui.internal.util.InventoryUtils;
29+
import xyz.xenondevs.invui.internal.util.*;
3330
import xyz.xenondevs.invui.inventory.CompositeInventory;
3431
import xyz.xenondevs.invui.inventory.Inventory;
3532
import xyz.xenondevs.invui.inventory.InventorySlot;
@@ -504,6 +501,7 @@ public void open() {
504501
throw new IllegalStateException("Opening a window is not allowed to trigger opening another window.");
505502
if (isInCloseHandlerContext.get() > 0)
506503
throw new IllegalStateException("Opening a window is not allowed while handling window close. Consider setting a fallback window or scheduling a task instead.");
504+
ThreadCheck.checkOwnedBy(viewer);
507505

508506
try {
509507
isInOpeningContext.set(true);
@@ -549,6 +547,7 @@ protected void postItemInit() {
549547

550548
@Override
551549
public void close() {
550+
ThreadCheck.checkOwnedBy(getViewer());
552551
if (isOpen()) {
553552
viewer.closeInventory(); // WindowManager then calls handleClose
554553
}

0 commit comments

Comments
 (0)