Class DialogHolder

java.lang.Object
org.geysermc.geyser.session.dialog.DialogHolder

public class DialogHolder extends Object
Used to manage an open dialog. Handles dialog input, transferring to other dialogs, and dialog "submenus" for e.g. waiting on a new dialog or confirming a command.

This is passed to a Dialog when using it to send a form to the client, it uses the runButton(Optional, ParsedInputs) and closeDialog(Optional) methods.

To make it easier to understand what this class does and why it does it, here is the summed up behaviour of dialogs on Java. Java dialogs consist of inputs and buttons that run actions. Dialogs also have an "on cancel"/closing action, which is usually executed when the user presses ESC, or presses an "exit" button, defined by the dialog (note: not all dialog types can have an exit button). Dialogs can disallow closing by pressing ESC. Geyser translates clicking the "X" in the corner of a form as pressing ESC.

Dialog inputs are quite simple. The user can enter what they want, and the inputs will clear once the dialog has been closed (note: only once the dialog has been closed. This becomes important later!).

Dialog actions are more complicated. Dialogs can define what to do after an action has been executed (so-called "after action" behaviour). When executing 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" set as after action: the dialog is kept open, its current input kept. This means the dialog can only be closed by pressing ESC (when allowed), or by an exit button, if it exists.
  • Executes with "CLOSE" as after action: the dialog is closed, its closing action not executed.
  • Executes with "WAIT_FOR_RESPONSE" as after action: the dialog is closed, its closing action not executed. A new, temporary screen is opened telling the user Minecraft is waiting on a response from the server.
    The server must then send a new dialog within 5 seconds. After this period, a "back" button will appear, allowing the user to go back into the game if no new dialog appears.

If a new dialog is opened whilst another dialog is open, the old dialog is closed and the new dialog takes its place. The closing action of the dialog is not executed.

All of this behaviour must be emulated by Geyser. That said, here are some of the things that this class must handle:

  • Executing actions with after actions properly. Actions that run commands or the "WAIT_FOR_RESPONSE" after action make this especially complicated.
    In the case of commands that require operator permissions or the previously mentioned after action, Geyser must open a temporary form asking the user for confirmation or telling the user to wait.
  • Remember form input and restore it after returning to this dialog, e.g. by cancelling a command execution or by the "NONE" after action.
  • Properly close this dialog and open other dialogs - for example, bedrock/Cumulus likes to call "close" handlers a lot, including when the client closes a currently open form to open a new one. As such, every time we do something, we must make sure this dialog is still considered open.

Final note: when reading through this code, a dialog is "valid" when it is still considered open.

  • Constructor Details

  • Method Details

    • runButton

      public void runButton(Optional<DialogButton> button, @NonNull ParsedInputs inputs)
      Checks if this dialog is still valid, and if so, runs the given button (if present) with the given inputs. These inputs can be ParsedInputs.EMPTY when the dialog has no inputs, but can never be null. This method also runs the dialog's after action.
    • tick

      public void tick()
      Ticks this dialog. Ticks are only used to check when to show the "back" button on the "waiting for response" screen.
    • closeDialog

      public void closeDialog(Optional<DialogButton> onCancel)
      Should be called when pressing "ESC", i.e., clicking the X in the corner of the form. This method checks if the dialog is still valid, and if so, closes it if the dialog allows closing by pressing ESC. If not, the dialog is reopened.

      If the dialog was closed successfully, the given close action is also executed, if present.

    • session

      public GeyserSession session()