Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/bedrock-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ No complete area has verified Bedrock parity.

Retain these reports until a matching reproduction establishes the result:

- Lifeboat dialog text was reported as untranslated. A generic [action-form dialog label defect](../patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md) is fixed. The original report still needs a matching form capture.
- Lifeboat dialog text was reported as untranslated. Captured Navigator titles, captions, and response indices survive both [Java dialog projection](../patches/viabedrock/upstreamable/0095-share-native-ui-programs-and-resources.pr.md) and [add-on render failures](../patches/viafabricplus-bedrock/upstreamable/0029-render-authored-forms-and-npc-dialogs.pr.md). These controls preserve the official 1.26.60.5 scene bytes. The original reported dialog remains unmatched.
- Lifeboat's opaque player-head obstruction matches a missing native near-camera fade. World player materials now use the [native ordered fade](../patches/viafabricplus-bedrock/upstreamable/0002-native-entities-and-skins.pr.md). GPU checks cover color and depth through native and Iris programs. A matching offline scene reveals the lobby through nearby players. Broader spawn and rendering parity remain open.
- WildFFA inventory opened with E shows items without the expected background.
- An update from 0.3.61 to 0.4.2 caused reported inventory lag spikes and overlapping menus.
- The oversized shield and distorted custom-skin pose in the confirmed 0.4.3 screenshots remain unresolved.
Expand Down
6 changes: 6 additions & 0 deletions docs/server-replay.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,12 @@ Private `camera-audit.jsonl` observations include frame time, world clocks, play

Private `held-item-light-audit.jsonl` observations record actual first-person submissions. They include packed light, quad normals, tint layers, material emission, and the selected pipeline. Observations do not change the item or camera. Compare them with the screenshot timestamp; startup light values can change while chunks load.

Private `native-form-audit.json` observations distinguish authored forms, shared scenes, add-on fallback forms, and standard Java dialogs.
For authored forms, the observer reads identity from the form controller and geometry from the shared screen.
The `presentation` field identifies the path. `nativeForm` is true only for an authored form.
Shared scenes can belong to another domain. A Java dialog classification does not prove that Bedrock supplied it.
The bounded geometry report excludes authored labels, URLs, and input text.

Private `movement-audit.jsonl` observations record position, velocity, item use, held item, and selected hotbar slot at each observed movement phase.
The `epochMillis` timestamp aligns those observations with external input markers.
Use the item and slot fields to distinguish a changed selection from a missing movement impulse.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 4848b046be5a57d29dd4cdeace1a429f07317806 Mon Sep 17 00:00:00 2001
From 0e0579dd8583d16bf07eeef88308e461676b1aa3 Mon Sep 17 00:00:00 2001
From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com>
Date: Sun, 18 Oct 2026 16:55:37 +0200
Subject: [PATCH] feat(ui): share bounded native UI programs and resource
Expand Down Expand Up @@ -481,6 +481,24 @@ program and the host policy. Synthetic fixtures now declare real screen
content controls rather than relying on the old content-only resolver.
A contract boundary control rejects unknown policy versions and prevents
legacy programs from claiming the new host behavior.

Keep narration metadata out of visible Java dialog captions. The official
Bedrock 1.26.60.5 Lifeboat Navigator renders an image-only Close action.
Its authored scene uses accessibility.button.tts.title for narration,
while the form supplies Close at response index 8. Projecting tts_name
as visible text leaks that key into the Java fallback dialog.

Use visible authored labels when available. For image-only actions,
retain the translated source form caption at the original response index.
Hidden actions remain omitted. A focused presentation regression covers
image-only actions, resolved labels, and sparse response identities.

