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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user