Skip to content

Commit 110dd9d

Browse files
bukkit inventory events
1 parent 3cbb8b0 commit 110dd9d

File tree

1 file changed

+110
-79
lines changed

1 file changed

+110
-79
lines changed

docs/invui2/inventory.md

Lines changed: 110 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,92 @@ For most use cases, you will want to use a `VirtualInventory`. This is just a co
3838

3939
![](assets/img/inventory/virtual_inventory.avif){width=500}
4040

41-
### Inventory Events
41+
### Serialization
42+
43+
You can also serialize and deserialize `VirtualInventory` (i.e. saving and loading it):
44+
45+
Serializing a `VirtualInventory`:
46+
=== "Kotlin"
47+
```kotlin
48+
// serialize a VirtualInventory to a ByteArray
49+
val bin: ByteArray = virtualInventory.serialize()
50+
51+
// write a VirtualInventory directly to an output stream
52+
file.outputStream().use { virtualInventory.serialize(it) }
53+
```
54+
55+
=== "Java"
56+
```java
57+
// serialize a VirtualInventory to a ByteArray
58+
byte[] bin = virtualInventory.serialize();
59+
60+
// write a VirtualInventory directly to an output stream
61+
try (var out = new FileOutputStream(file)) {
62+
virtualInventory.serialize(out);
63+
}
64+
```
65+
66+
Deserializing a `VirtualInventory`:
67+
=== "Kotlin"
68+
```kotlin
69+
// deserialize a VirtualInventory from a ByteArray
70+
val inv: VirtualInventory = VirtualInventory.deserialize(bin)
71+
72+
// read a VirtualInventory directly from an input stream
73+
val inv2: VirtualInventory = file.inputStream().use { VirtualInventory.deserialize(it) }
74+
```
75+
76+
=== "Java"
77+
```java
78+
// deserialize a VirtualInventory from a ByteArray
79+
VirtualInventory inv = VirtualInventory.deserialize(bin);
80+
81+
// read a VirtualInventory directly from an input stream
82+
VirtualInventory inv2;
83+
try (var in = new FileInputStream(file)) {
84+
inv2 = VirtualInventory.deserialize(in);
85+
}
86+
```
87+
88+
There is also `VirtualInventoryManager`, which automatically writes virtual inventories registered with it to disk on shutdown and reads them back on startup. This allows you to very easily create persistent inventories, but note that using `VirtualInventoryManager` with a large amount of inventories will cause a slowdown on startup as all inventories are loaded on startup at once.
89+
90+
=== "Kotlin"
91+
```kotlin
92+
val inv: VirtualInventory = VirtualInventoryManager.getInstance().getOrCreate(uuid, size)
93+
```
94+
95+
=== "Java"
96+
```java
97+
VirtualInventory inv = VirtualInventoryManager.getInstance().getOrCreate(uuid, size);
98+
```
99+
100+
## Referencing Inventory
101+
102+
The `ReferencingInventory` can be used to reference a Bukkit inventory, such as the player's inventory. For example, you can easily implement a gui to look at another player's inventory using it:
103+
104+
=== "Kotlin"
105+
```kotlin
106+
val inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.inventory)
107+
Window.builder()
108+
.setUpperGui(Gui.of(9, 4, inv))
109+
.open(player)
110+
```
111+
112+
=== "Java"
113+
```java
114+
var inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.getInventory());
115+
Window.builder()
116+
.setUpperGui(Gui.of(9, 4, inv))
117+
.open(player);
118+
```
119+
120+
![](assets/img/inventory/invsee.avif)
121+
122+
## Inventory Events
42123

43124
InvUI's inventories have a powerful event system. There are multiple events that you can listen to, each of which is fired at a different stage of the interaction and can be used for different purposes. `ItemPreUpdateEvent` and `ItemPostUpdateEvent` are fired with an `UpdateReason`. If a player interaction caused the event, this will be a `PlayerUpdateReason` from which you can retrieve the player and additional information about the click.
44125

45-
#### ItemPreUpdateEvent
126+
### ItemPreUpdateEvent
46127

