Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions api/src/main/java/net/kyori/adventure/text/event/ClickEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import net.kyori.adventure.text.format.StyleBuilderApplicable;
import net.kyori.adventure.util.Index;
import org.jspecify.annotations.Nullable;

import static java.util.Objects.requireNonNull;

Expand Down Expand Up @@ -179,6 +180,17 @@ static ClickEvent<Payload.Dialog> showDialog(final DialogLike dialog) {
return ClickEventImpl.create(Action.SHOW_DIALOG, Payload.dialog(dialog));
}

/**
* Creates a click event that sends a custom event to the server.
*
* @param key the key identifying the payload
* @return the click event
* @since 4.23.0
*/
static ClickEvent<Payload.Custom> custom(final Key key) {
return ClickEvent.custom(key, null);
}

/**
* Creates a click event that sends a custom event to the server.
*
Expand All @@ -190,9 +202,8 @@ static ClickEvent<Payload.Dialog> showDialog(final DialogLike dialog) {
* @return the click event
* @since 4.23.0
*/
static ClickEvent<Payload.Custom> custom(final Key key, final BinaryTagHolder nbt) {
static ClickEvent<Payload.Custom> custom(final Key key, final @Nullable BinaryTagHolder nbt) {
requireNonNull(key, "key");
requireNonNull(nbt, "nbt");
return ClickEventImpl.create(Action.CUSTOM, Payload.custom(key, nbt));
}

Expand Down Expand Up @@ -464,20 +475,30 @@ static ClickEvent.Payload.Dialog dialog(final DialogLike dialog) {
return new PayloadImpl.DialogImpl(dialog);
}

/**
* Creates a custom payload.
*
* @param key the key identifying the payload
* @return the payload
* @since 4.23.0
*/
static ClickEvent.Payload.Custom custom(final Key key) {
return ClickEvent.Payload.custom(key, null);
}

/**
* Creates a custom payload.
*
* <p>See {@link BinaryTagHolder#binaryTagHolder(String)} for a simple way to create NBT from SNBT.
* For simple use cases, you can use plain strings directly as SNBT.</p>
*
* @param key the key identifying the payload
* @param nbt the payload nbt data
* @param nbt the payload nbt data, optional
* @return the payload
* @since 4.23.0
*/
static ClickEvent.Payload.Custom custom(final Key key, final BinaryTagHolder nbt) {
static ClickEvent.Payload.Custom custom(final Key key, final @Nullable BinaryTagHolder nbt) {
requireNonNull(key, "key");
requireNonNull(nbt, "nbt");
return new PayloadImpl.CustomImpl(key, nbt);
}

Expand Down Expand Up @@ -528,21 +549,21 @@ sealed interface Dialog extends Payload permits PayloadImpl.DialogImpl {
}

/**
* A payload that holds custom data.
* A payload with a key and optional custom NBT data.
*
* @see Action#CUSTOM
* @since 4.22.0
*/
sealed interface Custom extends Payload, Keyed permits PayloadImpl.CustomImpl {
/**
* The custom data.
* The optional custom data.
*
* <p>See {@link BinaryTagHolder#string()} for a simple way to return SNBT from NBT data.</p>
*
* @return the data
* @since 4.23.0
*/
BinaryTagHolder nbt();
@Nullable BinaryTagHolder nbt();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import net.kyori.adventure.dialog.DialogLike;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import org.jspecify.annotations.Nullable;

final class PayloadImpl {
private PayloadImpl() {
Expand All @@ -40,6 +41,6 @@ record IntImpl(int integer) implements ClickEvent.Payload.Int {
record DialogImpl(DialogLike dialog) implements ClickEvent.Payload.Dialog {
}

record CustomImpl(Key key, BinaryTagHolder nbt) implements ClickEvent.Payload.Custom {
record CustomImpl(Key key, @Nullable BinaryTagHolder nbt) implements ClickEvent.Payload.Custom {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ record ClickTag() {
}, QuotingOverride.QUOTED);

if (payload instanceof ClickEvent.Payload.Custom custom) {
emitter.argument(custom.nbt().string());
final BinaryTagHolder nbt = custom.nbt();
if (nbt != null) {
emitter.argument(nbt.string());
}
}
})
);
Expand Down Expand Up @@ -90,9 +93,14 @@ static Tag create(final ArgumentQueue args, final Context ctx) throws ParsingExc
throw ctx.newException("'custom' click event requires a valid key argument", ex, args);
}

final String nbt = args.popOr("'custom' click event requires a nbt argument").value();
final String nbt;
if (args.hasNext()) {
nbt = args.pop().value();
} else {
nbt = null;
}

yield ClickEvent.custom(key, BinaryTagHolder.binaryTagHolder(nbt));
yield ClickEvent.custom(key, nbt == null ? null : BinaryTagHolder.binaryTagHolder(nbt));
}
case ClickEvent.Action.ShowDialog ignored ->
throw ctx.newException("'show_dialog' click events are not supported in MiniMessage yet");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public Style read(final JsonReader in) throws IOException {
if (value != null) style.clickEvent(ClickEvent.copyToClipboard(value));
}
case ClickEvent.Action.Custom ignored -> {
if (key != null && value != null) style.clickEvent(ClickEvent.custom(key, BinaryTagHolder.binaryTagHolder(value)));
if (key != null) style.clickEvent(ClickEvent.custom(key, value == null ? null : BinaryTagHolder.binaryTagHolder(value)));
}
// Not readable.
case ClickEvent.Action.ShowDialog ignored -> {
Expand Down Expand Up @@ -360,8 +360,12 @@ private void writeClickEvent(final ClickEvent<?> clickEvent, final JsonWriter ou
case ClickEvent.Payload.Custom customPayload -> {
out.name(CLICK_EVENT_ID);
this.gson.toJson(customPayload.key(), SerializerFactory.KEY_TYPE, out);
out.name(CLICK_EVENT_PAYLOAD);
out.value(customPayload.nbt().string());

final BinaryTagHolder nbt = customPayload.nbt();
if (nbt != null) {
out.name(CLICK_EVENT_PAYLOAD);
out.value(nbt.string());
}
}
case ClickEvent.Payload.Int intPayload -> {
out.name(CLICK_EVENT_PAGE);
Expand Down