mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-30 20:29:19 +00:00
Fix various things relating to closing and switching of dialogs; implement 2 after-actions; implement exit button on button list dialogs; some cleanup
This commit is contained in:
@@ -176,6 +176,7 @@ import org.geysermc.geyser.session.cache.TeleportCache;
|
||||
import org.geysermc.geyser.session.cache.WorldBorder;
|
||||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
|
||||
import org.geysermc.geyser.session.dialog.DialogManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
@@ -307,6 +308,9 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
@Setter
|
||||
private @Nullable InventoryHolder<? extends Inventory> inventoryHolder;
|
||||
|
||||
@Getter
|
||||
private final DialogManager dialogManager = new DialogManager(this);
|
||||
|
||||
/**
|
||||
* Whether the client is currently closing an inventory.
|
||||
* Used to open new inventories while another one is currently open.
|
||||
@@ -1515,6 +1519,19 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
|
||||
@Override
|
||||
public boolean sendForm(@NonNull Form form) {
|
||||
// First close any dialogs that are open. This won't execute the dialog's closing action.
|
||||
dialogManager.close();
|
||||
return doSendForm(form);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a form without first closing any open dialog. This should only be used by {@link org.geysermc.geyser.session.dialog.Dialog}s.
|
||||
*/
|
||||
public boolean sendDialogForm(@NonNull Form form) {
|
||||
return doSendForm(form);
|
||||
}
|
||||
|
||||
private boolean doSendForm(@NonNull Form form) {
|
||||
formCache.showForm(form);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -37,11 +37,6 @@ public class ConfirmationDialog extends DialogWithButtons {
|
||||
public static final Key TYPE = MinecraftKey.key("confirmation");
|
||||
|
||||
public ConfirmationDialog(GeyserSession session, NbtMap map, IdGetter idGetter) {
|
||||
super(session, map, parseOptionalList(DialogButton.read(session, map.get("yes"), idGetter), DialogButton.read(session, map.get("no"), idGetter)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<DialogButton> onCancel() {
|
||||
return buttons.size() > 1 ? Optional.of(buttons.get(1)) : Optional.empty(); // "no" button, there should always be 2 buttons but check just to be sure
|
||||
super(session, map, parseOptionalList(DialogButton.read(session, map.get("yes"), idGetter), DialogButton.read(session, map.get("no"), idGetter)), Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,10 @@
|
||||
|
||||
package org.geysermc.geyser.session.dialog;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.Accessors;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.cumulus.form.CustomForm;
|
||||
@@ -50,12 +53,16 @@ import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.ToIntFunction;
|
||||
|
||||
@Accessors(fluent = true)
|
||||
public abstract class Dialog {
|
||||
|
||||
private static final Key PLAIN_MESSAGE_BODY = MinecraftKey.key("plain_message");
|
||||
|
||||
private final String title;
|
||||
private final String externalTitle;
|
||||
@Getter
|
||||
private final boolean canCloseWithEscape;
|
||||
@Getter
|
||||
private final AfterAction afterAction;
|
||||
private final List<String> labels;
|
||||
private final List<DialogInput<?>> inputs = new ArrayList<>();
|
||||
@@ -63,6 +70,7 @@ public abstract class Dialog {
|
||||
protected Dialog(GeyserSession session, NbtMap map) {
|
||||
title = MessageTranslator.convertFromNullableNbtTag(session, map.get("title"));
|
||||
externalTitle = MessageTranslator.convertFromNullableNbtTag(session, map.get("title"));
|
||||
canCloseWithEscape = map.getBoolean("can_close_with_escape", true);
|
||||
afterAction = AfterAction.fromString(map.getString("after_action"));
|
||||
|
||||
Object bodyTag = map.get("body");
|
||||
@@ -100,42 +108,42 @@ public abstract class Dialog {
|
||||
|
||||
protected abstract Optional<DialogButton> onCancel();
|
||||
|
||||
protected FormBuilder<? extends FormBuilder<?,?,?>, ? extends Form, ? extends FormResponse> createForm(GeyserSession session) {
|
||||
protected FormBuilder<? extends FormBuilder<?,?,?>, ? extends Form, ? extends FormResponse> createForm(GeyserSession session, Optional<ParsedInputs> restored, DialogHolder holder) {
|
||||
if (inputs.isEmpty()) {
|
||||
SimpleForm.Builder builder = SimpleForm.builder()
|
||||
.title(title);
|
||||
builder.content(String.join("\n", labels));
|
||||
builder.content(String.join("\n\n", labels));
|
||||
|
||||
builder.closedOrInvalidResultHandler(() -> runButton(session, onCancel(), ParsedInputs.EMPTY));
|
||||
addCustomComponents(session, builder);
|
||||
builder.closedOrInvalidResultHandler(() -> holder.closeDialog(onCancel()));
|
||||
addCustomComponents(session, builder, holder);
|
||||
return builder;
|
||||
} else {
|
||||
CustomForm.Builder builder = CustomForm.builder()
|
||||
.title(title);
|
||||
|
||||
inputs.forEach(input -> input.addComponent(builder, Optional.empty()));
|
||||
builder.closedOrInvalidResultHandler(response -> runButton(session, onCancel(), new ParsedInputs(inputs)));
|
||||
addCustomComponents(session, builder);
|
||||
restored.ifPresentOrElse(last -> last.restore(builder), () -> inputs.forEach(input -> input.addComponent(builder)));
|
||||
builder.closedOrInvalidResultHandler(response -> holder.closeDialog(onCancel()));
|
||||
addCustomComponents(session, builder, holder);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void addCustomComponents(GeyserSession session, CustomForm.Builder builder);
|
||||
protected abstract void addCustomComponents(GeyserSession session, CustomForm.Builder builder, DialogHolder holder);
|
||||
|
||||
protected abstract void addCustomComponents(GeyserSession session, SimpleForm.Builder builder);
|
||||
protected abstract void addCustomComponents(GeyserSession session, SimpleForm.Builder builder, DialogHolder holder);
|
||||
|
||||
public Form buildForm(GeyserSession session) {
|
||||
return createForm(session).build();
|
||||
public void sendForm(GeyserSession session, DialogHolder holder) {
|
||||
session.sendDialogForm(createForm(session, Optional.empty(), holder).build());
|
||||
}
|
||||
|
||||
public void restoreForm(GeyserSession session, @NonNull ParsedInputs inputs, DialogHolder holder) {
|
||||
session.sendDialogForm(createForm(session, Optional.of(inputs), holder).build());
|
||||
}
|
||||
|
||||
protected ParsedInputs parseInput(CustomFormResponse response) {
|
||||
return new ParsedInputs(inputs, response);
|
||||
}
|
||||
|
||||
protected void runButton(GeyserSession session, Optional<DialogButton> button, ParsedInputs inputs) {
|
||||
button.flatMap(DialogButton::action).ifPresent(action -> action.run(session, inputs));
|
||||
}
|
||||
|
||||
public static Dialog readDialog(RegistryEntryContext context) {
|
||||
return readDialogFromNbt(context.session(), context.data(), context::getNetworkId);
|
||||
}
|
||||
@@ -154,10 +162,10 @@ public abstract class Dialog {
|
||||
return new Dialog(session, map) {
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder) {}
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder, DialogHolder holder) {}
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder) {}
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder, DialogHolder holder) {}
|
||||
|
||||
@Override
|
||||
protected Optional<DialogButton> onCancel() {
|
||||
@@ -167,14 +175,12 @@ public abstract class Dialog {
|
||||
// throw new UnsupportedOperationException("Unable to read unknown dialog type " + type + "!"); // TODO put this here once all types are implemented
|
||||
}
|
||||
|
||||
public static void showDialog(GeyserSession session, Holder<NbtMap> holder) {
|
||||
Dialog dialog;
|
||||
public static Dialog getDialogFromHolder(GeyserSession session, Holder<NbtMap> holder) {
|
||||
if (holder.isId()) {
|
||||
dialog = JavaRegistries.DIALOG.fromNetworkId(session, holder.id());
|
||||
return Objects.requireNonNull(JavaRegistries.DIALOG.fromNetworkId(session, holder.id()));
|
||||
} else {
|
||||
dialog = Dialog.readDialogFromNbt(session, holder.custom(), key -> JavaRegistries.DIALOG.keyToNetworkId(session, key));
|
||||
return Dialog.readDialogFromNbt(session, holder.custom(), key -> JavaRegistries.DIALOG.keyToNetworkId(session, key));
|
||||
}
|
||||
session.sendForm(Objects.requireNonNull(dialog).buildForm(session));
|
||||
}
|
||||
|
||||
public enum AfterAction {
|
||||
@@ -188,7 +194,7 @@ public abstract class Dialog {
|
||||
return action;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return CLOSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.session.dialog;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.session.dialog.action.DialogAction;
|
||||
import org.geysermc.geyser.session.dialog.input.ParsedInputs;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class DialogHolder {
|
||||
private final DialogManager manager;
|
||||
private final Dialog dialog;
|
||||
private ParsedInputs lastInputs;
|
||||
|
||||
public DialogHolder(DialogManager manager, Dialog dialog) {
|
||||
this.manager = manager;
|
||||
this.dialog = dialog;
|
||||
}
|
||||
|
||||
|
||||
// Dialog action behaviour:
|
||||
// When running an action, if the action:
|
||||
// - opens a new dialog: the new dialog is opened, the old one is closed, its closing action not executed. [ ]
|
||||
// - executes with "none" as after action: the dialog is kept open. The dialog can only be closed by pressing "escape" (when allowed by the dialog), or on bedrock, the X in the corner of the form. [ ] (TODO note about multi action exit)
|
||||
// - executes with "close" as after action: the dialog is closed, its closing action not executed.
|
||||
// A dialogs closing action (onCancel()) is only executed when the dialog is closed by pressing "escape" (when allowed by the dialog). [ ]
|
||||
// If a new dialog is opened by the server when a dialog is already open, that dialog is closed, its closing action not executed. [ ]
|
||||
|
||||
public void runButton(Optional<DialogButton> button, @NonNull ParsedInputs inputs) {
|
||||
lastInputs = inputs;
|
||||
|
||||
boolean stillValid = runAction(button, lastInputs);
|
||||
switch (dialog.afterAction()) {
|
||||
case NONE -> {
|
||||
// If no new dialog was opened, reopen this one
|
||||
if (stillValid) {
|
||||
dialog.restoreForm(manager.session(), lastInputs, this);
|
||||
}
|
||||
}
|
||||
case CLOSE -> {
|
||||
// If no new dialog was opened, tell the manager this one is now closed
|
||||
if (stillValid) {
|
||||
manager.close();
|
||||
}
|
||||
}
|
||||
case WAIT_FOR_RESPONSE -> {} // TODO
|
||||
}
|
||||
}
|
||||
|
||||
// Called when clicking the X in the corner on a form, which we interpret as clicking escape
|
||||
// Note that this method is called from the "closedOrInvalidResultHandler",
|
||||
// meaning it can also be called when e.g. the bedrock client opens another form or is unable to open the form sent to it
|
||||
public void closeDialog(Optional<DialogButton> onCancel) {
|
||||
if (dialog.canCloseWithEscape()) {
|
||||
if (runAction(onCancel, lastInputs == null ? ParsedInputs.EMPTY : lastInputs)) {
|
||||
manager.close();
|
||||
}
|
||||
} else if (manager.open() == this) { // Check if this is still the currently open dialog
|
||||
// If player should not have been able to close the dialog, reopen it with the last inputs
|
||||
|
||||
// lastInputs might be null here since it's possible none were sent yet, and bedrock doesn't send them when just closing the form
|
||||
if (lastInputs == null) {
|
||||
dialog.sendForm(manager.session(), this);
|
||||
} else {
|
||||
dialog.restoreForm(manager.session(), lastInputs, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if this dialog is still regarded open by the DialogManager
|
||||
// When returning false, that means a new dialog has been opened, possibly by the action, which takes this dialog's place
|
||||
private boolean runAction(Optional<DialogButton> button, ParsedInputs inputs) {
|
||||
// Don't run any action if a new dialog has already been opened
|
||||
if (manager.open() != this) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DialogAction action = button.flatMap(DialogButton::action).orElse(null);
|
||||
if (action != null) {
|
||||
action.run(manager.session(), inputs);
|
||||
if (action instanceof DialogAction.ShowDialog) {
|
||||
return false;
|
||||
}
|
||||
// TODO command warning screen
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.session.dialog;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
|
||||
|
||||
/**
|
||||
* Small class to manage the currently open dialog.
|
||||
*/
|
||||
@Accessors(fluent = true)
|
||||
public class DialogManager {
|
||||
@Getter
|
||||
private final GeyserSession session;
|
||||
@Getter
|
||||
private DialogHolder open;
|
||||
|
||||
public DialogManager(GeyserSession session) {
|
||||
this.session = session;
|
||||
}
|
||||
|
||||
public void openDialog(Holder<NbtMap> dialog) {
|
||||
openDialog(Dialog.getDialogFromHolder(session, dialog));
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a new dialog. If a dialog was already open, this one will be closed. Its closing action will not be executed. This matches Java behaviour.
|
||||
*/
|
||||
public void openDialog(Dialog dialog) {
|
||||
open = new DialogHolder(this, dialog);
|
||||
session.closeForm();
|
||||
dialog.sendForm(session, open);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the currently open dialog, if any. The dialog's closing action will not be executed.
|
||||
*/
|
||||
public void close() {
|
||||
if (open != null) {
|
||||
open = null;
|
||||
// The form could already have been closed by now, but in the case it wasn't, close it anyway
|
||||
// This won't run a closing dialog action, because the manager already regards the dialog as closed
|
||||
session.closeForm();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,35 +39,55 @@ import java.util.Optional;
|
||||
public abstract class DialogWithButtons extends Dialog {
|
||||
|
||||
protected final List<DialogButton> buttons;
|
||||
protected final Optional<DialogButton> exitAction;
|
||||
|
||||
protected DialogWithButtons(GeyserSession session, NbtMap map, List<DialogButton> buttons) {
|
||||
protected DialogWithButtons(GeyserSession session, NbtMap map, List<DialogButton> buttons, Optional<DialogButton> exitAction) {
|
||||
super(session, map);
|
||||
this.buttons = buttons;
|
||||
this.exitAction = exitAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder) {
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder, DialogHolder holder) {
|
||||
DropdownComponent.Builder dropdown = DropdownComponent.builder();
|
||||
dropdown.text("Please select an option:");
|
||||
for (DialogButton button : buttons) {
|
||||
dropdown.option(button.label());
|
||||
}
|
||||
exitAction.ifPresent(button -> dropdown.option(button.label()));
|
||||
builder.dropdown(dropdown);
|
||||
|
||||
builder.validResultHandler(response -> {
|
||||
ParsedInputs inputs = parseInput(response);
|
||||
int selection = response.asDropdown();
|
||||
runButton(session, Optional.of(buttons.get(selection)), inputs);
|
||||
if (selection == buttons.size()) {
|
||||
holder.runButton(exitAction, inputs);
|
||||
} else {
|
||||
holder.runButton(Optional.of(buttons.get(selection)), inputs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder) {
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder, DialogHolder holder) {
|
||||
for (DialogButton button : buttons) {
|
||||
builder.button(button.label());
|
||||
}
|
||||
exitAction.ifPresent(button -> builder.button(button.label()));
|
||||
|
||||
builder.validResultHandler(response -> runButton(session, Optional.of(buttons.get(response.clickedButtonId())), ParsedInputs.EMPTY));
|
||||
builder.validResultHandler(response -> {
|
||||
if (response.clickedButtonId() == buttons.size()) {
|
||||
holder.runButton(exitAction, ParsedInputs.EMPTY);
|
||||
} else {
|
||||
|
||||
holder.runButton(Optional.of(buttons.get(response.clickedButtonId())), ParsedInputs.EMPTY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<DialogButton> onCancel() {
|
||||
return exitAction;
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
|
||||
@@ -31,21 +31,11 @@ import org.cloudburstmc.nbt.NbtType;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.MinecraftKey;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class MultiActionDialog extends DialogWithButtons {
|
||||
|
||||
public static final Key TYPE = MinecraftKey.key("multi_action");
|
||||
|
||||
private final Optional<DialogButton> exit;
|
||||
|
||||
protected MultiActionDialog(GeyserSession session, NbtMap map, IdGetter idGetter) {
|
||||
super(session, map, DialogButton.readList(session, map.getList("actions", NbtType.COMPOUND), idGetter));
|
||||
exit = DialogButton.read(session, map.get("exit_action"), idGetter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<DialogButton> onCancel() {
|
||||
return exit;
|
||||
super(session, map, DialogButton.readList(session, map.getList("actions", NbtType.COMPOUND), idGetter), DialogButton.read(session, map.get("exit_action"), idGetter));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,12 +52,12 @@ public class NoticeDialog extends Dialog {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder) {
|
||||
builder.validResultHandler(response -> runButton(session, button, parseInput(response)));
|
||||
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder, DialogHolder holder) {
|
||||
builder.validResultHandler(response -> holder.runButton(onCancel(), parseInput(response)));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder) {
|
||||
builder.validResultHandler(response -> runButton(session, button, ParsedInputs.EMPTY));
|
||||
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder, DialogHolder holder) {
|
||||
builder.validResultHandler(response -> holder.runButton(onCancel(), ParsedInputs.EMPTY));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,6 @@ import java.util.Optional;
|
||||
public class ServerLinksDialog extends DialogWithButtons {
|
||||
|
||||
protected ServerLinksDialog(GeyserSession session, NbtMap map, List<DialogButton> buttons) {
|
||||
super(session, map, buttons);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<DialogButton> onCancel() {
|
||||
return Optional.empty();
|
||||
super(session, map, buttons, Optional.empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ package org.geysermc.geyser.session.dialog.action;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.geysermc.cumulus.form.SimpleForm;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.dialog.Dialog;
|
||||
import org.geysermc.geyser.session.dialog.input.ParsedInputs;
|
||||
@@ -76,7 +75,8 @@ public interface DialogAction {
|
||||
|
||||
@Override
|
||||
public void run(GeyserSession session, ParsedInputs inputs) {
|
||||
session.sendForm(SimpleForm.builder().title("Open URL").content(url));
|
||||
//session.sendForm(SimpleForm.builder().title("Open URL").content(url));
|
||||
// TODO if we use form here we need a connection in dialog stack
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +105,7 @@ public interface DialogAction {
|
||||
|
||||
@Override
|
||||
public void run(GeyserSession session, ParsedInputs inputs) {
|
||||
// TODO figure out parent dialog
|
||||
Dialog.showDialog(session, dialog);
|
||||
session.getDialogManager().openDialog(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,10 @@ public abstract class DialogInput<T> {
|
||||
this.label = MessageTranslator.convertFromNullableNbtTag(session, map.get("label"));
|
||||
}
|
||||
|
||||
public void addComponent(CustomForm.Builder builder) {
|
||||
addComponent(builder, Optional.empty());
|
||||
}
|
||||
|
||||
public abstract void addComponent(CustomForm.Builder builder, Optional<T> restored);
|
||||
|
||||
public abstract T read(CustomFormResponse response);
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
package org.geysermc.geyser.translator.protocol.java.dialogues;
|
||||
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.dialog.Dialog;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundShowDialogGamePacket;
|
||||
@@ -36,6 +35,6 @@ public class JavaShowDialogGameTranslator extends PacketTranslator<ClientboundSh
|
||||
|
||||
@Override
|
||||
public void translate(GeyserSession session, ClientboundShowDialogGamePacket packet) {
|
||||
Dialog.showDialog(session, packet.getDialog());
|
||||
session.getDialogManager().openDialog(packet.getDialog());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user