@@ -28,7 +28,7 @@ The dialog API is currently experimental and might change in the future.
28
28
update. Paper released developer API for creating custom dialogs in 1.21.7. This section is meant
29
29
as an introduction to this API and what you can and cannot do with dialogs.
30
30
31
- ## What is a dialog
31
+ ## What is a dialog?
32
32
Dialogs are a way for servers to send custom in-game menus to clients. They allow for displaying various information
33
33
or provide an easy way to gather user input.
34
34
@@ -53,8 +53,6 @@ There are three built-in dialogs:
53
53
- [ Quick Actions] ( jd:paper:io.papermc.paper.registry.keys.DialogKeys#QUICK_ACTIONS )
54
54
- [ Custom Options] ( jd:paper:io.papermc.paper.registry.keys.DialogKeys#CUSTOM_OPTIONS )
55
55
56
- Currently, only the server links can be modified from the API.
57
-
58
56
### Adding server links
59
57
You can add server links by retrieving the [ ` ServerLinks ` ] ( jd:paper:org.bukkit.ServerLinks ) instance from
60
58
[ ` Bukkit.getServer().getServerLinks() ` ] ( jd:paper:org.bukkit.Server#getServerLinks() ) and using the various mutation methods.
@@ -129,7 +127,7 @@ There are four ways to gather input:
129
127
130
128
131
129
### Dialog type
132
- The [ ` DialogTypes ` ] ( jd:paper:io.papermc.paper.registry.data.dialog.type.DialogType ) interface defines a few static
130
+ The [ ` DialogType ` ] ( jd:paper:io.papermc.paper.registry.data.dialog.type.DialogType ) interface defines a few static
133
131
methods for the various dialog types. The following types exist:
134
132
135
133
| Type | Method | Description |
@@ -143,11 +141,11 @@ methods for the various dialog types. The following types exist:
143
141
The type primarily influences the bottom part of the dialog.
144
142
145
143
## Registering dialogs in the registry
146
- If you want dialogs to be registered in the dialogs registry, you have register them inside a registry modification lifecycle
144
+ If you want dialogs to be registered in the dialogs registry, you must register them inside a registry modification lifecycle
147
145
event in your plugin's bootstrapper. Some general information on that can be read [ here] ( /paper/dev/registries ) .
148
146
149
147
The general registration looks fairly similar to dynamically created dialogs:
150
- ``` java title="YourPluginBootstrapper.java"
148
+ ``` java title="YourPluginBootstrapper.java" showLineNumbers
151
149
@Override
152
150
public void bootstrap(BootstrapContext context) {
153
151
context. getLifecycleManager(). registerEventHandler(RegistryEvents . DIALOG. compose()
@@ -167,14 +165,14 @@ the start.
167
165
168
166
### The dialog
169
167
The dialog is a simple confirmation-type dialog with a single plain message body components. We will register it in
170
- the bootstrapper so that we can easily retrieve it from the ` AsyncPlayerConfigureEvent ` , where the dialog will
168
+ the bootstrapper so that we can easily retrieve it from the ` AsyncPlayerConnectionConfigureEvent ` , where the dialog will
171
169
be sent from.
172
170
173
- ``` java title="CustomPluginBootstrapper.java"
171
+ ``` java title="CustomPluginBootstrapper.java" showLineNumbers
174
172
ctx. getLifecycleManager(). registerEventHandler(RegistryEvents . DIALOG. compose(),
175
- e - > e. registry(). registerWith (
173
+ e - > e. registry(). register (
176
174
DialogKeys . create(Key . key(" papermc:praise_paperchan" )),
177
- builder - > builder. empty()
175
+ builder - > builder
178
176
.base(DialogBase . builder(Component . text(" Accept our rules!" , NamedTextColor . LIGHT_PURPLE ))
179
177
.canCloseWithEscape(false )
180
178
.body(List . of(
@@ -208,7 +206,7 @@ this by constructing a `CompletableFuture`, putting it into a map, and waiting u
208
206
completed, will only happen as soon the player pressed one of the two confirmation buttons of the dialog.
209
207
210
208
The code for that would look something like this:
211
- ``` java title="ServerJoinListener.java"
209
+ ``` java title="ServerJoinListener.java" showLineNumbers
212
210
@NullMarked
213
211
public class ServerJoinListener implements Listener {
214
212
@@ -224,7 +222,7 @@ public class ServerJoinListener implements Listener {
224
222
// The dialog failed to load :(
225
223
// This would happen if the dialog could not be found in the registry by the provided key.
226
224
// Usually that is an indicator that the used key is different from the one used to register your
227
- // dialog, your bootstrapper might not be registered, or an exception ocurred in the bootstrap phase.
225
+ // dialog, your bootstrapper might not be registered, or an exception occurred in the bootstrap phase.
228
226
return ;
229
227
}
230
228
@@ -284,11 +282,11 @@ be allowed to.
284
282
</details >
285
283
286
284
## Example: Retrieving and parsing user input
287
- The dialog for this example will be fairly simple: It again confirmation-type dialog which contains two number range inputs.
285
+ The dialog for this example will be fairly simple: We once again create a confirmation-type dialog which contains two number range inputs.
288
286
The top input will be for setting the level, the bottom input for setting the experience percentage towards the next level.
289
287
When the player clicks on the confirmation button, they should have their levels and exp set to the configured values.
290
288
291
- ``` java
289
+ ``` java showLineNumbers
292
290
Dialog . create(builder - > builder. empty()
293
291
.base(DialogBase . builder(Component . text(" Configure your new experience value" ))
294
292
.inputs(List . of(
@@ -324,7 +322,7 @@ Dialog.create(builder -> builder.empty()
324
322
```
325
323
326
324
### Reading the input
327
- To retrieve the values the user put into the dialog, we once again have to listen to a ` PlayerCustomClickEvent ` .
325
+ To retrieve the values the user put into the dialog, we can once again listen to a ` PlayerCustomClickEvent ` .
328
326
We first check the identifier of the action. After that, we can retrieve the input values from the
329
327
[ ` DialogResponseView ` ] ( jd:paper:io.papermc.paper.dialog.DialogResponseView ) retrievable from
330
328
[ ` PlayerCustomClickEvent#getDialogResponseView() ` ] ( jd:paper:io.papermc.paper.event.player.PlayerCustomClickEvent#getDialogResponseView() ) .
@@ -364,6 +362,34 @@ void handleLevelsDialog(PlayerCustomClickEvent event) {
364
362
}
365
363
```
366
364
365
+ ### Using callbacks
366
+
367
+ Instead of registering another event handler, you can instead use the
368
+ [ ` DialogAction.customClick(DialogActionCallback, ClickCallback.Options) ` ] ( jd:paper:io.papermc.paper.registry.data.dialog.action.DialogAction#customClick(io.papermc.paper.registry.data.dialog.action.DialogActionCallback,net.kyori.adventure.text.event.ClickCallback.Options) )
369
+ method to register a callback locally.
370
+
371
+ The code for the dialog action would therefore look like this:
372
+
373
+ ``` java showLineNumbers
374
+ DialogAction . customClick(
375
+ (view, audience) - > {
376
+ int levels = view. getFloat(" level" ). intValue();
377
+ float exp = view. getFloat(" experience" ). floatValue();
378
+
379
+ player. sendRichMessage(" You selected <color:#ccfffd><level> levels</color> and <color:#ccfffd><exp>% exp</color> to the next level!" ,
380
+ Placeholder . component(" level" , Component . text(levels)),
381
+ Placeholder . component(" exp" , Component . text(exp))
382
+ );
383
+ player. setLevel(levels);
384
+ player. setExp(exp / 100 );
385
+ },
386
+ ClickCallback . Options . builder()
387
+ .uses(1 ) // Set the number of uses for this callback. Defaults to 1
388
+ .lifetime(ClickCallback . DEFAULT_LIFETIME ) // Set the lifetime of the callback. Defaults to 12 hours
389
+ .build()
390
+ )
391
+ ```
392
+
367
393
<details >
368
394
<summary >In-game preview</summary >
369
395
<Video src = { InputDialogShowcaseMp4 } />
0 commit comments