Skip to content

Commit 2ed3857

Browse files
Fix async items
1 parent 5a65f3c commit 2ed3857

3 files changed

Lines changed: 81 additions & 24 deletions

File tree

invui/src/main/java/xyz/xenondevs/invui/item/CustomBoundItem.java

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515
import xyz.xenondevs.invui.window.AbstractWindow;
1616

1717
import java.util.List;
18+
import java.util.concurrent.CompletableFuture;
1819
import java.util.function.*;
1920

2021
class CustomBoundItem<G extends Gui> extends AbstractBoundItem {
2122

2223
private final TriConsumer<Item, G, Click> clickHandler;
23-
private BiFunction<Player, G, ItemProvider> itemProvider;
24+
private volatile BiFunction<Player, G, ItemProvider> itemProvider;
2425
private final BiConsumer<Item, G> bindHandler;
2526
private final long updatePeriod;
2627
private @Nullable BukkitTask updateTask;
@@ -83,6 +84,8 @@ non-sealed static class Builder<G extends Gui> implements BoundItem.Builder<G> {
8384
private TriConsumer<Item, G, Click> clickHandler = (item, gui, click) -> {};
8485
private @Nullable BiFunction<Player, G, ItemProvider> itemProviderFn;
8586
private @Nullable ItemProvider asyncPlaceholder;
87+
private @Nullable Supplier<ItemProvider> asyncSupplier;
88+
private @Nullable CompletableFuture<ItemProvider> asyncFuture;
8689
private Consumer<Item> modifier = item -> {};
8790
private boolean updateOnClick;
8891
private long updatePeriod = -1L;
@@ -123,8 +126,16 @@ public BoundItem.Builder<G> setCyclingItemProvider(int period, List<? extends It
123126
}
124127

125128
@Override
126-
public Builder<G> async(ItemProvider placeholder) {
129+
public BoundItem.Builder<G> async(ItemProvider placeholder, Supplier<ItemProvider> itemProviderSupplier) {
127130
this.asyncPlaceholder = placeholder;
131+
this.asyncSupplier = itemProviderSupplier;
132+
return this;
133+
}
134+
135+
@Override
136+
public BoundItem.Builder<G> async(ItemProvider placeholder, CompletableFuture<ItemProvider> itemProviderFuture) {
137+
this.asyncPlaceholder = placeholder;
138+
this.asyncFuture = itemProviderFuture;
128139
return this;
129140
}
130141

@@ -175,15 +186,25 @@ public Item build() {
175186
customItem = new CustomBoundItem<>(
176187
bindHandler,
177188
clickHandler,
178-
itemProviderFn,
189+
(viewer, gui) -> asyncPlaceholder,
179190
updatePeriod
180191
);
181192

182-
Bukkit.getScheduler().runTaskAsynchronously(
183-
InvUI.getInstance().getPlugin(),
184-
() -> customItem.itemProvider = (viewer, gui) -> itemProviderFn.apply(viewer, gui)
185-
);
186-
193+
if (asyncSupplier != null) {
194+
Bukkit.getScheduler().runTaskAsynchronously(
195+
InvUI.getInstance().getPlugin(),
196+
() -> {
197+
var itemProvider = asyncSupplier.get();
198+
customItem.itemProvider = (viewer, gui) -> itemProvider;
199+
customItem.notifyWindows();
200+
}
201+
);
202+
} else if (asyncFuture != null) {
203+
asyncFuture.thenAccept(itemProvider -> {
204+
customItem.itemProvider = (viewer, gui) -> itemProvider;
205+
customItem.notifyWindows();
206+
});
207+
}
187208
} else {
188209
customItem = new CustomBoundItem<>(
189210
bindHandler,
@@ -198,12 +219,8 @@ public Item build() {
198219
return customItem;
199220
}
200221

201-
static class Normal extends Builder<Gui> {
202-
}
203-
204222
static class Paged extends Builder<PagedGui<?>> {
205223

206-
207224
Paged() {
208225
bindHandler = bindHandler.andThen((item, gui) -> {
209226
//noinspection ConstantValue // the generic type is unchecked otherwise

invui/src/main/java/xyz/xenondevs/invui/item/CustomItem.java

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@
99
import xyz.xenondevs.invui.window.AbstractWindow;
1010

1111
import java.util.List;
12+
import java.util.concurrent.CompletableFuture;
1213
import java.util.function.BiConsumer;
1314
import java.util.function.Consumer;
1415
import java.util.function.Function;
16+
import java.util.function.Supplier;
1517

1618
class CustomItem extends AbstractItem {
1719

1820
private final BiConsumer<Item, Click> clickHandler;
19-
private Function<Player, ItemProvider> itemProvider;
21+
private volatile Function<Player, ItemProvider> itemProvider;
2022
private final long updatePeriod;
2123
private @Nullable BukkitTask updateTask;
2224

@@ -63,6 +65,8 @@ static final class Builder implements Item.Builder<Builder> {
6365
private BiConsumer<Item, Click> clickHandler = (item, click) -> {};
6466
private @Nullable Function<Player, ItemProvider> itemProviderFn;
6567
private @Nullable ItemProvider asyncPlaceholder;
68+
private @Nullable Supplier<ItemProvider> asyncSupplier;
69+
private @Nullable CompletableFuture<ItemProvider> asyncFuture;
6670
private Consumer<Item> modifier = item -> {};
6771
private boolean updateOnClick;
6872
private long updatePeriod = -1L;
@@ -97,8 +101,16 @@ public Builder setCyclingItemProvider(int period, List<? extends ItemProvider> i
97101
}
98102

99103
@Override
100-
public Builder async(ItemProvider placeholder) {
104+
public Builder async(ItemProvider placeholder, Supplier<ItemProvider> itemProviderSupplier) {
101105
this.asyncPlaceholder = placeholder;
106+
this.asyncSupplier = itemProviderSupplier;
107+
return this;
108+
}
109+
110+
@Override
111+
public Builder async(ItemProvider placeholder, CompletableFuture<ItemProvider> itemProviderFuture) {
112+
this.asyncPlaceholder = placeholder;
113+
this.asyncFuture = itemProviderFuture;
102114
return this;
103115
}
104116

@@ -133,18 +145,28 @@ public Item build() {
133145
}
134146

135147
CustomItem customItem;
136-
if (asyncPlaceholder != null && itemProviderFn != null) {
148+
if (asyncPlaceholder != null) {
137149
customItem = new CustomItem(
138150
clickHandler,
139151
viewer -> asyncPlaceholder,
140152
updatePeriod
141153
);
142154

143-
Bukkit.getScheduler().runTaskAsynchronously(
144-
InvUI.getInstance().getPlugin(),
145-
() -> customItem.itemProvider = (viewer -> itemProviderFn.apply(viewer))
146-
);
147-
155+
if (asyncSupplier != null) {
156+
Bukkit.getScheduler().runTaskAsynchronously(
157+
InvUI.getInstance().getPlugin(),
158+
() -> {
159+
var itemProvider = asyncSupplier.get();
160+
customItem.itemProvider = (viewer -> itemProvider);
161+
customItem.notifyWindows();
162+
}
163+
);
164+
} else if (asyncFuture != null) {
165+
asyncFuture.thenAccept(itemProvider -> {
166+
customItem.itemProvider = (viewer -> itemProvider);
167+
customItem.notifyWindows();
168+
});
169+
}
148170
} else {
149171
customItem = new CustomItem(
150172
clickHandler,

invui/src/main/java/xyz/xenondevs/invui/item/Item.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@
88
import xyz.xenondevs.invui.window.Window;
99

1010
import java.util.List;
11+
import java.util.concurrent.CompletableFuture;
12+
import java.util.concurrent.Future;
1113
import java.util.function.BiConsumer;
1214
import java.util.function.Consumer;
1315
import java.util.function.Function;
16+
import java.util.function.Supplier;
1417

1518
/**
1619
* A UI element for use in {@link Gui Guis}.
@@ -130,14 +133,29 @@ default S setCyclingItemProvider(int period, ItemProvider itemProvider, ItemProv
130133
S setCyclingItemProvider(int period, List<? extends ItemProvider> itemProviders);
131134

132135
/**
133-
* Configures the resulting {@link Item} to resolve the {@link ItemProvider} set via {@link #setItemProvider(Function)}
134-
* asynchronously. Once resolved, the {@link ItemProvider} will stay like this and the function will never be called again.
136+
* Configures the resulting {@link Item} to resolve the {@link ItemProvider} asynchronously.
137+
* Once resolved, the {@link ItemProvider} will stay like this and the function will never be called again.
135138
* (Not even when calling {@link Item#notifyWindows()})
139+
* <p>
140+
* This function invalidates all previously configured {@link ItemProvider ItemProviders}.
136141
*
137-
* @param placeholder The {@link ItemProvider} to display while the actual {@link ItemProvider} is being resolved.
142+
* @param placeholder The {@link ItemProvider} to display while the actual {@link ItemProvider} is being resolved.
143+
* @param itemProviderSupplier The supplier that resolves the {@link ItemProvider}.
138144
* @return This builder.
139145
*/
140-
S async(ItemProvider placeholder);
146+
S async(ItemProvider placeholder, Supplier<ItemProvider> itemProviderSupplier);
147+
148+
/**
149+
* Configures the resulting {@link Item} to display a placeholder {@link ItemProvider} until
150+
* the specified {@link Future} arrives.
151+
* <p>
152+
* This function invalidates all previously configured {@link ItemProvider ItemProviders}.
153+
*
154+
* @param placeholder The {@link ItemProvider} to display while the actual {@link ItemProvider} is being resolved.
155+
* @param itemProviderFuture The future that resolves the {@link ItemProvider}.
156+
* @return This builder.
157+
*/
158+
S async(ItemProvider placeholder, CompletableFuture<ItemProvider> itemProviderFuture);
141159

142160
/**
143161
* Configures the resulting to automatically call {@link #notifyWindows()} every period ticks, while it is

0 commit comments

Comments
 (0)