From 69e4872f4042df342b9bf2df0724d9cbc18d241f Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 17 May 2025 16:01:00 +1000 Subject: [PATCH] Minecraft 25w20a protocol support --- api/pom.xml | 6 + .../bungee/api/connection/ProxiedPlayer.java | 20 +++ .../bungee/api/event/CustomClickEvent.java | 43 +++++++ .../net/md_5/bungee/api/chat/ClickEvent.java | 14 ++- .../bungee/api/chat/ClickEventCustom.java | 30 +++++ .../net/md_5/bungee/api/chat/HoverEvent.java | 17 --- dialog/LICENSE | 28 +++++ dialog/README.md | 35 ++++++ dialog/nb-configuration.xml | 31 +++++ dialog/pom.xml | 36 ++++++ .../bungee/api/dialog/ConfirmationDialog.java | 27 ++++ .../net/md_5/bungee/api/dialog/Dialog.java | 9 ++ .../md_5/bungee/api/dialog/DialogBase.java | 21 ++++ .../bungee/api/dialog/DialogListDialog.java | 41 ++++++ .../bungee/api/dialog/MultiActionDialog.java | 42 +++++++ .../dialog/MultiActionInputFormDialog.java | 29 +++++ .../md_5/bungee/api/dialog/NoticeDialog.java | 26 ++++ .../bungee/api/dialog/ServerLinksDialog.java | 31 +++++ .../api/dialog/SimpleInputFormDialog.java | 40 ++++++ .../api/dialog/action/DialogAction.java | 20 +++ .../api/dialog/action/DialogClickAction.java | 36 ++++++ .../api/dialog/action/DialogSubmitAction.java | 33 +++++ .../bungee/api/dialog/body/DialogBody.java | 10 ++ .../api/dialog/body/PlainMessageBody.java | 28 +++++ .../api/dialog/chat/ShowDialogClickEvent.java | 42 +++++++ .../bungee/api/dialog/input/BooleanInput.java | 37 ++++++ .../bungee/api/dialog/input/DialogInput.java | 13 ++ .../bungee/api/dialog/input/InputOption.java | 22 ++++ .../api/dialog/input/NumberRangeInput.java | 40 ++++++ .../api/dialog/input/SingleOptionInput.java | 38 ++++++ .../bungee/api/dialog/input/TextInput.java | 36 ++++++ .../submit/CommandTemplateSubmission.java | 22 ++++ .../dialog/submit/CustomFormSubmission.java | 22 ++++ .../submit/CustomTemplateSubmission.java | 24 ++++ .../api/dialog/submit/DialogSubmission.java | 12 ++ pom.xml | 2 + protocol/pom.xml | 2 +- .../protocol/AbstractPacketHandler.java | 15 +++ .../net/md_5/bungee/protocol/Protocol.java | 46 +++++-- .../bungee/protocol/ProtocolConstants.java | 2 +- .../bungee/protocol/packet/ClearDialog.java | 32 +++++ .../md_5/bungee/protocol/packet/Commands.java | 21 ++-- .../protocol/packet/CustomClickAction.java | 47 +++++++ .../bungee/protocol/packet/ShowDialog.java | 73 +++++++++++ .../protocol/packet/ShowDialogDirect.java | 40 ++++++ .../java/net/md_5/bungee/UserConnection.java | 20 +++ .../bungee/connection/UpstreamBridge.java | 28 +++++ serializer/nb-configuration.xml | 31 +++++ serializer/pom.xml | 41 ++++++ .../chat/hover/content/EntitySerializer.java | 0 .../chat/hover/content/ItemSerializer.java | 0 .../chat/hover/content/TextSerializer.java | 0 .../bungee/chat/BaseComponentSerializer.java | 19 +++ .../net/md_5/bungee/chat/ChatVersion.java | 0 .../md_5/bungee/chat/ComponentSerializer.java | 0 .../bungee/chat/ComponentStyleSerializer.java | 0 .../chat/KeybindComponentSerializer.java | 0 .../bungee/chat/ScoreComponentSerializer.java | 0 .../chat/SelectorComponentSerializer.java | 0 .../bungee/chat/TextComponentSerializer.java | 0 .../chat/TranslatableComponentSerializer.java | 0 .../chat/VersionedComponentSerializer.java | 11 ++ .../md_5/bungee/dialog/DialogSerializer.java | 117 ++++++++++++++++++ .../ShowDialogClickEventSerializer.java | 38 ++++++ .../md_5/bungee/api/chat/ComponentsTest.java | 0 .../api/chat/TranslatableComponentTest.java | 0 .../net/md_5/bungee/dialog/SimpleTest.java | 25 ++++ 67 files changed, 1530 insertions(+), 41 deletions(-) create mode 100644 api/src/main/java/net/md_5/bungee/api/event/CustomClickEvent.java create mode 100644 chat/src/main/java/net/md_5/bungee/api/chat/ClickEventCustom.java create mode 100644 dialog/LICENSE create mode 100644 dialog/README.md create mode 100644 dialog/nb-configuration.xml create mode 100644 dialog/pom.xml create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/ConfirmationDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/Dialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/DialogBase.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/DialogListDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionInputFormDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/NoticeDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/ServerLinksDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/SimpleInputFormDialog.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogAction.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogClickAction.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogSubmitAction.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/body/DialogBody.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/body/PlainMessageBody.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/chat/ShowDialogClickEvent.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/BooleanInput.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/DialogInput.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/InputOption.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/NumberRangeInput.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/SingleOptionInput.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/input/TextInput.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CommandTemplateSubmission.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomFormSubmission.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomTemplateSubmission.java create mode 100644 dialog/src/main/java/net/md_5/bungee/api/dialog/submit/DialogSubmission.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearDialog.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/CustomClickAction.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialog.java create mode 100644 protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialogDirect.java create mode 100644 serializer/nb-configuration.xml create mode 100644 serializer/pom.xml rename {chat => serializer}/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/api/chat/hover/content/ItemSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/api/chat/hover/content/TextSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java (90%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/ChatVersion.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java (100%) rename {chat => serializer}/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java (94%) create mode 100644 serializer/src/main/java/net/md_5/bungee/dialog/DialogSerializer.java create mode 100644 serializer/src/main/java/net/md_5/bungee/dialog/ShowDialogClickEventSerializer.java rename {chat => serializer}/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java (100%) rename {chat => serializer}/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java (100%) create mode 100644 serializer/src/test/java/net/md_5/bungee/dialog/SimpleTest.java diff --git a/api/pom.xml b/api/pom.xml index b050e847..fdf519e1 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -31,6 +31,12 @@ ${project.version} compile + + net.md-5 + bungeecord-dialog + ${project.version} + compile + net.md-5 bungeecord-event diff --git a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java index 17dd8694..1c0714f4 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java @@ -12,6 +12,7 @@ import net.md_5.bungee.api.SkinConfiguration; import net.md_5.bungee.api.Title; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.dialog.Dialog; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.score.Scoreboard; import org.jetbrains.annotations.ApiStatus; @@ -390,4 +391,23 @@ public interface ProxiedPlayer extends Connection, CommandSender * @return the brand of the client, or null if not received yet */ String getClientBrand(); + + /** + * Clear the player's open dialog. + * + * @throws IllegalStateException if the players version is not at least + * 1.21.6 + */ + @ApiStatus.Experimental + void clearDialog(); + + /** + * Show a dialog to the player. + * + * @param dialog the dialog to show + * @throws IllegalStateException if the players version is not at least + * 1.21.6 + */ + @ApiStatus.Experimental + void showDialog(Dialog dialog); } diff --git a/api/src/main/java/net/md_5/bungee/api/event/CustomClickEvent.java b/api/src/main/java/net/md_5/bungee/api/event/CustomClickEvent.java new file mode 100644 index 00000000..01d065c4 --- /dev/null +++ b/api/src/main/java/net/md_5/bungee/api/event/CustomClickEvent.java @@ -0,0 +1,43 @@ +package net.md_5.bungee.api.event; + +import java.util.Map; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.plugin.Cancellable; +import net.md_5.bungee.api.plugin.Event; + +/** + * Called after a {@link ProxiedPlayer} runs a custom action from a chat event + * or form submission. + */ +@Data +@ToString(callSuper = false) +@EqualsAndHashCode(callSuper = false) +public class CustomClickEvent extends Event implements Cancellable +{ + + /** + * Map key containing the form action, if available. + */ + public static final String ACTION_KEY = "action"; + // + /** + * Player who clicked. + */ + private final ProxiedPlayer player; + /** + * Custom action ID. + */ + private final String id; + /** + * Form data, may be null. If a form submission, usually contains a key + * {@link ACTION_KEY} with the ID of the relevant submission action. + */ + private final Map data; + /** + * Cancelled state. + */ + private boolean cancelled; +} diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java index 1f643599..2aba0866 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEvent.java @@ -4,12 +4,14 @@ import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.ToString; +import org.jetbrains.annotations.ApiStatus; @Getter @ToString @EqualsAndHashCode @RequiredArgsConstructor -public final class ClickEvent +@ApiStatus.NonExtendable +public class ClickEvent { /** @@ -52,11 +54,19 @@ public final class ClickEvent * {@link net.md_5.bungee.api.chat.ClickEvent#value} in a book. */ CHANGE_PAGE, + /** + * Must use subclass ShowDialogClickEvent. + */ + SHOW_DIALOG, /** * Copy the string given by * {@link net.md_5.bungee.api.chat.ClickEvent#value} into the player's * clipboard. */ - COPY_TO_CLIPBOARD + COPY_TO_CLIPBOARD, + /** + * Must use subclass {@link ClickEventCustom}. + */ + CUSTOM, } } diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/ClickEventCustom.java b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEventCustom.java new file mode 100644 index 00000000..6946d00c --- /dev/null +++ b/chat/src/main/java/net/md_5/bungee/api/chat/ClickEventCustom.java @@ -0,0 +1,30 @@ +package net.md_5.bungee.api.chat; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * Click event which sends a custom payload to the server. + */ +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class ClickEventCustom extends ClickEvent +{ + + /** + * The custom payload. + */ + private final String payload; + + /** + * @param id identifier for the event (lower case, no special characters) + * @param payload custom payload + */ + public ClickEventCustom(String id, String payload) + { + super( ClickEvent.Action.CUSTOM, id ); + this.payload = payload; + } +} diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java b/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java index 3408b887..6017a14a 100644 --- a/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java +++ b/chat/src/main/java/net/md_5/bungee/api/chat/HoverEvent.java @@ -13,7 +13,6 @@ import net.md_5.bungee.api.chat.hover.content.Content; import net.md_5.bungee.api.chat.hover.content.Entity; import net.md_5.bungee.api.chat.hover.content.Item; import net.md_5.bungee.api.chat.hover.content.Text; -import net.md_5.bungee.chat.VersionedComponentSerializer; import org.jetbrains.annotations.ApiStatus; @Getter @@ -73,22 +72,6 @@ public final class HoverEvent this.legacy = true; } - @Deprecated - public BaseComponent[] getValue() - { - Content content = contents.get( 0 ); - if ( content instanceof Text && ( (Text) content ).getValue() instanceof BaseComponent[] ) - { - return (BaseComponent[]) ( (Text) content ).getValue(); - } - - TextComponent component = new TextComponent( VersionedComponentSerializer.getDefault().toString( content ) ); - return new BaseComponent[] - { - component - }; - } - /** * Adds a content to this hover event. * diff --git a/dialog/LICENSE b/dialog/LICENSE new file mode 100644 index 00000000..f3e916a9 --- /dev/null +++ b/dialog/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2025, SpigotMC Pty. Ltd. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/dialog/README.md b/dialog/README.md new file mode 100644 index 00000000..0bf858d5 --- /dev/null +++ b/dialog/README.md @@ -0,0 +1,35 @@ +BungeeCord-Dialog +================= + +Highly experimental API, subject to breakage. All contributions welcome, including major refactors/design changes. + +Sample Plugin +------------- + +```java + private class TestCommand extends Command + { + + public TestCommand() + { + super( "btest" ); + } + + @Override + public void execute(CommandSender sender, String[] args) + { + ProxiedPlayer player = (ProxiedPlayer) sender; + + Dialog notice = new NoticeDialog( new DialogBase( new ComponentBuilder( "Hello" ).color( ChatColor.RED ).build() ) ); + player.showDialog( notice ); + + notice = new SimpleInputFormDialog( + new DialogBase( new ComponentBuilder( "Hello" ).color( ChatColor.RED ).build() ), + new DialogSubmitAction( "submit", new CustomFormSubmission( "customform" ), new ComponentBuilder( "Submit Button" ).build() ), + new TextInput( "first", new ComponentBuilder( "First" ).build() ), + new TextInput( "second", new ComponentBuilder( "Second" ).build() ) + ); + player.sendMessage( new ComponentBuilder( "click me" ).event( new ShowDialogClickEvent( notice ) ).build() ); + } + } +``` diff --git a/dialog/nb-configuration.xml b/dialog/nb-configuration.xml new file mode 100644 index 00000000..7e465924 --- /dev/null +++ b/dialog/nb-configuration.xml @@ -0,0 +1,31 @@ + + + + + + project + NEW_LINE + NEW_LINE + NEW_LINE + true + true + true + true + true + true + true + true + true + true + + diff --git a/dialog/pom.xml b/dialog/pom.xml new file mode 100644 index 00000000..0a3d929c --- /dev/null +++ b/dialog/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + + + net.md-5 + bungeecord-parent + 1.21-R0.3-SNAPSHOT + ../pom.xml + + + net.md-5 + bungeecord-dialog + 1.21-R0.3-SNAPSHOT + jar + + BungeeCord-Dialog + Minecraft dialog API intended for use with BungeeCord + + + BSD-3-Clause + https://github.com/SpigotMC/BungeeCord/blob/master/dialog/LICENSE + repo + + + + + + net.md-5 + bungeecord-chat + ${project.version} + compile + + + diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/ConfirmationDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/ConfirmationDialog.java new file mode 100644 index 00000000..9ed5f2f3 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/ConfirmationDialog.java @@ -0,0 +1,27 @@ +package net.md_5.bungee.api.dialog; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.dialog.action.DialogClickAction; + +@Data +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@Accessors(fluent = true) +public class ConfirmationDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private DialogClickAction yes; + private DialogClickAction no; + + public ConfirmationDialog(DialogBase base) + { + this( base, null, null ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/Dialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/Dialog.java new file mode 100644 index 00000000..028357b9 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/Dialog.java @@ -0,0 +1,9 @@ +package net.md_5.bungee.api.dialog; + +public interface Dialog +{ + + DialogBase getBase(); + + void setBase(DialogBase base); +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogBase.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogBase.java new file mode 100644 index 00000000..df84a390 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogBase.java @@ -0,0 +1,21 @@ +package net.md_5.bungee.api.dialog; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@AllArgsConstructor +@RequiredArgsConstructor +@Accessors(fluent = true) +public class DialogBase +{ + + private final BaseComponent title; + private BaseComponent externalTitle; + private List body; + private boolean canCloseWithEscape; +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogListDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogListDialog.java new file mode 100644 index 00000000..d37a54d7 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/DialogListDialog.java @@ -0,0 +1,41 @@ +package net.md_5.bungee.api.dialog; + +import com.google.gson.annotations.SerializedName; +import java.util.Arrays; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.ClickEvent; + +@Data +@ToString +@EqualsAndHashCode +@Accessors(fluent = true) +public class DialogListDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private List dialogs; + @SerializedName("on_cancel") + private ClickEvent onCancel; + private int columns; + @SerializedName("button_width") + private int buttonWidth; + + public DialogListDialog(DialogBase base, Dialog... dialogs) + { + this( base, Arrays.asList( dialogs ), null, 2, 150 ); + } + + public DialogListDialog(DialogBase base, List dialogs, ClickEvent onCancel, int columns, int buttonWidth) + { + this.base = base; + this.dialogs = dialogs; + this.onCancel = onCancel; + this.columns = columns; + this.buttonWidth = buttonWidth; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionDialog.java new file mode 100644 index 00000000..86591701 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionDialog.java @@ -0,0 +1,42 @@ +package net.md_5.bungee.api.dialog; + +import com.google.common.base.Preconditions; +import com.google.gson.annotations.SerializedName; +import java.util.Arrays; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.dialog.action.DialogClickAction; + +@Data +@ToString +@EqualsAndHashCode +@Accessors(fluent = true) +public class MultiActionDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private List actions; + private int columns; + @SerializedName("on_cancel") + private ClickEvent onCancel; + + public MultiActionDialog(DialogBase base, DialogClickAction... actions) + { + this( base, Arrays.asList( actions ), 2, null ); + } + + public MultiActionDialog(DialogBase base, List actions, int columns, ClickEvent onCancel) + { + Preconditions.checkArgument( actions != null && !actions.isEmpty(), "At least one action must be provided" ); + + this.base = base; + this.actions = actions; + this.columns = columns; + this.onCancel = onCancel; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionInputFormDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionInputFormDialog.java new file mode 100644 index 00000000..227c273b --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/MultiActionInputFormDialog.java @@ -0,0 +1,29 @@ +package net.md_5.bungee.api.dialog; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.dialog.action.DialogClickAction; +import net.md_5.bungee.api.dialog.input.DialogInput; + +@Data +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@Accessors(fluent = true) +public class MultiActionInputFormDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private List inputs; + private List actions; + + public MultiActionInputFormDialog(DialogBase base) + { + this( base, null, null ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/NoticeDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/NoticeDialog.java new file mode 100644 index 00000000..c54366d7 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/NoticeDialog.java @@ -0,0 +1,26 @@ +package net.md_5.bungee.api.dialog; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.dialog.action.DialogClickAction; + +@Data +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@Accessors(fluent = true) +public class NoticeDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private DialogClickAction action; + + public NoticeDialog(DialogBase base) + { + this( base, null ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/ServerLinksDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/ServerLinksDialog.java new file mode 100644 index 00000000..f7fd5c59 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/ServerLinksDialog.java @@ -0,0 +1,31 @@ +package net.md_5.bungee.api.dialog; + +import com.google.gson.annotations.SerializedName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.ClickEvent; + +@Data +@ToString +@EqualsAndHashCode +@AllArgsConstructor +@Accessors(fluent = true) +public class ServerLinksDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + @SerializedName("on_click") + private ClickEvent onClick; + private int columns; + @SerializedName("button_width") + private int buttonWidth; + + public ServerLinksDialog(DialogBase base) + { + this( base, null, 2, 150 ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/SimpleInputFormDialog.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/SimpleInputFormDialog.java new file mode 100644 index 00000000..c7c03166 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/SimpleInputFormDialog.java @@ -0,0 +1,40 @@ +package net.md_5.bungee.api.dialog; + +import java.util.Arrays; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.dialog.action.DialogSubmitAction; +import net.md_5.bungee.api.dialog.input.DialogInput; + +@Data +@ToString +@EqualsAndHashCode +@Accessors(fluent = true) +public class SimpleInputFormDialog implements Dialog +{ + + @Accessors(fluent = false) + private DialogBase base; + private List inputs; + private DialogSubmitAction action; + + public SimpleInputFormDialog(DialogBase base, DialogInput... inputs) + { + this( base, null, inputs ); + } + + public SimpleInputFormDialog(DialogBase base, DialogSubmitAction action, DialogInput... inputs) + { + this( base, action, Arrays.asList( inputs ) ); + } + + public SimpleInputFormDialog(DialogBase base, DialogSubmitAction action, List inputs) + { + this.base = base; + this.inputs = inputs; + this.action = action; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogAction.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogAction.java new file mode 100644 index 00000000..25b86798 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogAction.java @@ -0,0 +1,20 @@ +package net.md_5.bungee.api.dialog.action; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@AllArgsConstructor +public class DialogAction +{ + + private BaseComponent label; + private BaseComponent tooltip; + private int width; + + public DialogAction(BaseComponent label) + { + this( label, null, 150 ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogClickAction.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogClickAction.java new file mode 100644 index 00000000..6a47ec42 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogClickAction.java @@ -0,0 +1,36 @@ +package net.md_5.bungee.api.dialog.action; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.chat.ClickEvent; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class DialogClickAction extends DialogAction +{ + + @SerializedName("on_click") + private ClickEvent onClick; + + public DialogClickAction(BaseComponent label) + { + this( null, label ); + } + + public DialogClickAction(ClickEvent onClick, BaseComponent label) + { + this( onClick, label, null, 150 ); + } + + public DialogClickAction(ClickEvent onClick, BaseComponent label, BaseComponent tooltip, int width) + { + super( label, tooltip, width ); + this.onClick = onClick; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogSubmitAction.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogSubmitAction.java new file mode 100644 index 00000000..f3ba3224 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/action/DialogSubmitAction.java @@ -0,0 +1,33 @@ +package net.md_5.bungee.api.dialog.action; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; +import net.md_5.bungee.api.dialog.submit.DialogSubmission; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class DialogSubmitAction extends DialogAction +{ + + private String id; + @SerializedName("on_submit") + private DialogSubmission onSubmit; + + public DialogSubmitAction(String id, DialogSubmission onSubmit, BaseComponent label) + { + this( id, onSubmit, label, null, 150 ); + } + + public DialogSubmitAction(String id, DialogSubmission onSubmit, BaseComponent label, BaseComponent tooltip, int width) + { + super( label, tooltip, width ); + this.id = id; + this.onSubmit = onSubmit; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/body/DialogBody.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/body/DialogBody.java new file mode 100644 index 00000000..e49973c0 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/body/DialogBody.java @@ -0,0 +1,10 @@ +package net.md_5.bungee.api.dialog.body; + +import lombok.Data; + +@Data +public class DialogBody +{ + + private final String type; +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/body/PlainMessageBody.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/body/PlainMessageBody.java new file mode 100644 index 00000000..52108dc5 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/body/PlainMessageBody.java @@ -0,0 +1,28 @@ +package net.md_5.bungee.api.dialog.body; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class PlainMessageBody extends DialogBody +{ + + private BaseComponent contents; + private int width; + + public PlainMessageBody(BaseComponent contents) + { + this( contents, 200 ); + } + + public PlainMessageBody(BaseComponent contents, int width) + { + super( "minecraft:plain_message" ); + this.contents = contents; + this.width = width; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/chat/ShowDialogClickEvent.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/chat/ShowDialogClickEvent.java new file mode 100644 index 00000000..868ec431 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/chat/ShowDialogClickEvent.java @@ -0,0 +1,42 @@ +package net.md_5.bungee.api.dialog.chat; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.dialog.Dialog; + +/** + * Click event which displays either a pre-existing dialog by key or a custom + * dialog. + */ +@Data +@EqualsAndHashCode(callSuper = false) +public class ShowDialogClickEvent extends ClickEvent +{ + + /** + * Key for a pre-existing dialog to show. + */ + private String reference; + /** + * Dialog to show. + */ + private Dialog dialog; + + public ShowDialogClickEvent(String reference) + { + this( reference, null ); + } + + public ShowDialogClickEvent(Dialog dialog) + { + this( null, dialog ); + } + + private ShowDialogClickEvent(String reference, Dialog dialog) + { + super( Action.SHOW_DIALOG, null ); + this.reference = reference; + this.dialog = dialog; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/BooleanInput.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/BooleanInput.java new file mode 100644 index 00000000..4ffecd2f --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/BooleanInput.java @@ -0,0 +1,37 @@ +package net.md_5.bungee.api.dialog.input; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class BooleanInput extends DialogInput +{ + + private BaseComponent label; + private boolean initial; + @SerializedName("on_true") + private String onTrue; + @SerializedName("on_false") + private String onFalse; + + public BooleanInput(String key, BaseComponent label) + { + this( key, label, false, "true", "false" ); + } + + public BooleanInput(String key, BaseComponent label, boolean initial, String onTrue, String onFalse) + { + super( "minecraft:boolean", key ); + this.label = label; + this.initial = initial; + this.onTrue = onTrue; + this.onFalse = onFalse; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/DialogInput.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/DialogInput.java new file mode 100644 index 00000000..ecf4880e --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/DialogInput.java @@ -0,0 +1,13 @@ +package net.md_5.bungee.api.dialog.input; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(fluent = true) +public class DialogInput +{ + + private final String type; + private final String key; +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/InputOption.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/InputOption.java new file mode 100644 index 00000000..ae15f5c6 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/InputOption.java @@ -0,0 +1,22 @@ +package net.md_5.bungee.api.dialog.input; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@AllArgsConstructor +@Accessors(fluent = true) +public class InputOption +{ + + private String id; + private BaseComponent display; + private boolean initial; + + public InputOption(String id) + { + this( id, null, false ); + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/NumberRangeInput.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/NumberRangeInput.java new file mode 100644 index 00000000..52055d02 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/NumberRangeInput.java @@ -0,0 +1,40 @@ +package net.md_5.bungee.api.dialog.input; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class NumberRangeInput extends DialogInput +{ + + private int width; + private BaseComponent label; + private String labelFormat; + private int start; + private int end; + private int steps; + private int initial; + + public NumberRangeInput(String key, BaseComponent label, int start, int end, int steps) + { + this( key, 200, label, "options.generic_value", start, end, steps, start ); + } + + public NumberRangeInput(String key, int width, BaseComponent label, String labelFormat, int start, int end, int steps, int initial) + { + super( "minecraft:number_range", key ); + this.width = width; + this.label = label; + this.labelFormat = labelFormat; + this.start = start; + this.end = end; + this.steps = steps; + this.initial = initial; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/SingleOptionInput.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/SingleOptionInput.java new file mode 100644 index 00000000..0f92ffa4 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/SingleOptionInput.java @@ -0,0 +1,38 @@ +package net.md_5.bungee.api.dialog.input; + +import com.google.gson.annotations.SerializedName; +import java.util.Arrays; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class SingleOptionInput extends DialogInput +{ + + private int width; + private BaseComponent label; + @SerializedName("label_visible") + private boolean labelVisible; + private List options; + + public SingleOptionInput(String key, BaseComponent label, InputOption... options) + { + this( key, 200, label, true, Arrays.asList( options ) ); + } + + public SingleOptionInput(String key, int width, BaseComponent label, boolean labelVisible, List options) + { + super( "minecraft:single_option", key ); + this.width = width; + this.label = label; + this.labelVisible = labelVisible; + this.options = options; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/input/TextInput.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/TextInput.java new file mode 100644 index 00000000..5ce8130b --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/input/TextInput.java @@ -0,0 +1,36 @@ +package net.md_5.bungee.api.dialog.input; + +import com.google.gson.annotations.SerializedName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; +import net.md_5.bungee.api.chat.BaseComponent; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class TextInput extends DialogInput +{ + + private int width; + private BaseComponent label; + @SerializedName("label_visible") + private boolean labelVisible; + private String initial; + + public TextInput(String key, BaseComponent label) + { + this( key, 200, label, true, "" ); + } + + public TextInput(String key, int width, BaseComponent label, boolean labelVisible, String initial) + { + super( "minecraft:text", key ); + this.width = width; + this.label = label; + this.labelVisible = labelVisible; + this.initial = initial; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CommandTemplateSubmission.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CommandTemplateSubmission.java new file mode 100644 index 00000000..9ba076fc --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CommandTemplateSubmission.java @@ -0,0 +1,22 @@ +package net.md_5.bungee.api.dialog.submit; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class CommandTemplateSubmission extends DialogSubmission +{ + + private String template; + + public CommandTemplateSubmission(String template) + { + super( "minecraft:command_template" ); + this.template = template; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomFormSubmission.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomFormSubmission.java new file mode 100644 index 00000000..fa0fd2ce --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomFormSubmission.java @@ -0,0 +1,22 @@ +package net.md_5.bungee.api.dialog.submit; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class CustomFormSubmission extends DialogSubmission +{ + + private String id; + + public CustomFormSubmission(String id) + { + super( "minecraft:custom_form" ); + this.id = id; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomTemplateSubmission.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomTemplateSubmission.java new file mode 100644 index 00000000..3013825c --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/CustomTemplateSubmission.java @@ -0,0 +1,24 @@ +package net.md_5.bungee.api.dialog.submit; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import lombok.experimental.Accessors; + +@Data +@Accessors(fluent = true) +@ToString(callSuper = true) +@EqualsAndHashCode(callSuper = true) +public class CustomTemplateSubmission extends DialogSubmission +{ + + private String id; + private String template; + + public CustomTemplateSubmission(String id, String template) + { + super( "minecraft:custom_template" ); + this.id = id; + this.template = template; + } +} diff --git a/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/DialogSubmission.java b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/DialogSubmission.java new file mode 100644 index 00000000..81cbb6c3 --- /dev/null +++ b/dialog/src/main/java/net/md_5/bungee/api/dialog/submit/DialogSubmission.java @@ -0,0 +1,12 @@ +package net.md_5.bungee.api.dialog.submit; + +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(fluent = true) +public class DialogSubmission +{ + + private final String type; +} diff --git a/pom.xml b/pom.xml index 0af145e1..5d540b2c 100644 --- a/pom.xml +++ b/pom.xml @@ -35,12 +35,14 @@ bootstrap chat config + dialog event log module protocol proxy query + serializer slf4j native diff --git a/protocol/pom.xml b/protocol/pom.xml index 10278395..77e11507 100644 --- a/protocol/pom.xml +++ b/protocol/pom.xml @@ -36,7 +36,7 @@ net.md-5 - bungeecord-chat + bungeecord-serializer ${project.version} compile diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java index 8d91211b..8c73509b 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/AbstractPacketHandler.java @@ -2,6 +2,7 @@ package net.md_5.bungee.protocol; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClearDialog; import net.md_5.bungee.protocol.packet.ClearTitles; import net.md_5.bungee.protocol.packet.ClientChat; import net.md_5.bungee.protocol.packet.ClientCommand; @@ -10,6 +11,7 @@ import net.md_5.bungee.protocol.packet.ClientStatus; import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.CookieRequest; import net.md_5.bungee.protocol.packet.CookieResponse; +import net.md_5.bungee.protocol.packet.CustomClickAction; import net.md_5.bungee.protocol.packet.DisconnectReportDetails; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; @@ -41,6 +43,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardScoreReset; import net.md_5.bungee.protocol.packet.ServerData; import net.md_5.bungee.protocol.packet.ServerLinks; import net.md_5.bungee.protocol.packet.SetCompression; +import net.md_5.bungee.protocol.packet.ShowDialog; import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; @@ -278,4 +281,16 @@ public abstract class AbstractPacketHandler public void handle(ServerLinks serverLinks) throws Exception { } + + public void handle(ShowDialog showDialog) throws Exception + { + } + + public void handle(ClearDialog clearDialog) throws Exception + { + } + + public void handle(CustomClickAction customClickAction) throws Exception + { + } } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java index 40fdb868..32ffa28f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/Protocol.java @@ -11,6 +11,7 @@ import lombok.Data; import lombok.Getter; import net.md_5.bungee.protocol.packet.BossBar; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClearDialog; import net.md_5.bungee.protocol.packet.ClearTitles; import net.md_5.bungee.protocol.packet.ClientChat; import net.md_5.bungee.protocol.packet.ClientCommand; @@ -18,6 +19,7 @@ import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.Commands; import net.md_5.bungee.protocol.packet.CookieRequest; import net.md_5.bungee.protocol.packet.CookieResponse; +import net.md_5.bungee.protocol.packet.CustomClickAction; import net.md_5.bungee.protocol.packet.DisconnectReportDetails; import net.md_5.bungee.protocol.packet.EncryptionRequest; import net.md_5.bungee.protocol.packet.EncryptionResponse; @@ -47,6 +49,7 @@ import net.md_5.bungee.protocol.packet.ScoreboardScoreReset; import net.md_5.bungee.protocol.packet.ServerData; import net.md_5.bungee.protocol.packet.ServerLinks; import net.md_5.bungee.protocol.packet.SetCompression; +import net.md_5.bungee.protocol.packet.ShowDialog; import net.md_5.bungee.protocol.packet.StartConfiguration; import net.md_5.bungee.protocol.packet.StatusRequest; import net.md_5.bungee.protocol.packet.StatusResponse; @@ -559,6 +562,16 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_21, 0x7B ), map( ProtocolConstants.MINECRAFT_1_21_2, 0x82 ) ); + TO_CLIENT.registerPacket( + ClearDialog.class, + ClearDialog::new, + map( ProtocolConstants.MINECRAFT_1_21_6, 0x84 ) + ); + TO_CLIENT.registerPacket( + ShowDialog.class, + ShowDialog::new, + map( ProtocolConstants.MINECRAFT_1_21_6, 0x85 ) + ); TO_SERVER.registerPacket( KeepAlive.class, @@ -578,7 +591,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_20_2, 0x14 ), map( ProtocolConstants.MINECRAFT_1_20_3, 0x15 ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x18 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x1A ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x1A ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x1B ) ); TO_SERVER.registerPacket( Chat.class, Chat::new, @@ -595,14 +609,15 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19, 0x03 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x04 ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x05 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x06 ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x06 ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x07 ) ); TO_SERVER.registerPacket( UnsignedClientCommand.class, UnsignedClientCommand::new, map( ProtocolConstants.MINECRAFT_1_20_5, 0x04 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x05 ) - + map( ProtocolConstants.MINECRAFT_1_21_2, 0x05 ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x06 ) ); TO_SERVER.registerPacket( ClientChat.class, @@ -610,7 +625,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19, 0x04 ), map( ProtocolConstants.MINECRAFT_1_19_1, 0x05 ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x06 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x07 ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x07 ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x08 ) ); TO_SERVER.registerPacket( TabCompleteRequest.class, @@ -627,7 +643,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_4, 0x09 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x0A ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x0B ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x0D ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x0D ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x0E ) ); TO_SERVER.registerPacket( ClientSettings.class, @@ -643,7 +660,8 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_19_4, 0x08 ), map( ProtocolConstants.MINECRAFT_1_20_2, 0x09 ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x0A ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x0C ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x0C ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x0D ) ); TO_SERVER.registerPacket( PluginMessage.class, @@ -662,20 +680,28 @@ public enum Protocol map( ProtocolConstants.MINECRAFT_1_20_2, 0x0F ), map( ProtocolConstants.MINECRAFT_1_20_3, 0x10 ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x12 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x14 ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x14 ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x15 ) ); TO_SERVER.registerPacket( StartConfiguration.class, StartConfiguration::new, map( ProtocolConstants.MINECRAFT_1_20_2, 0x0B ), map( ProtocolConstants.MINECRAFT_1_20_5, 0x0C ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x0E ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x0E ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x0F ) ); TO_SERVER.registerPacket( CookieResponse.class, CookieResponse::new, map( ProtocolConstants.MINECRAFT_1_20_5, 0x11 ), - map( ProtocolConstants.MINECRAFT_1_21_2, 0x13 ) + map( ProtocolConstants.MINECRAFT_1_21_2, 0x13 ), + map( ProtocolConstants.MINECRAFT_1_21_6, 0x14 ) + ); + TO_SERVER.registerPacket( + CustomClickAction.class, + CustomClickAction::new, + map( ProtocolConstants.MINECRAFT_1_21_6, 0x41 ) ); } }, diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java index 6e00f1a6..a2cac13f 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/ProtocolConstants.java @@ -50,7 +50,7 @@ public class ProtocolConstants public static final int MINECRAFT_1_21_2 = 768; public static final int MINECRAFT_1_21_4 = 769; public static final int MINECRAFT_1_21_5 = 770; - public static final int MINECRAFT_1_21_6 = 1073742073; + public static final int MINECRAFT_1_21_6 = 1073742074; public static final List SUPPORTED_VERSIONS; public static final List SUPPORTED_VERSION_IDS; diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearDialog.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearDialog.java new file mode 100644 index 00000000..612a130b --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ClearDialog.java @@ -0,0 +1,32 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ClearDialog extends DefinedPacket +{ + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java index 1f32ba1f..e0953932 100644 --- a/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/Commands.java @@ -745,8 +745,8 @@ public class Commands extends DefinedPacket get( "minecraft:resource_key", RAW_STRING ), get( "minecraft:template_mirror", VOID ), get( "minecraft:template_rotation", VOID ), - get( "minecraft:uuid", VOID ), - get( "minecraft:heightmap", VOID ) + get( "minecraft:heightmap", VOID ), + get( "minecraft:uuid", VOID ) }; IDS_1_20_3 = new ArgumentSerializer[] @@ -799,8 +799,8 @@ public class Commands extends DefinedPacket get( "minecraft:resource_key", RAW_STRING ), get( "minecraft:template_mirror", VOID ), get( "minecraft:template_rotation", VOID ), - get( "minecraft:uuid", VOID ), - get( "minecraft:heightmap", VOID ) + get( "minecraft:heightmap", VOID ), + get( "minecraft:uuid", VOID ) }; IDS_1_20_5 = new ArgumentSerializer[] @@ -854,11 +854,11 @@ public class Commands extends DefinedPacket get( "minecraft:resource_key", RAW_STRING ), get( "minecraft:template_mirror", VOID ), get( "minecraft:template_rotation", VOID ), - get( "minecraft:uuid", VOID ), get( "minecraft:heightmap", VOID ), get( "minecraft:loot_table", VOID ), get( "minecraft:loot_predicate", VOID ), - get( "minecraft:loot_modifier", VOID ) + get( "minecraft:loot_modifier", VOID ), + get( "minecraft:uuid", VOID ) }; IDS_1_21_5 = new ArgumentSerializer[] @@ -913,11 +913,11 @@ public class Commands extends DefinedPacket get( "minecraft:resource_selector", RAW_STRING ), get( "minecraft:template_mirror", VOID ), get( "minecraft:template_rotation", VOID ), - get( "minecraft:uuid", VOID ), get( "minecraft:heightmap", VOID ), get( "minecraft:loot_table", VOID ), get( "minecraft:loot_predicate", VOID ), - get( "minecraft:loot_modifier", VOID ) + get( "minecraft:loot_modifier", VOID ), + get( "minecraft:uuid", VOID ) }; IDS_1_21_6 = new ArgumentSerializer[] @@ -973,11 +973,12 @@ public class Commands extends DefinedPacket get( "minecraft:resource_selector", RAW_STRING ), get( "minecraft:template_mirror", VOID ), get( "minecraft:template_rotation", VOID ), - get( "minecraft:uuid", VOID ), get( "minecraft:heightmap", VOID ), get( "minecraft:loot_table", VOID ), get( "minecraft:loot_predicate", VOID ), - get( "minecraft:loot_modifier", VOID ) + get( "minecraft:loot_modifier", VOID ), + get( "minecraft:dialog", VOID ), + get( "minecraft:uuid", VOID ) }; } diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/CustomClickAction.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CustomClickAction.java new file mode 100644 index 00000000..9b2ff7cd --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/CustomClickAction.java @@ -0,0 +1,47 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Protocol; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class CustomClickAction extends DefinedPacket +{ + + private String id; + private String data; + + @Override + public void read(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion) + { + id = readString( buf ); + data = readNullable( DefinedPacket::readString, buf ); + } + + @Override + public void write(ByteBuf buf, Protocol protocol, ProtocolConstants.Direction direction, int protocolVersion) + { + writeString( id, buf ); + writeNullable( data, DefinedPacket::writeString, buf ); + } + + @Override + public void write(ByteBuf buf) + { + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialog.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialog.java new file mode 100644 index 00000000..440020c8 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialog.java @@ -0,0 +1,73 @@ +package net.md_5.bungee.protocol.packet; + +import com.google.gson.JsonElement; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.api.dialog.Dialog; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.ChatSerializer; +import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Either; +import net.md_5.bungee.protocol.ProtocolConstants; +import net.md_5.bungee.protocol.TagUtil; +import se.llbit.nbt.SpecificTag; + +@Data +@NoArgsConstructor +@AllArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ShowDialog extends DefinedPacket +{ + + protected Either dialog; + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + int id = readVarInt( buf ); + if ( id == 0 ) + { + dialog = Either.right( readDialog( buf, direction, protocolVersion ) ); + } else + { + dialog = Either.left( id ); + } + } + + protected static Dialog readDialog(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + SpecificTag nbt = (SpecificTag) readTag( buf, protocolVersion ); + JsonElement json = TagUtil.toJson( nbt ); + return ChatSerializer.forVersion( protocolVersion ).getDialogSerializer().deserialize( json ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + if ( dialog.isLeft() ) + { + writeVarInt( dialog.getLeft(), buf ); + } else + { + writeVarInt( 0, buf ); + writeDialog( dialog.getRight(), buf, direction, protocolVersion ); + } + } + + protected static void writeDialog(Dialog dialog, ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + JsonElement json = ChatSerializer.forVersion( protocolVersion ).getDialogSerializer().toJson( dialog ); + SpecificTag nbt = TagUtil.fromJson( json ); + + writeTag( nbt, buf, protocolVersion ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialogDirect.java b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialogDirect.java new file mode 100644 index 00000000..8a6ce652 --- /dev/null +++ b/protocol/src/main/java/net/md_5/bungee/protocol/packet/ShowDialogDirect.java @@ -0,0 +1,40 @@ +package net.md_5.bungee.protocol.packet; + +import io.netty.buffer.ByteBuf; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import net.md_5.bungee.api.dialog.Dialog; +import net.md_5.bungee.protocol.AbstractPacketHandler; +import net.md_5.bungee.protocol.Either; +import net.md_5.bungee.protocol.ProtocolConstants; + +@Data +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) +public class ShowDialogDirect extends ShowDialog +{ + + public ShowDialogDirect(Dialog dialog) + { + super( Either.right( dialog ) ); + } + + @Override + public void read(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + dialog = Either.right( readDialog( buf, direction, protocolVersion ) ); + } + + @Override + public void write(ByteBuf buf, ProtocolConstants.Direction direction, int protocolVersion) + { + writeDialog( dialog.getRight(), buf, direction, protocolVersion ); + } + + @Override + public void handle(AbstractPacketHandler handler) throws Exception + { + handler.handle( this ); + } +} diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index 35e59709..d5df3c27 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -35,6 +35,7 @@ import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.ProxiedPlayer; +import net.md_5.bungee.api.dialog.Dialog; import net.md_5.bungee.api.event.PermissionCheckEvent; import net.md_5.bungee.api.event.ServerConnectEvent; import net.md_5.bungee.api.score.Scoreboard; @@ -49,15 +50,18 @@ import net.md_5.bungee.netty.HandlerBoss; import net.md_5.bungee.netty.PipelineUtils; import net.md_5.bungee.protocol.ChatSerializer; import net.md_5.bungee.protocol.DefinedPacket; +import net.md_5.bungee.protocol.Either; import net.md_5.bungee.protocol.PacketWrapper; import net.md_5.bungee.protocol.Protocol; import net.md_5.bungee.protocol.ProtocolConstants; import net.md_5.bungee.protocol.packet.Chat; +import net.md_5.bungee.protocol.packet.ClearDialog; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.Kick; import net.md_5.bungee.protocol.packet.PlayerListHeaderFooter; import net.md_5.bungee.protocol.packet.PluginMessage; import net.md_5.bungee.protocol.packet.SetCompression; +import net.md_5.bungee.protocol.packet.ShowDialog; import net.md_5.bungee.protocol.packet.StoreCookie; import net.md_5.bungee.protocol.packet.SystemChat; import net.md_5.bungee.protocol.packet.Transfer; @@ -826,4 +830,20 @@ public final class UserConnection implements ProxiedPlayer unsafe().sendPacket( new Transfer( host, port ) ); } + + @Override + public void clearDialog() + { + Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_21_6, "Dialogs are only supported in 1.21.6 and above" ); + + unsafe().sendPacket( new ClearDialog() ); + } + + @Override + public void showDialog(Dialog dialog) + { + Preconditions.checkState( getPendingConnection().getVersion() >= ProtocolConstants.MINECRAFT_1_21_6, "Dialogs are only supported in 1.21.6 and above" ); + + unsafe.sendPacket( new ShowDialog( Either.right( dialog ) ) ); + } } diff --git a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 93f57bc1..c0fdf533 100644 --- a/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/proxy/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -1,6 +1,7 @@ package net.md_5.bungee.connection; import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; import com.mojang.brigadier.context.StringRange; import com.mojang.brigadier.suggestion.Suggestion; import com.mojang.brigadier.suggestion.Suggestions; @@ -8,6 +9,7 @@ import io.netty.channel.Channel; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.UUID; import net.md_5.bungee.BungeeCord; import net.md_5.bungee.ServerConnection; @@ -17,6 +19,7 @@ import net.md_5.bungee.Util; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.ChatEvent; +import net.md_5.bungee.api.event.CustomClickEvent; import net.md_5.bungee.api.event.PlayerDisconnectEvent; import net.md_5.bungee.api.event.PluginMessageEvent; import net.md_5.bungee.api.event.SettingsChangedEvent; @@ -33,6 +36,7 @@ import net.md_5.bungee.protocol.packet.ClientChat; import net.md_5.bungee.protocol.packet.ClientCommand; import net.md_5.bungee.protocol.packet.ClientSettings; import net.md_5.bungee.protocol.packet.CookieResponse; +import net.md_5.bungee.protocol.packet.CustomClickAction; import net.md_5.bungee.protocol.packet.KeepAlive; import net.md_5.bungee.protocol.packet.LoginAcknowledged; import net.md_5.bungee.protocol.packet.LoginPayloadResponse; @@ -378,6 +382,30 @@ public class UpstreamBridge extends PacketHandler con.getPendingConnection().handle( loginPayloadResponse ); } + @Override + public void handle(CustomClickAction customClickAction) throws Exception + { + Map data = null; + if ( customClickAction.getData() != null ) + { + ImmutableMap.Builder parsed = ImmutableMap.builder(); + + String[] lines = customClickAction.getData().split( "\n" ); + for ( String line : lines ) + { + String[] split = line.split( "\t", 2 ); + parsed.put( split[0], ( split.length > 1 ) ? split[1] : "" ); + } + data = parsed.build(); + } + + CustomClickEvent event = new CustomClickEvent( con, customClickAction.getId(), data ); + if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) + { + throw CancelSendSignal.INSTANCE; + } + } + @Override public String toString() { diff --git a/serializer/nb-configuration.xml b/serializer/nb-configuration.xml new file mode 100644 index 00000000..7e465924 --- /dev/null +++ b/serializer/nb-configuration.xml @@ -0,0 +1,31 @@ + + + + + + project + NEW_LINE + NEW_LINE + NEW_LINE + true + true + true + true + true + true + true + true + true + true + + diff --git a/serializer/pom.xml b/serializer/pom.xml new file mode 100644 index 00000000..670eb6bc --- /dev/null +++ b/serializer/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + net.md-5 + bungeecord-parent + 1.21-R0.3-SNAPSHOT + ../pom.xml + + + net.md-5 + bungeecord-serializer + 1.21-R0.3-SNAPSHOT + jar + + BungeeCord-Serializer + Minecraft JSON serializer intended for use with BungeeCord + + + + com.google.code.gson + gson + 2.11.0 + compile + + + ${project.groupId} + bungeecord-chat + ${project.version} + compile + + + ${project.groupId} + bungeecord-dialog + ${project.version} + compile + + + diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java b/serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java rename to serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/EntitySerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/ItemSerializer.java b/serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/ItemSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/api/chat/hover/content/ItemSerializer.java rename to serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/ItemSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/api/chat/hover/content/TextSerializer.java b/serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/TextSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/api/chat/hover/content/TextSerializer.java rename to serializer/src/main/java/net/md_5/bungee/api/chat/hover/content/TextSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java similarity index 90% rename from chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java index e36e0009..48e6a16c 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java +++ b/serializer/src/main/java/net/md_5/bungee/chat/BaseComponentSerializer.java @@ -13,9 +13,11 @@ import java.util.Locale; import lombok.RequiredArgsConstructor; import net.md_5.bungee.api.chat.BaseComponent; import net.md_5.bungee.api.chat.ClickEvent; +import net.md_5.bungee.api.chat.ClickEventCustom; import net.md_5.bungee.api.chat.ComponentStyle; import net.md_5.bungee.api.chat.HoverEvent; import net.md_5.bungee.api.chat.hover.content.Content; +import net.md_5.bungee.api.dialog.chat.ShowDialogClickEvent; @RequiredArgsConstructor public class BaseComponentSerializer @@ -59,6 +61,12 @@ public class BaseComponentSerializer Preconditions.checkArgument( page >= 0, "Page number has to be positive" ); component.setClickEvent( new ClickEvent( action, Integer.toString( page ) ) ); break; + case SHOW_DIALOG: + component.setClickEvent( context.deserialize( clickEvent.get( "dialog" ), ShowDialogClickEvent.class ) ); + break; + case CUSTOM: + component.setClickEvent( new ClickEventCustom( clickEvent.get( "id" ).getAsString(), ( clickEvent.has( "payload" ) ) ? clickEvent.get( "payload" ).getAsString() : null ) ); + break; default: component.setClickEvent( new ClickEvent( action, ( clickEvent.has( "value" ) ) ? clickEvent.get( "value" ).getAsString() : "" ) ); break; @@ -182,6 +190,17 @@ public class BaseComponentSerializer case CHANGE_PAGE: clickEvent.addProperty( "page", Integer.parseInt( component.getClickEvent().getValue() ) ); break; + case SHOW_DIALOG: + clickEvent.add( "dialog", context.serialize( component.getClickEvent() ) ); + break; + case CUSTOM: + ClickEventCustom custom = (ClickEventCustom) component.getClickEvent(); + clickEvent.addProperty( "id", custom.getValue() ); + if ( custom.getPayload() != null ) + { + clickEvent.addProperty( "payload", custom.getPayload() ); + } + break; default: clickEvent.addProperty( "value", component.getClickEvent().getValue() ); break; diff --git a/chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java b/serializer/src/main/java/net/md_5/bungee/chat/ChatVersion.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/ChatVersion.java rename to serializer/src/main/java/net/md_5/bungee/chat/ChatVersion.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/ComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/ComponentStyleSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/KeybindComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/ScoreComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/SelectorComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/TextComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java similarity index 100% rename from chat/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/TranslatableComponentSerializer.java diff --git a/chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java b/serializer/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java similarity index 94% rename from chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java rename to serializer/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java index a46adc17..8abf5d25 100644 --- a/chat/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java +++ b/serializer/src/main/java/net/md_5/bungee/chat/VersionedComponentSerializer.java @@ -28,6 +28,10 @@ import net.md_5.bungee.api.chat.hover.content.Item; import net.md_5.bungee.api.chat.hover.content.ItemSerializer; import net.md_5.bungee.api.chat.hover.content.Text; import net.md_5.bungee.api.chat.hover.content.TextSerializer; +import net.md_5.bungee.api.dialog.Dialog; +import net.md_5.bungee.api.dialog.chat.ShowDialogClickEvent; +import net.md_5.bungee.dialog.DialogSerializer; +import net.md_5.bungee.dialog.ShowDialogClickEventSerializer; import org.jetbrains.annotations.ApiStatus; @ApiStatus.Experimental @@ -40,10 +44,14 @@ public class VersionedComponentSerializer implements JsonDeserializer, JsonSerializer +{ + + private static final BiMap> TYPES; + private final VersionedComponentSerializer serializer; + + static + { + ImmutableBiMap.Builder> builder = ImmutableBiMap.builder(); + + builder.put( "minecraft:notice", NoticeDialog.class ); + builder.put( "minecraft:confirmation", ConfirmationDialog.class ); + builder.put( "minecraft:multi_action", MultiActionDialog.class ); + builder.put( "minecraft:server_links", ServerLinksDialog.class ); + builder.put( "minecraft:dialog_list", DialogListDialog.class ); + builder.put( "minecraft:simple_input_form", SimpleInputFormDialog.class ); + builder.put( "minecraft:multi_action_input_form", MultiActionInputFormDialog.class ); + + TYPES = builder.build(); + } + + public JsonElement toJson(Dialog dialog) + { + return serializer.getGson().toJsonTree( dialog, Dialog.class ); + } + + public String toString(Dialog dialog) + { + return serializer.getGson().toJson( dialog, Dialog.class ); + } + + public Dialog deserialize(JsonElement jsonElement) + { + return serializer.getGson().fromJson( jsonElement, Dialog.class ); + } + + public Dialog deserialize(String json) + { + JsonElement jsonElement = JsonParser.parseString( json ); + return deserialize( jsonElement ); + } + + @Override + public Dialog deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + JsonObject object = json.getAsJsonObject(); + + String type = object.get( "type" ).getAsString(); + + if ( object.has( "base" ) ) + { + throw new JsonParseException( "Cannot explicitly specify base" ); + } + + Type realType = TYPES.get( type ); + if ( realType == null ) + { + throw new JsonParseException( "Unknown type " + type ); + } + + Dialog dialog = context.deserialize( json, realType ); + + DialogBase base = context.deserialize( json, DialogBase.class ); + dialog.setBase( base ); + + return dialog; + } + + @Override + public JsonElement serialize(Dialog src, Type typeOfSrc, JsonSerializationContext context) + { + if ( src == null ) + { + return JsonNull.INSTANCE; + } + + Class realType = src.getClass(); + String type = TYPES.inverse().get( realType ); + Preconditions.checkArgument( type != null, "Unknown type %s", typeOfSrc ); + + JsonObject object = (JsonObject) context.serialize( src, realType ); + object.addProperty( "type", type ); + + JsonObject base = (JsonObject) context.serialize( src.getBase() ); + object.asMap().putAll( base.asMap() ); + + return object; + } +} diff --git a/serializer/src/main/java/net/md_5/bungee/dialog/ShowDialogClickEventSerializer.java b/serializer/src/main/java/net/md_5/bungee/dialog/ShowDialogClickEventSerializer.java new file mode 100644 index 00000000..5e0966ef --- /dev/null +++ b/serializer/src/main/java/net/md_5/bungee/dialog/ShowDialogClickEventSerializer.java @@ -0,0 +1,38 @@ +package net.md_5.bungee.dialog; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import net.md_5.bungee.api.dialog.Dialog; +import net.md_5.bungee.api.dialog.chat.ShowDialogClickEvent; + +public class ShowDialogClickEventSerializer implements JsonDeserializer, JsonSerializer +{ + + @Override + public ShowDialogClickEvent deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException + { + if ( json.isJsonPrimitive() && json.getAsJsonPrimitive().isString() ) + { + return new ShowDialogClickEvent( json.getAsJsonPrimitive().getAsString() ); + } + + return new ShowDialogClickEvent( (Dialog) context.deserialize( json, Dialog.class ) ); + } + + @Override + public JsonElement serialize(ShowDialogClickEvent src, Type typeOfSrc, JsonSerializationContext context) + { + if ( src.getReference() != null ) + { + return new JsonPrimitive( src.getReference() ); + } + + return context.serialize( src.getDialog(), Dialog.class ); + } +} diff --git a/chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java b/serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java similarity index 100% rename from chat/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java rename to serializer/src/test/java/net/md_5/bungee/api/chat/ComponentsTest.java diff --git a/chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java b/serializer/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java similarity index 100% rename from chat/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java rename to serializer/src/test/java/net/md_5/bungee/api/chat/TranslatableComponentTest.java diff --git a/serializer/src/test/java/net/md_5/bungee/dialog/SimpleTest.java b/serializer/src/test/java/net/md_5/bungee/dialog/SimpleTest.java new file mode 100644 index 00000000..ff7c068d --- /dev/null +++ b/serializer/src/test/java/net/md_5/bungee/dialog/SimpleTest.java @@ -0,0 +1,25 @@ +package net.md_5.bungee.dialog; + +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.chat.ComponentBuilder; +import net.md_5.bungee.api.dialog.Dialog; +import net.md_5.bungee.api.dialog.DialogBase; +import net.md_5.bungee.api.dialog.NoticeDialog; +import net.md_5.bungee.chat.VersionedComponentSerializer; +import org.junit.jupiter.api.Test; + +public class SimpleTest +{ + + @Test + public void testNotice() + { + String json = "{type:\"minecraft:notice\",title:\"Hello\"}"; + Dialog deserialized = VersionedComponentSerializer.getDefault().getDialogSerializer().deserialize( json ); + System.err.println( deserialized ); + + Dialog notice = new NoticeDialog( new DialogBase( new ComponentBuilder( "Hello" ).color( ChatColor.RED ).build() ) ); + String newJson = VersionedComponentSerializer.getDefault().getDialogSerializer().toString( notice ); + System.err.println( newJson ); + } +}