fix(settings): use static dialog command actions
Release / release (push) Successful in 2m55s
CI / build (push) Successful in 1m16s

This commit is contained in:
dmg
2026-08-25 19:06:05 -04:00
parent 8b3eaad253
commit bc2f9d8e25
4 changed files with 32 additions and 3 deletions
+7
View File
@@ -130,6 +130,13 @@ description: Chronological record of material decisions affecting the Spigot Bas
- Preserved unit-test coverage through server-independent dialog specifications and adapted Bukkit test fixtures to Purpur's registry-aware API behavior. - Preserved unit-test coverage through server-independent dialog specifications and adapted Bukkit test fixtures to Purpur's registry-aware API behavior.
- Verified 128 tests and the Java 25 plugin artifact with `./gradlew clean check jar`. - Verified 128 tests and the Java 25 plugin artifact with `./gradlew clean check jar`.
## 2026-08-25 — Static dialog command actions
- Replaced macro command templates with static run-command actions for fixed dialog buttons.
- Added regression coverage for the generated run-command action and its unchanged command payload.
- Verified `/basesettings` opens without command exceptions on a local Purpur 26.2 build 2618 server.
- Verified the plugin artifact with `./gradlew clean check jar`.
## 2026-08-24 — Pocket Base mob portal travel ## 2026-08-24 — Pocket Base mob portal travel
- Added five-tick collision scanning that transports non-player living mobs through active Pocket Base entrance and return portals. - Added five-tick collision scanning that transports non-player living mobs through active Pocket Base entrance and return portals.
@@ -2,7 +2,7 @@
type: User Story type: User Story
title: "US-020: Control a base through a dialog UI" title: "US-020: Control a base through a dialog UI"
description: Let players inspect and control their base through Minecraft's native dialog interface. description: Let players inspect and control their base through Minecraft's native dialog interface.
status: in-progress status: done
--- ---
# US-020: Control a base through a dialog UI # US-020: Control a base through a dialog UI
@@ -21,7 +21,9 @@ As a **player**, I want a dialog-based base dashboard so that I can inspect prog
- [x] `ui` is offered through command autocomplete. - [x] `ui` is offered through command autocomplete.
- [x] Non-player execution remains safely rejected. - [x] Non-player execution remains safely rejected.
- [x] Automated tests verify dialog routing and generated controls. - [x] Automated tests verify dialog routing and generated controls.
- [ ] The dialog uses Purpur's supported Paper dialog API and opens on the production Purpur 26.2 runtime without missing-class or command exceptions. - [x] Fixed dialog commands use Purpur static run-command actions rather than macro templates.
- [x] A rendering regression test verifies fixed command buttons do not throw `No variables in macro`.
- [x] The dialog uses Purpur's supported Paper dialog API and opens on the production Purpur 26.2 runtime without missing-class or command exceptions.
## Related ## Related
@@ -12,6 +12,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
final class BaseSettingsDialogFactory { final class BaseSettingsDialogFactory {
private static final int DIALOG_WIDTH = 420; private static final int DIALOG_WIDTH = 420;
@@ -366,13 +367,17 @@ final class BaseSettingsDialogFactory {
private static ActionButton render(ButtonSpec button) { private static ActionButton render(ButtonSpec button) {
ActionButton.Builder builder = ActionButton.builder(Component.text(button.label())) ActionButton.Builder builder = ActionButton.builder(Component.text(button.label()))
.width(button.width()) .width(button.width())
.action(DialogAction.commandTemplate(button.command())); .action(DialogAction.staticAction(commandClick(button.command())));
if (!button.tooltip().isEmpty()) { if (!button.tooltip().isEmpty()) {
builder.tooltip(Component.text(button.tooltip())); builder.tooltip(Component.text(button.tooltip()));
} }
return builder.build(); return builder.build();
} }
static ClickEvent<ClickEvent.Payload.Text> commandClick(String command) {
return ClickEvent.runCommand(command);
}
sealed interface DialogSpec permits ListSpec, MultiSpec, ConfirmationSpec, NoticeSpec { sealed interface DialogSpec permits ListSpec, MultiSpec, ConfirmationSpec, NoticeSpec {
DialogContent content(); DialogContent content();
} }
@@ -10,9 +10,24 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import net.kyori.adventure.text.event.ClickEvent;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
final class BaseSettingsDialogFactoryTest { final class BaseSettingsDialogFactoryTest {
@Test
void createsStaticRunCommandActionWithoutMacroVariables() {
ClickEvent<ClickEvent.Payload.Text> action = BaseSettingsDialogFactory.commandClick(
"/basesettings status"
);
assertEquals(ClickEvent.Action.RUN_COMMAND, action.action());
ClickEvent.Payload.Text payload = assertInstanceOf(
ClickEvent.Payload.Text.class,
action.payload()
);
assertEquals("/basesettings status", payload.value());
}
@Test @Test
void createsControlsForEveryBaseSettingAndConfirmedPurchase() { void createsControlsForEveryBaseSettingAndConfirmedPurchase() {
UUID playerId = UUID.randomUUID(); UUID playerId = UUID.randomUUID();