Bound the public form projection before traversing captions. Client
render-failure fallbacks also consume this API and can receive a scene
that their renderer rejects. Preserve the shared 64-level and 8192-node
scene limits so the client can retain the intact original form when
projection metadata is invalid. A regression rejects an overdeep tree
before caption traversal or fallback-field access.
---
build.gradle | 11 +
.../api/model/NativeContainerAction.java | 93 +
Expand Down Expand Up @@ -521,7 +539,7 @@ legacy programs from claiming the new host behavior.
.../resourcepack/ui/NpcEditorBindings.java | 329 ++++
.../api/resourcepack/ui/NpcEditorState.java | 322 +++
.../api/resourcepack/ui/RecipeCollection.java | 266 +++
.../api/resourcepack/ui/ServerFormUi.java | 253 +++
.../api/resourcepack/ui/ServerFormUi.java | 271 +++
.../resourcepack/ui/UiAsepriteMetadata.java | 95 +
.../api/resourcepack/ui/UiBindings.java | 79 +
.../api/resourcepack/ui/UiBitmapFonts.java | 282 +++
Expand Down Expand Up @@ -569,7 +587,7 @@ legacy programs from claiming the new host behavior.
.../resourcepack/ui/RecipeCollectionTest.java | 227 +++
.../ui/ServerCustomFormUiTest.java | 146 ++
.../ui/ServerFormUiSliderStateTest.java | 126 ++
.../api/resourcepack/ui/ServerFormUiTest.java | 427 ++++
.../api/resourcepack/ui/ServerFormUiTest.java | 486 +++++
.../ui/UiAsepriteMetadataTest.java | 112 ++
.../resourcepack/ui/UiBitmapFontsTest.java | 285 +++
.../ui/UiCollectionWindowTest.java | 131 ++
Expand All @@ -578,7 +596,7 @@ legacy programs from claiming the new host behavior.
.../api/resourcepack/ui/UiTexturesTest.java | 231 +++
.../ui/native-inventory-item-filter.json | 311 +++
.../generator/SearchUnicodeDataGenerator.java | 126 ++
96 files changed, 14747 insertions(+), 60 deletions(-)
96 files changed, 14824 insertions(+), 60 deletions(-)
create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeContainerAction.java
create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeContainerData.java
create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeContainerMessage.java
Expand Down Expand Up @@ -671,10 +689,10 @@ legacy programs from claiming the new host behavior.
create mode 100644 src/tool/java/net/raphimc/viabedrock/tool/generator/SearchUnicodeDataGenerator.java

