1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-24 01:09:30 +00:00

Implement "waiting for response" screen

This commit is contained in:
Eclipse
2025-06-04 17:41:14 +00:00
parent 2bb9cf664d
commit b708c17600
5 changed files with 70 additions and 10 deletions

View File

@@ -1240,6 +1240,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
// but this will work once we implement matching Java custom tick cycles
sendDownstreamGamePacket(ServerboundClientTickEndPacket.INSTANCE);
}
dialogManager.tick();
} catch (Throwable throwable) {
throwable.printStackTrace();
}

View File

@@ -42,6 +42,7 @@ import org.geysermc.geyser.session.cache.registry.JavaRegistries;
import org.geysermc.geyser.session.cache.registry.RegistryEntryContext;
import org.geysermc.geyser.session.dialog.input.DialogInput;
import org.geysermc.geyser.session.dialog.input.ParsedInputs;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.MinecraftKey;
import org.geysermc.mcprotocollib.protocol.data.game.Holder;
@@ -111,6 +112,7 @@ public abstract class Dialog {
protected FormBuilder<? extends FormBuilder<?,?,?>, ? extends Form, ? extends FormResponse> createForm(GeyserSession session, Optional<ParsedInputs> restored, DialogHolder holder) {
if (inputs.isEmpty()) {
SimpleForm.Builder builder = SimpleForm.builder()
.translator(MinecraftLocale::getLocaleString, session.locale())
.title(title);
builder.content(String.join("\n\n", labels));
@@ -119,6 +121,7 @@ public abstract class Dialog {
return builder;
} else {
CustomForm.Builder builder = CustomForm.builder()
.translator(MinecraftLocale::getLocaleString, session.locale())
.title(title);
restored.ifPresentOrElse(last -> last.restore(builder), () -> inputs.forEach(input -> input.addComponent(builder)));

View File

@@ -26,14 +26,18 @@
package org.geysermc.geyser.session.dialog;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.cumulus.form.SimpleForm;
import org.geysermc.geyser.session.dialog.action.DialogAction;
import org.geysermc.geyser.session.dialog.input.ParsedInputs;
import org.geysermc.geyser.text.MinecraftLocale;
import java.util.Optional;
public class DialogHolder {
private final DialogManager manager;
private final Dialog dialog;
private long responseWaitTime = 0;
private boolean sendBackButton = false;
private ParsedInputs lastInputs;
public DialogHolder(DialogManager manager, Dialog dialog) {
@@ -67,7 +71,23 @@ public class DialogHolder {
manager.close();
}
}
case WAIT_FOR_RESPONSE -> {} // TODO
case WAIT_FOR_RESPONSE -> {
// If no new dialog was opened, open a form telling the user we're waiting on a response from the server
// This dialog is replaced with a similar form with a "back" button after 5 seconds, matching Java behaviour
if (stillValid) {
responseWaitTime = System.currentTimeMillis();
sendBackButton = false;
waitForResponse();
}
}
}
}
public void tick() {
// Replace wait form with one with a back button if no replacement dialog was given
if (responseWaitTime > 0 && !sendBackButton && System.currentTimeMillis() - responseWaitTime > 5000) {
sendBackButton = true;
manager.session().closeForm(); // Automatically reopens with a back button
}
}
@@ -81,14 +101,42 @@ public class DialogHolder {
}
} 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
reopenDialog();
}
}
// lastInputs might be null here since it's possible none were sent yet, and bedrock doesn't send them when just closing the form
private void reopenDialog() {
responseWaitTime = 0;
// lastInputs might be null here since it's possible none were sent yet
// 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);
}
}
private void waitForResponse() {
String content = "Geyser is waiting for the server to respond with a new dialog.";
if (sendBackButton) {
content += " The server is taking a while to respond. You can press the button below to go back to the game.";
} else {
content += " If no new dialog is shown within 5 seconds, a button will appear to go back to the game.";
}
manager.session().sendDialogForm(SimpleForm.builder()
.translator(MinecraftLocale::getLocaleString, manager.session().locale())
.title("gui.waitingForResponse.title")
.content(content)
.optionalButton("Back", sendBackButton)
.closedOrInvalidResultHandler(() -> {
if (manager.open() == this) { // If still waiting on a new dialog
waitForResponse();
}
})
.validResultHandler(response -> manager.close()) // Back button was pressed, meaning no new dialog was sent
.build());
}
// Returns true if this dialog is still regarded open by the DialogManager

View File

@@ -58,6 +58,12 @@ public class DialogManager {
dialog.sendForm(session, open);
}
public void tick() {
if (open != null) {
open.tick();
}
}
/**
* Closes the currently open dialog, if any. The dialog's closing action will not be executed.
*/

View File

@@ -53,11 +53,12 @@ public class NoticeDialog extends Dialog {
@Override
protected void addCustomComponents(GeyserSession session, CustomForm.Builder builder, DialogHolder holder) {
builder.validResultHandler(response -> holder.runButton(onCancel(), parseInput(response)));
builder.validResultHandler(response -> holder.runButton(button, parseInput(response)));
}
@Override
protected void addCustomComponents(GeyserSession session, SimpleForm.Builder builder, DialogHolder holder) {
builder.validResultHandler(response -> holder.runButton(onCancel(), ParsedInputs.EMPTY));
builder.button(button.map(DialogButton::label).orElse("gui.ok"))
.validResultHandler(response -> holder.runButton(button, ParsedInputs.EMPTY));
}
}