47128
This event is called before changes were fully processed. Cancelling this event will affect the source of the change (i.e. the player's cursor most of the time) appropriately, if possible. This allows restricting which items can be put into an inventory or even a specific slot of an inventory.
48129

@@ -77,7 +158,7 @@ In the following example, the `ItemPreUpdateEvent` is cancelled in such a way th
77158
![](assets/img/inventory/item_pre_update_event.avif){width=500}
78159

79160

80-
#### ItemPostUpdateEvent
161+
### ItemPostUpdateEvent
81162

82163
This event is called after changes were performed on a slot. It is not cancellable and changes done to the inventory during this event will not affect the source of the change.
83164

@@ -103,7 +184,7 @@ In the following example, the `ItemPostUpdateEvent` is used to implement a trash
103184

104185
![](assets/img/inventory/item_post_update_event.avif){width=500}
105186

106-
#### InventoryClickEvent
187+
### InventoryClickEvent
107188

108189
InvUI also has its own inventory click event, not to be confused with `org.bukkit.event.inventory.InventoryClickEvent`. This event is fired when a player clicks on a slot in a gui-embedded inventory. For most cases, `ItemPreUpdateEvent` and `ItemPostUpdateEvent` are sufficient. However, in very specialized cases, you might want to intercept certain click actions and use them for something else.
109190

@@ -135,86 +216,36 @@ In the following example, the `InventoryClickEvent` is used to change the number
135216

136217
![](assets/img/inventory/inventory_click_event.avif){width=500}
137218

138-
### Serialization
219+
### Bukkit Events
139220

140-
You can also serialize and deserialize `VirtualInventory` (i.e. saving and loading it):
221+
When embedded in a Gui, InvUI fires Bukkit's `InventoryClickEvent` and `InventoryDragEvent` for `VirtualInventory` and `ReferencingInventory`. This allows other plugins to handle interactions with InvUI inventories. Since other inventory types (`CompositeInventory`, `ObscuredInventory`) at some point delegate to one of these types, actions on them will also lead to an event being fired, but there won't be multiple event calls for one action.
141222

142-
Serializing a `VirtualInventory`:
143-
=== "Kotlin"
144-
```kotlin
145-
// serialize a VirtualInventory to a ByteArray
146-
val bin: ByteArray = virtualInventory.serialize()
147-
148-
// write a VirtualInventory directly to an output stream
149-
file.outputStream().use { virtualInventory.serialize(it) }
150-
```
223+
??? info "Behavior"
151224

152-
=== "Java"
153-
```java
154-
// serialize a VirtualInventory to a ByteArray
155-
byte[] bin = virtualInventory.serialize();
156-
157-
// write a VirtualInventory directly to an output stream
158-
try (var out = new FileOutputStream(file)) {
159-
virtualInventory.serialize(out);
160-
}
161-
```
225+
To isolate InvUI's gui components from other plugins, these events are fired with custom `Inventory` and `InventoryView` implementations that just expose the slots of the InvUI inventories involved in the action. Refer to the tables below for more details.
162226

163-
Deserializing a `VirtualInventory`:
164-
=== "Kotlin"
165-
```kotlin
166-
// deserialize a VirtualInventory from a ByteArray
167-
val inv: VirtualInventory = VirtualInventory.deserialize(bin)
227+
=== "InventoryClickEvent"
168228

169-
// read a VirtualInventory directly from an input stream
170-
val inv2: VirtualInventory = file.inputStream().use { VirtualInventory.deserialize(it) }
171-
```
172-
173-
=== "Java"
174-
```java
175-
// deserialize a VirtualInventory from a ByteArray
176-
VirtualInventory inv = VirtualInventory.deserialize(bin);
177-
178-
// read a VirtualInventory directly from an input stream
179-
VirtualInventory inv2;
180-
try (var in = new FileInputStream(file)) {
181-
inv2 = VirtualInventory.deserialize(in);
182-
}
183-
```
184-
185-
There is also `VirtualInventoryManager`, which automatically writes virtual inventories registered with it to disk on shutdown and reads them back on startup. This allows you to very easily create persistent inventories, but note that using `VirtualInventoryManager` with a large amount of inventories will cause a slowdown on startup as all inventories are loaded on startup at once.
186-
187-
=== "Kotlin"
188-
```kotlin
189-
val inv: VirtualInventory = VirtualInventoryManager.getInstance().getOrCreate(uuid, size)
190-
```
191-
192-
=== "Java"
193-
```java
194-
VirtualInventory inv = VirtualInventoryManager.getInstance().getOrCreate(uuid, size);
195-
```
196-
197-
## Referencing Inventory
198-
199-
The `ReferencingInventory` can be used to reference a Bukkit inventory, such as the player's inventory. For example, you can easily implement a gui to look at another player's inventory using it:
200-
201-
=== "Kotlin"
202-
```kotlin
203-
val inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.inventory)
204-
Window.builder()
205-
.setUpperGui(Gui.of(9, 4, inv))
206-
.open(player)
207-
```
208-
209-
=== "Java"
210-
```java
211-
var inv = ReferencingInventory.fromPlayerStorageContents(otherPlayer.getInventory());
212-
Window.builder()
213-
.setUpperGui(Gui.of(9, 4, inv))
214-
.open(player);
215-
```
216-
217-
![](assets/img/inventory/invsee.avif)
229+
| Clicked Inventory | Behavior |
230+
|-------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
231+
| `ReferencingInventory` to the viewer's player inventory (e.g. the default lower GUI) | Fired with a view matching the player's current open view (top inventory of 0 slots, player inventory as bottom). Even if the referencing inventory is embedded in the upper GUI, click events use slots translated to the lower inventory. |
232+
| Any other inventory (e.g. `VirtualInventory` or `ReferencingInventory` to something else) | Fired with a custom view using an adapter `Inventory` that delegates to the InvUI inventory as the top inventory. The lower inventory is always the player's inventory. |
233+
234+
=== "InventoryDragEvent"
235+
236+
| Drag Slots | Behavior |
237+
|----------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
238+
| All slots within a `ReferencingInventory` to the viewer's player inventory | Fired with a view matching the player's current open view. Even if the referencing inventory is embeded in the upper GUI, slots are translated to the lower inventory. |
239+
| Slots from other inventories involved | Fired with a custom view using an adapter `Inventory` to a `CompositeInventory` combining all involved inventories (except `ReferencingInventory` to the viewer's player inventory, which uses the view's lower inventory). |
240+
241+
!!! note "Drag Event Limitations"
242+
- The `InventoryDragEvent` is fired with an expected outcome of the drag action, not taking into account any custom InvUI-inventory logic like update handlers.
243+
- While cancelling the `InventoryDragEvent` works as expected, changing the cursor with `InventoryDragEvent#setCursor` or updating the `newItems` map is ignored by InvUI.
244+
245+
Bukkit inventory event firing is enabled by default. You can disable it:
246+
247+
- Per-plugin: `InvUI.getInstance().setFireBukkitInventoryEvents(false)`
248+
- Globally: Set the system property `-Dinvui.fireBukkitInventoryEvents=false`
218249

219250
## Other configuration options
220251

0 commit comments

Comments
 (0)