diff --git a/build.gradle b/build.gradle
index 2fd72ae4..8e9eab8b 100644
index 8e003758..7d4816d6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -238,3 +238,14 @@ class MockitoAgentArgumentProvider implements org.gradle.process.CommandLineArgu
@@ -239,3 +239,14 @@ class MockitoAgentArgumentProvider implements org.gradle.process.CommandLineArgu
return ["-javaagent:${this.classpath.singleFile}"]
}
}
Expand Down Expand Up @@ -7356,10 +7374,10 @@ index 00000000..cb7249f2
+}
diff --git a/src/main/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUi.java b/src/main/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUi.java
new file mode 100644
index 00000000..d2ec9215
index 00000000..53aa191f
--- /dev/null
+++ b/src/main/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUi.java
@@ -0,0 +1,253 @@
@@ -0,0 +1,271 @@
+/*
+ * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
+ * Copyright (C) 2026 RK_01/RaphiMC and contributors
Expand Down Expand Up @@ -7485,7 +7503,9 @@ index 00000000..d2ec9215
+ for (final JsonElement entry : form.getAsJsonArray(collection)) {
+ final JsonObject element = entry.getAsJsonObject();
+ if ("button".equals(string(element, "type"))) {
+ fallbackButtons.add(element.deepCopy());
+ final JsonObject button = element.deepCopy();
+ button.addProperty("text", this.program.translate(string(element, "text")));
+ fallbackButtons.add(button);
+ } else if (!string(element, "text").isBlank()) {
+ content.add(string(element, "text"));
+ }
Expand Down Expand Up @@ -7560,11 +7580,27 @@ index 00000000..d2ec9215
+ public static Presentation presentation(final JsonObject scene) {
+ final Map<Integer, String> labels = new LinkedHashMap<>();
+ final List<String> prose = new ArrayList<>();
+ project(scene.getAsJsonObject("root"), labels, prose);
+ final JsonObject root = scene.getAsJsonObject("root");
+ validateProjection(root, 0, new int[1]);
+ project(root, labels, prose);
+ final JsonArray buttons = scene.getAsJsonObject("fallback").getAsJsonArray("buttons");
+ labels.replaceAll((index, caption) -> caption.isBlank() && index < buttons.size()
+ ? string(buttons.get(index).getAsJsonObject(), "text") : caption);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
+ final String title = prose.isEmpty() ? string(scene.getAsJsonObject("fallback"), "title") : prose.removeFirst();
+ return new Presentation(title, String.join("\n\n", prose), Collections.unmodifiableMap(labels));
+ }
+
+ private static void validateProjection(final JsonObject node, final int depth, final int[] count) {
+ if (depth > 64 || ++count[0] > JsonUiProgram.MAX_NODES) {
+ throw new IllegalArgumentException("Form projection exceeds scene limits");
+ }
+ if (node.has("children")) {
+ for (final JsonElement child : node.getAsJsonArray("children")) {
+ validateProjection(child.getAsJsonObject(), depth + 1, count);
+ }
+ }
+ }
+
+ private static void project(final JsonObject node, final Map<Integer, String> labels, final List<String> prose) {
+ if (node.has("visible") && !UiExpression.truth(node.get("visible"))) {
+ return;
Expand All @@ -7574,7 +7610,7 @@ index 00000000..d2ec9215
+ if (index >= 0) {
+ final List<String> text = new ArrayList<>();
+ captions(node, text);
+ final String caption = text.isEmpty() ? string(node, "tts_name") : String.join("\n", text);
+ final String caption = String.join("\n", text);
+ labels.merge(index, caption, (earlier, later) -> earlier.isBlank() ? later : earlier);
+ }
+ return;
Expand Down Expand Up @@ -14986,10 +15022,10 @@ index 00000000..362380ae
+}
diff --git a/src/test/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUiTest.java b/src/test/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUiTest.java
new file mode 100644
index 00000000..056d3123
index 00000000..63bf4b98
--- /dev/null
+++ b/src/test/java/net/raphimc/viabedrock/api/resourcepack/ui/ServerFormUiTest.java
@@ -0,0 +1,427 @@
@@ -0,0 +1,486 @@
+/*
+ * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock
+ * Copyright (C) 2026 RK_01/RaphiMC and contributors
Expand Down Expand Up @@ -15156,6 +15192,65 @@ index 00000000..056d3123
+ }
+
+ @Test
+ void rejectsOverdeepSceneMetadataBeforeProjectingDialogControls() {
+ final JsonObject scene = new JsonObject();
+ final JsonObject fallback = new JsonObject();
+ fallback.addProperty("title", "Ordinary form");
+ fallback.add("buttons", new JsonArray());
+ scene.add("fallback", fallback);
+ JsonObject root = new JsonObject();
+ scene.add("root", root);
+ for (int depth = 0; depth < 64; depth++) {
+ final JsonObject child = new JsonObject();
+ final JsonArray children = new JsonArray();
+ children.add(child);
+ root.add("children", children);
+ root = child;
+ }
+ assertEquals("Ordinary form", ServerFormUi.presentation(scene).title());
+ final JsonArray beyondLimit = new JsonArray();
+ beyondLimit.add(new JsonObject());
+ root.add("children", beyondLimit);
+ assertThrows(IllegalArgumentException.class, () -> ServerFormUi.presentation(scene));
+ }
+
+ @Test
+ void imageOnlyDialogActionsUseTheOriginalCaptionInsteadOfNarrationKeys() {
+ final var scene = JsonParser.parseString("""
+ {"root":{"type":"panel","children":[
+ {"type":"label","text":"Navigator"},
+ {"type":"button","action":2,"tts_name":"accessibility.button.tts.title",
+ "children":[{"type":"image","texture":"textures/ui/close"}]},
+ {"type":"button","action":0,"tts_name":"narration.choice",
+ "children":[{"type":"label","text":"Resolved choice"}]},
+ {"type":"button","action":1,"visible":false,"tts_name":"hidden.choice"}]},
+ "fallback":{"title":"selector_Navigator","buttons":[
+ {"text":"Source choice"},{"text":"Hidden choice"},{"text":"Close"}]}}
+ """).getAsJsonObject();
+ final var presentation = ServerFormUi.presentation(scene);
+ assertEquals("Navigator", presentation.title());
+ assertEquals(Map.of(0, "Resolved choice", 2, "Close"), presentation.buttons());
+ }
+
+ @Test
+ void imageOnlyCaptionsTranslateWithoutChangingRawBindingValues() {
+ final String images = """
+ {"namespace":"server_form",
+ "third_party_server_screen":{"$screen_content":"server_form.main_screen_content"},
+ "main_screen_content":{"type":"grid","collection_name":"form_buttons","grid_item_template":"server_form.row"},
+ "row":{"type":"button","$pressed_button_name":"button.form_button_click",
+ "bindings":[{"binding_name":"(#form_button_text = '%probe.choice')","binding_name_override":"#visible"}],
+ "controls":[{"icon":{"type":"image","texture":"textures/ui/close"}}]}}
+ """;
+ final JsonObject form = form("unused", "%probe.choice");
+ final var ui = new ServerFormUi(List.of(definitions(images)), text -> "%probe.choice".equals(text) ? "Translated choice" : text);
+ final JsonObject scene = ui.resolve(form);
+ assertNotNull(scene);
+ assertEquals(Map.of(1, "Translated choice"), ServerFormUi.presentation(scene).buttons());
+ assertEquals("%probe.choice", form.getAsJsonArray("elements").get(1).getAsJsonObject().get("text").getAsString());
+ }
+
+ @Test
+ void javaPresentationUsesResolvedCaptionsAndRetainsSparseResponseIndices() {
+ final var scene = new ServerFormUi(List.of(definitions(UI))).resolve(form("tile:One", "unused", "tile:Three"));
+ final var presentation = ServerFormUi.presentation(scene);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,12 @@ Program export preserves the selected format and pack-layer precedence. PNG pref
Regressions cover byte preservation, both override directions, program round trips, metadata, and resource export.
The rebuilt add-on accepts MegaSMP's converted pack under Java's existing download cap and reaches a visible lobby.
A fresh walking control remains grounded. The attempted hotbar menu input opens no screen; complete gameplay remains unverified.

Java dialog projection uses visible authored labels and the original translated caption for image-only actions.
The captured 1.26.60.5 Navigator Close action previously exposed a narration key.
The corrected projection retains Close at response index 8 and preserves the other eight captions and indices.
Regressions cover image-only captions, authored labels, hidden actions, and translated source captions without changing raw binding values.
A client-facing projection regression accepts the scene depth boundary and rejects an overdeep tree before caption traversal.
A rebuilt Java dialog shows the captured Navigator labels and sends response 8 when the source Close action is clicked.
The local diagnostic control disables authored-form capability without changing the recorded scene packets.
The original reported dialog remains unmatched.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
From 24a18417c6941d1921b5eb6c6a67bc7d9d182c89 Mon Sep 17 00:00:00 2001
From 671d083f0b1f9fbe359a81b06cc5ff13475cb665 Mon Sep 17 00:00:00 2001
From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com>
Date: Sun, 1 Nov 2026 14:06:07 +0100
Subject: [PATCH] feat(connection): allow confirmed blacklisted server joins
Expand Down Expand Up @@ -247,10 +247,10 @@ index f345d7c..40e7ae9 100644
"command_block.viafabricplus.first_tick": "Execute on first tick",
"base.viafabricplus.accept": "Accept",
diff --git a/src/main/resources/viafabricplus-bedrock.mixins.json b/src/main/resources/viafabricplus-bedrock.mixins.json
index ac083ae..8777544 100644
index 65afd38..c073c0e 100644
--- a/src/main/resources/viafabricplus-bedrock.mixins.json
+++ b/src/main/resources/viafabricplus-bedrock.mixins.json
@@ -48,6 +48,8 @@
@@ -49,6 +49,8 @@
"core.access.MixinEventLoopGroupHolder",
"core.access.MixinServerAddress",
"core.connection.MixinConnectScreen_1",
Expand Down
Loading
Loading