From 97fbfdf8aabdd1075badf23e80bde8e85590a985 Mon Sep 17 00:00:00 2001 From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Wed, 4 Nov 2026 23:14:49 +0100 Subject: [PATCH 1/3] chore: continue compatibility maintenance From 89d417c82f96dcd3beb3c388c522743623118248 Mon Sep 17 00:00:00 2001 From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Wed, 4 Nov 2026 23:29:46 +0100 Subject: [PATCH 2/3] fix(inventory): preserve native storage identity defaults Native storage defaults a present non-integer bundle_id to container zero. Share that decoder across storage weight, physical tooltip snapshots, and transfer planning so they resolve the same container. Keep absent identities unavailable and preserve strict transported snapshot validation. Verify the change against original 1.26.60.5 NBT getter controls, focused regressions, the full core test suite, Checkstyle, and the full patch replay. --- ...rate-authored-native-ui-presentation.patch | 128 +++++++++++++----- ...rate-authored-native-ui-presentation.pr.md | 5 + 2 files changed, 100 insertions(+), 33 deletions(-) diff --git a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch index a8c0a8d4..3fe42792 100644 --- a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch +++ b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch @@ -1,4 +1,4 @@ -From e03b81e1cceb1c0949ec1367d6d3e8b0f32bb9a0 Mon Sep 17 00:00:00 2001 +From 9323b830ebe9e230566dff571938ce3a859e0191 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): resolve authored Bedrock server UI scenes @@ -745,17 +745,31 @@ merges, holes, partial destinations, nested weight, filters and rejections. Original ContainerModel setter143a7b610 confirms incoming identity copying and the identity-only notification fast path. Request-scope ID assignment, trusted controller sessions and installed input remain separate work. + +Decode native storage identity with separate NBT presence and typed-int reads. +A present non-integer bundle_id resolves container zero; a missing identity +does not select a container. Share that rule across storage weight, physical +tooltip snapshots, and transfer planning. Keep transported snapshot validation +strict and keep unavailable dynamic contents unknown. + +Original Bedrock 1.26.60.5/protocol 2225 storage admission and child lookup +execute 42 controls through the real CompoundTag presence1429659f0 and +typed-int142965cf0 getters. Resolver142f32c90 and child lookup144fe4a60 retain +signed Int3 payloads and use zero for a present String8 discriminator. The PE +SHA-256 is 988f6a61403b4381aa41e6c66d64cce441b14e561a9b10f647c2758ef3f2672a. +These controls use explicit native tag-map and component fixtures; they do not +establish full protocol NBT construction or installed controller parity. --- Data Asset Sources.md | 33 + build.gradle | 1 + .../chunk/blockstate/BuiltinBlockNames.java | 46 + - .../api/model/NativeBundleTooltipData.java | 86 + + .../api/model/NativeBundleTooltipData.java | 87 + .../api/model/NativeBundleTooltipItems.java | 170 + .../viabedrock/api/model/NativeItemNames.java | 14 + .../api/model/NativeItemStacking.java | 85 + - .../api/model/NativeItemStorageData.java | 116 + + .../api/model/NativeItemStorageData.java | 123 + .../api/model/container/ChestContainer.java | 3 +- - .../container/NativeBundleTransferPlan.java | 294 + + .../container/NativeBundleTransferPlan.java | 289 + .../container/NativeContainerActionSlots.java | 75 + .../NativeContainerLegacyActions.java | 130 + .../container/NativeContainerTransfer.java | 63 + @@ -813,12 +827,12 @@ trusted controller sessions and installed input remain separate work. .../data/bedrock/item_factories.json | 10234 +++++++++++ .../data/bedrock/item_registry.json | 14496 ++++++++++++++++ .../viabedrock/data/bedrock/potion_names.json | 194 + - .../model/NativeBundleTooltipDataTest.java | 97 + + .../model/NativeBundleTooltipDataTest.java | 113 + .../model/NativeBundleTooltipItemsTest.java | 147 + .../api/model/NativeItemNamesTest.java | 83 + .../api/model/NativeItemStackingTest.java | 149 + - .../api/model/NativeItemStorageDataTest.java | 96 + - .../NativeBundleTransferPlanTest.java | 175 + + .../api/model/NativeItemStorageDataTest.java | 112 + + .../NativeBundleTransferPlanTest.java | 188 + .../NativeContainerLegacyActionsTest.java | 323 + .../NativeContainerTransferTest.java | 115 + .../container/NativeItemStackMatcherTest.java | 191 + @@ -844,7 +858,7 @@ trusted controller sessions and installed input remain separate work. .../native-bundle-tooltip-layout.json | 266 + .../inventory/native-bundle-transfers.json | 1622 ++ .../inventory/native-item-storage.json | 568 + - 98 files changed, 40157 insertions(+), 364 deletions(-) + 98 files changed, 40205 insertions(+), 364 deletions(-) create mode 100644 src/main/java/net/raphimc/viabedrock/api/chunk/blockstate/BuiltinBlockNames.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipData.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipItems.java @@ -1024,10 +1038,10 @@ index 00000000..c9581911 +} diff --git a/src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipData.java b/src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipData.java new file mode 100644 -index 00000000..eca249b8 +index 00000000..705bd265 --- /dev/null +++ b/src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipData.java -@@ -0,0 +1,86 @@ +@@ -0,0 +1,87 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -1101,15 +1115,16 @@ index 00000000..eca249b8 + + public static NativeBundleTooltipData resolve(final BedrockItem item, final ItemStorageProperties properties, + final IntFunction contents) { ++ final Integer identity = NativeItemStorageData.containerIdentity(item); + if (item.isEmpty() || !properties.storage() || properties.viewableSlots() == null || properties.viewableSlots() <= 0 -+ || item.tag() == null || !(item.tag().get("bundle_id") instanceof IntTag id)) { ++ || identity == null) { + return null; + } -+ final var items = contents.apply(id.asInt()); ++ final var items = contents.apply(identity); + if (items == null || items.length > 64) { + return null; + } -+ return new NativeBundleTooltipData(id.asInt(), properties.viewableSlots(), Arrays.stream(items) ++ return new NativeBundleTooltipData(identity, properties.viewableSlots(), Arrays.stream(items) + .map(child -> child.isEmpty() ? 0 : child.amount()).toList()); + } + @@ -1422,10 +1437,10 @@ index 00000000..9bd1f5b7 +} diff --git a/src/main/java/net/raphimc/viabedrock/api/model/NativeItemStorageData.java b/src/main/java/net/raphimc/viabedrock/api/model/NativeItemStorageData.java new file mode 100644 -index 00000000..65c4c91c +index 00000000..c95fff7a --- /dev/null +++ b/src/main/java/net/raphimc/viabedrock/api/model/NativeItemStorageData.java -@@ -0,0 +1,116 @@ +@@ -0,0 +1,123 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -1474,6 +1489,13 @@ index 00000000..65c4c91c + return resolve(item, source, work, 0, new HashSet<>()); + } + ++ /** Native presence and typed lookup are separate: a present non-integer identity reads as zero. */ ++ public static Integer containerIdentity(final BedrockItem item) { ++ final CompoundTag tag = item.tag(); ++ return tag == null || !tag.contains("bundle_id") ? null ++ : tag.get("bundle_id") instanceof IntTag id ? id.asInt() : 0; ++ } ++ + private static NativeItemStorageData resolve(final BedrockItem item, final Source source, final Work work, + final int depth, final Set path) { + if (++work.items > MAX_ITEMS || depth > MAX_DEPTH) { @@ -1488,10 +1510,10 @@ index 00000000..65c4c91c + if (tag != null && tag.get("bundle_weight") instanceof IntTag cached && cached.asInt() != 0) { + return new NativeItemStorageData(properties.modifier(), cached.asInt() - properties.modifier(), properties.capacity()); + } -+ if (tag == null || !(tag.get("bundle_id") instanceof IntTag id)) { ++ final Integer identity = containerIdentity(item); ++ if (identity == null) { + return new NativeItemStorageData(properties.modifier(), 0, properties.capacity()); + } -+ final int identity = id.asInt(); + if (!path.add(identity)) { + work.incomplete = true; + return null; @@ -1558,10 +1580,10 @@ index a37f1b07..913255f8 100644 } diff --git a/src/main/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlan.java b/src/main/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlan.java new file mode 100644 -index 00000000..a2eb508e +index 00000000..fb69ab1a --- /dev/null +++ b/src/main/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlan.java -@@ -0,0 +1,294 @@ +@@ -0,0 +1,289 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -1569,7 +1591,6 @@ index 00000000..a2eb508e + */ +package net.raphimc.viabedrock.api.model.container; + -+import com.viaversion.nbt.tag.IntTag; +import net.raphimc.viabedrock.api.model.NativeItemStorageData; +import net.raphimc.viabedrock.protocol.model.BedrockItem; +import net.raphimc.viabedrock.protocol.model.ItemStorageProperties; @@ -1588,7 +1609,7 @@ index 00000000..a2eb508e + final BedrockItem destination, final int destinationSlot, + final int selectedSlot, final Source source) { + final var state = new State(contents, destination, destinationSlot, source); -+ if (identity(bundle) == null || selectedSlot < 0 || selectedSlot >= contents.length ++ if (NativeItemStorageData.containerIdentity(bundle) == null || selectedSlot < 0 || selectedSlot >= contents.length + || state.items[selectedSlot].isEmpty()) { + return state.result(false); + } @@ -1613,7 +1634,7 @@ index 00000000..a2eb508e + final BedrockItem incoming, final int incomingSlot, + final Integer quantity, final Source source) { + final var state = new State(contents, incoming, incomingSlot, source); -+ final Integer identity = identity(bundle); ++ final Integer identity = NativeItemStorageData.containerIdentity(bundle); + if (identity == null) { + return state.result(false); + } @@ -1634,7 +1655,7 @@ index 00000000..a2eb508e + return state.result(false); + } + final var properties = source.properties(incoming); -+ final Integer incomingIdentity = identity(incoming); ++ final Integer incomingIdentity = NativeItemStorageData.containerIdentity(incoming); + final int weight; + if (properties != null && properties.complete()) { + if (incomingIdentity != null) { @@ -1682,10 +1703,6 @@ index 00000000..a2eb508e + return state.result(false); + } + -+ private static Integer identity(final BedrockItem item) { -+ return item.tag() != null && item.tag().get("bundle_id") instanceof IntTag id ? id.asInt() : null; -+ } -+ + public enum Kind { + TAKE, PLACE, SWAP + } @@ -35804,10 +35821,10 @@ index 00000000..cd681cd4 +} diff --git a/src/test/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipDataTest.java b/src/test/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipDataTest.java new file mode 100644 -index 00000000..6ee62355 +index 00000000..2d663c47 --- /dev/null +++ b/src/test/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipDataTest.java -@@ -0,0 +1,97 @@ +@@ -0,0 +1,113 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -35829,6 +35846,22 @@ index 00000000..6ee62355 +class NativeBundleTooltipDataTest { + + @Test ++ void presentNonIntegerIdentitySelectsZeroContainerWhileMissingIdentityCannotPublish() { ++ final var parent = item(1); ++ parent.setTag(new CompoundTag()); ++ parent.tag().putString("bundle_id", "7"); ++ final var properties = new ItemStorageProperties(true, 4, 64, 12); ++ final var snapshot = NativeBundleTooltipData.resolve(parent, properties, id -> { ++ assertEquals(0, id); ++ return new BedrockItem[]{BedrockItem.empty(), item(3)}; ++ }); ++ assertNotNull(snapshot); ++ assertEquals(new NativeBundleTooltipData(0, 12, List.of(0, 3)), NativeBundleTooltipData.fromTag(snapshot.toTag())); ++ parent.tag().remove("bundle_id"); ++ assertNull(NativeBundleTooltipData.resolve(parent, properties, id -> fail("Missing identity must not select a container"))); ++ } ++ ++ @Test + void serializedSparseSnapshotRetainsPhysicalSlotsAcrossLaterContainerChanges() { + final var parent = item(1); + final var tag = new CompoundTag(); @@ -36329,10 +36362,10 @@ index 00000000..75b7dbfb +} diff --git a/src/test/java/net/raphimc/viabedrock/api/model/NativeItemStorageDataTest.java b/src/test/java/net/raphimc/viabedrock/api/model/NativeItemStorageDataTest.java new file mode 100644 -index 00000000..3b25d258 +index 00000000..0332336d --- /dev/null +++ b/src/test/java/net/raphimc/viabedrock/api/model/NativeItemStorageDataTest.java -@@ -0,0 +1,96 @@ +@@ -0,0 +1,112 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -36358,6 +36391,22 @@ index 00000000..3b25d258 +class NativeItemStorageDataTest { + + @Test ++ void presentNonIntegerIdentityUsesZeroContainerWeightAndKeepsUnavailableContentsUnknown() { ++ final var source = new FixtureSource(); ++ final var parent = source.item(JsonParser.parseString(""" ++ {"amount":1,"storage":true,"modifier":4,"capacity":64,"maximum":1,"supported":true,"tag":{"bundle_id":9}} ++ """).getAsJsonObject()); ++ parent.tag().putString("bundle_id", "9"); ++ final var child = source.item(JsonParser.parseString(""" ++ {"amount":3,"storage":false,"modifier":null,"capacity":null,"maximum":64,"supported":true,"tag":null} ++ """).getAsJsonObject()); ++ source.containers.put(0, new BedrockItem[]{child}); ++ assertEquals(new NativeItemStorageData(4, 3, 64), NativeItemStorageData.resolve(parent, source)); ++ source.containers.clear(); ++ assertNull(NativeItemStorageData.resolve(parent, source)); ++ } ++ ++ @Test + void cachedAndDynamicWeightsMatchTheOriginalNativeStorageProducer() throws Exception { + try (var stream = getClass().getResourceAsStream("/inventory/native-item-storage.json")) { + assertNotNull(stream); @@ -36431,10 +36480,10 @@ index 00000000..3b25d258 +} diff --git a/src/test/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlanTest.java b/src/test/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlanTest.java new file mode 100644 -index 00000000..75410469 +index 00000000..23d4e9bb --- /dev/null +++ b/src/test/java/net/raphimc/viabedrock/api/model/container/NativeBundleTransferPlanTest.java -@@ -0,0 +1,175 @@ +@@ -0,0 +1,188 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -36460,6 +36509,19 @@ index 00000000..75410469 +class NativeBundleTransferPlanTest { + + @Test ++ void presentNonIntegerBundleIdentityCanInsertIntoItsZeroContainer() { ++ final var bundle = item(1001, 1, 99); ++ bundle.setTag(new CompoundTag()); ++ bundle.tag().putString("bundle_id", "42"); ++ final var result = NativeBundleTransferPlan.insert(bundle, new BedrockItem[]{BedrockItem.empty()}, ++ item(31, 5, 7), 3, null, new FixtureSource(new JsonObject())); ++ assertTrue(result.successful()); ++ assertEquals(5, result.contents().getFirst().amount()); ++ assertTrue(result.external().isEmpty()); ++ assertEquals(3, result.transfers().getFirst().source().index()); ++ } ++ ++ @Test + void retainsOwnedRawIdentitiesBeforeTheRequestExecutorAssignsPredictedIds() { + final var bundle = item(1001, 1, 99); + bundle.setTag(new CompoundTag()); diff --git a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md index 0febebf1..248841e6 100644 --- a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md +++ b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md @@ -24,6 +24,11 @@ The original 1.26.60.5 producer executes 159 controls; 24 representative cases s The controls supply Item queries, typed NBT lookup, container/vector backing, and descriptor storage. Component defaults, tooltip selection, source timing, and complete installed pixels remain unverified. +Storage weight, physical tooltip snapshots, and transfer planning share the native container-identity decoder. +Original storage admission and child lookup controls execute the native CompoundTag presence and typed-int getters: a present string identity selects container zero, while an absent identity selects none. +Local regressions cover zero-container weight, unknown contents, tooltip transport, and physical insertion. +Full protocol tag construction and installed controller behavior remain outside these controls. + Packet, menu-lifetime, and action tests cover supported adapters. Complete installed player/cooking controllers and live native parity remain unfinished. Action-form dialog labels use the accepted pack translator, as the title and body already do. From 40b929de132ad6b000666d6acc74b5fc693e99a2 Mon Sep 17 00:00:00 2001 From: AlexProgrammerDE <40795980+AlexProgrammerDE@users.noreply.github.com> Date: Wed, 4 Nov 2026 23:57:58 +0100 Subject: [PATCH 3/3] feat(inventory): retain definition-owned storage policies Retain typed slot limits, nesting flags, and immutable descriptor maps on the selected native item definition. Preserve policy ownership across numeric ID collisions and packet mutation. Keep partial or wrong-typed policies unavailable instead of inventing unrestricted filters. Keep descriptor resolution in the later runtime layer. Resolve the shared registry-test import context during the full 107-patch replay. Verify the retention regressions, full core suite, and both Checkstyle checks. --- ...erver-authoritative-bedrock-requests.patch | 15 +- ...rate-authored-native-ui-presentation.patch | 203 +++++++++++++++++- ...rate-authored-native-ui-presentation.pr.md | 4 + 3 files changed, 204 insertions(+), 18 deletions(-) diff --git a/patches/viabedrock/deferred/0003-translate-server-authoritative-bedrock-requests.patch b/patches/viabedrock/deferred/0003-translate-server-authoritative-bedrock-requests.patch index 7c3d196a..a0a10dbf 100644 --- a/patches/viabedrock/deferred/0003-translate-server-authoritative-bedrock-requests.patch +++ b/patches/viabedrock/deferred/0003-translate-server-authoritative-bedrock-requests.patch @@ -1,4 +1,4 @@ -From 766d63ec9879dcf7ec959d0905f3eb03b51f5dcd Mon Sep 17 00:00:00 2001 +From d983e2b657e13603f4747ab1cb9c3632795d8198 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(inventory): translate server-authoritative Bedrock @@ -906,7 +906,7 @@ Validate every network ID needed by bundle swaps and compaction before changing .../ItemRegistryComponentUpdatesTest.java | 118 + .../model/ItemRegistryTagIndexTest.java | 127 + .../protocol/model/ItemRegistryTagsTest.java | 173 + - .../protocol/model/ItemRegistryTest.java | 223 +- + .../protocol/model/ItemRegistryTest.java | 224 +- .../protocol/model/ItemStackHeaderTest.java | 67 + .../LegacyItemStackingPropertiesTest.java | 104 + .../model/NamedItemConstructionTest.java | 77 + @@ -948,7 +948,7 @@ Validate every network ID needed by bundle swaps and compaction before changing .../item/NetworkItemConstructionTest.java | 171 + .../types/item/NetworkItemCountTest.java | 35 +- .../types/item/NetworkItemStackFixtures.java | 69 + - 139 files changed, 29203 insertions(+), 2049 deletions(-) + 139 files changed, 29203 insertions(+), 2050 deletions(-) create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/PlayerInventoryScreenClose.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/PlayerInventoryScreenReady.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/PlayerInventoryScreenRequest.java @@ -32756,13 +32756,13 @@ index 00000000..fb6fc02a + +} diff --git a/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java -index 914b28a1..08ae32d1 100644 +index 04d8c44b..597d7344 100644 --- a/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java +++ b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java -@@ -6,12 +6,23 @@ - package net.raphimc.viabedrock.protocol.model; +@@ -7,13 +7,23 @@ package net.raphimc.viabedrock.protocol.model; import com.viaversion.nbt.tag.CompoundTag; + import com.viaversion.nbt.tag.ListTag; +import com.viaversion.viaversion.libs.gson.JsonParser; import io.netty.buffer.Unpooled; +import java.nio.file.Files; @@ -32781,11 +32781,12 @@ index 914b28a1..08ae32d1 100644 import org.junit.jupiter.api.Test; - -import java.util.List; +-import java.util.Map; +import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable; import static org.junit.jupiter.api.Assertions.*; -@@ -269,4 +280,212 @@ class ItemRegistryTest { +@@ -302,4 +312,212 @@ class ItemRegistryTest { return new ItemEntry(name, id, false, version, null); } diff --git a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch index 3fe42792..bba5a156 100644 --- a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch +++ b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.patch @@ -1,4 +1,4 @@ -From 9323b830ebe9e230566dff571938ce3a859e0191 Mon Sep 17 00:00:00 2001 +From 455632d9a1d43fd8905775eb6fc6c81df40464e8 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): resolve authored Bedrock server UI scenes @@ -759,6 +759,21 @@ signed Int3 payloads and use zero for a present String8 discriminator. The PE SHA-256 is 988f6a61403b4381aa41e6c66d64cce441b14e561a9b10f647c2758ef3f2672a. These controls use explicit native tag-map and component fixtures; they do not establish full protocol NBT construction or installed controller parity. + +Retain storage_item slot limits, nesting admission, and allowed/banned +descriptor maps on the selected native Item definition. Copy the typed +component data into immutable policy values so packet mutation and numeric +ID collisions cannot replace a retained owner's rules. A partial or wrong-typed +replacement leaves policy unavailable instead of inventing empty filters. + +The 1.26.60.5/protocol2225 captured bundle definitions expose these fields. +Original legacy reader141a72880 and storage vector conversion148f31150 +establish lowercase string-map descriptors, with tags/name/item_tag precedence +and wildcard32767 for a named entry. Seventeen original controls cover the +map reader, four-entry vector conversion, and default Legacy construction. +Raw policy retention does not resolve those descriptors or assume a Molang +version context. Bind them in the runtime layer with the existing registry +and descriptor contracts before enabling native transfer actions. --- Data Asset Sources.md | 33 + build.gradle | 1 + @@ -802,7 +817,8 @@ establish full protocol NBT construction or installed controller parity. .../protocol/model/ItemNameContext.java | 23 + .../protocol/model/ItemRegistry.java | 187 + .../model/ItemStackingProperties.java | 36 + - .../protocol/model/ItemStorageProperties.java | 40 + + .../protocol/model/ItemStoragePolicy.java | 61 + + .../protocol/model/ItemStorageProperties.java | 45 + .../model/LegacyItemStackingProperties.java | 54 + .../protocol/model/NativeItemDefinitions.java | 309 + .../protocol/model/NativeItemName.java | 78 + @@ -844,7 +860,8 @@ establish full protocol NBT construction or installed controller parity. .../model/ItemRegistryAliasesTest.java | 36 + .../model/ItemRegistryComponentNamesTest.java | 84 + .../model/ItemRegistryOrdinaryNamesTest.java | 72 + - .../protocol/model/ItemRegistryTest.java | 272 + + .../protocol/model/ItemRegistryTest.java | 305 + + .../protocol/model/ItemStoragePolicyTest.java | 51 + .../model/NativeItemDefinitionsTest.java | 207 + .../protocol/model/NativeItemNameTest.java | 61 + .../packet/ModalFormTransitionTest.java | 165 + @@ -858,7 +875,7 @@ establish full protocol NBT construction or installed controller parity. .../native-bundle-tooltip-layout.json | 266 + .../inventory/native-bundle-transfers.json | 1622 ++ .../inventory/native-item-storage.json | 568 + - 98 files changed, 40205 insertions(+), 364 deletions(-) + 100 files changed, 40355 insertions(+), 364 deletions(-) create mode 100644 src/main/java/net/raphimc/viabedrock/api/chunk/blockstate/BuiltinBlockNames.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipData.java create mode 100644 src/main/java/net/raphimc/viabedrock/api/model/NativeBundleTooltipItems.java @@ -889,6 +906,7 @@ establish full protocol NBT construction or installed controller parity. create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/ItemNameContext.java create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/ItemRegistry.java create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/ItemStackingProperties.java + create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicy.java create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/ItemStorageProperties.java create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/LegacyItemStackingProperties.java create mode 100644 src/main/java/net/raphimc/viabedrock/protocol/model/NativeItemDefinitions.java @@ -919,6 +937,7 @@ establish full protocol NBT construction or installed controller parity. create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryComponentNamesTest.java create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryOrdinaryNamesTest.java create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java + create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicyTest.java create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/NativeItemDefinitionsTest.java create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/model/NativeItemNameTest.java create mode 100644 src/test/java/net/raphimc/viabedrock/protocol/packet/ModalFormTransitionTest.java @@ -4527,12 +4546,79 @@ index 00000000..06361312 + } + +} +diff --git a/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicy.java b/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicy.java +new file mode 100644 +index 00000000..0e59c214 +--- /dev/null ++++ b/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicy.java +@@ -0,0 +1,61 @@ ++/* ++ * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock ++ * Copyright (C) 2026 RK_01/RaphiMC and contributors ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++package net.raphimc.viabedrock.protocol.model; ++ ++import com.viaversion.nbt.tag.ByteTag; ++import com.viaversion.nbt.tag.CompoundTag; ++import com.viaversion.nbt.tag.IntTag; ++import com.viaversion.nbt.tag.ListTag; ++import com.viaversion.nbt.tag.StringTag; ++import com.viaversion.nbt.tag.Tag; ++ ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.List; ++import java.util.Map; ++ ++/** Definition-owned storage rules, before descriptor resolution through the native registry. */ ++public record ItemStoragePolicy(int maxSlots, boolean allowNested, List> allowedItems, ++ List> bannedItems) { ++ ++ public ItemStoragePolicy { ++ allowedItems = allowedItems.stream().map(Map::copyOf).toList(); ++ bannedItems = bannedItems.stream().map(Map::copyOf).toList(); ++ } ++ ++ /** Unavailable fields cannot silently become empty filters or an invented slot limit. */ ++ public static ItemStoragePolicy fromComponent(final CompoundTag component) { ++ if (!(component.get("max_slots") instanceof IntTag slots) ++ || !(component.get("allow_nested_storage_items") instanceof ByteTag nested)) { ++ return null; ++ } ++ final var allowed = descriptors(component.get("allowed_items")); ++ final var banned = descriptors(component.get("banned_items")); ++ return allowed != null && banned != null ? new ItemStoragePolicy(slots.asInt(), nested.asByte() != 0, allowed, banned) : null; ++ } ++ ++ private static List> descriptors(final Tag input) { ++ if (!(input instanceof ListTag values)) { ++ return null; ++ } ++ final List> result = new ArrayList<>(values.size()); ++ for (final var value : values) { ++ if (!(value instanceof CompoundTag descriptor)) { ++ return null; ++ } ++ final Map fields = new HashMap<>(); ++ for (final var field : descriptor.getValue().entrySet()) { ++ if (!(field.getValue() instanceof StringTag text)) { ++ return null; ++ } ++ fields.put(field.getKey(), text.getValue()); ++ } ++ result.add(fields); ++ } ++ return result; ++ } ++ ++} diff --git a/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStorageProperties.java b/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStorageProperties.java new file mode 100644 -index 00000000..08ca66d6 +index 00000000..9d70dedd --- /dev/null +++ b/src/main/java/net/raphimc/viabedrock/protocol/model/ItemStorageProperties.java -@@ -0,0 +1,40 @@ +@@ -0,0 +1,45 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -4544,12 +4630,16 @@ index 00000000..08ca66d6 +import com.viaversion.nbt.tag.IntTag; + +/** Storage components belong to the selected native Item definition. */ -+public record ItemStorageProperties(boolean storage, Integer modifier, Integer capacity, Integer viewableSlots) { ++public record ItemStorageProperties(boolean storage, Integer modifier, Integer capacity, Integer viewableSlots, ItemStoragePolicy policy) { + + public static final ItemStorageProperties NONE = new ItemStorageProperties(false, null, null); + + public ItemStorageProperties(final boolean storage, final Integer modifier, final Integer capacity) { -+ this(storage, modifier, capacity, null); ++ this(storage, modifier, capacity, null, null); ++ } ++ ++ public ItemStorageProperties(final boolean storage, final Integer modifier, final Integer capacity, final Integer viewableSlots) { ++ this(storage, modifier, capacity, viewableSlots, null); + } + + public ItemStorageProperties withComponentData(final CompoundTag components) { @@ -4557,7 +4647,8 @@ index 00000000..08ca66d6 + return new ItemStorageProperties(storage, + integer(components, "minecraft:storage_weight_modifier", "weight_in_storage_item", this.modifier), + integer(components, "minecraft:storage_weight_limit", "max_weight_limit", this.capacity), -+ integer(components, "minecraft:bundle_interaction", "num_viewable_slots", this.viewableSlots)); ++ integer(components, "minecraft:bundle_interaction", "num_viewable_slots", this.viewableSlots), ++ components.get("minecraft:storage_item") instanceof CompoundTag value ? ItemStoragePolicy.fromComponent(value) : this.policy); + } + + public boolean complete() { @@ -38231,10 +38322,10 @@ index 00000000..db6b7e37 +} diff --git a/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java new file mode 100644 -index 00000000..914b28a1 +index 00000000..04d8c44b --- /dev/null +++ b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemRegistryTest.java -@@ -0,0 +1,272 @@ +@@ -0,0 +1,305 @@ +/* + * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock + * Copyright (C) 2026 RK_01/RaphiMC and contributors @@ -38243,18 +38334,51 @@ index 00000000..914b28a1 +package net.raphimc.viabedrock.protocol.model; + +import com.viaversion.nbt.tag.CompoundTag; ++import com.viaversion.nbt.tag.ListTag; +import io.netty.buffer.Unpooled; +import net.raphimc.viabedrock.protocol.data.enums.bedrock.generated.ItemVersion; +import net.raphimc.viabedrock.protocol.types.BedrockTypes; +import org.junit.jupiter.api.Test; + +import java.util.List; ++import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +class ItemRegistryTest { + + @Test ++ void storagePoliciesKeepTheirDefinitionOwnerAndDoNotBorrowMutablePacketFields() { ++ final var storage = new CompoundTag(); ++ storage.putInt("max_slots", 64); ++ storage.putByte("allow_nested_storage_items", (byte) 1); ++ storage.put("allowed_items", new ListTag<>(CompoundTag.class)); ++ final var blocked = new CompoundTag(); ++ blocked.putString("name", "minecraft:shulker_box"); ++ final var banned = new ListTag<>(CompoundTag.class); ++ banned.add(blocked); ++ storage.put("banned_items", banned); ++ final var components = new CompoundTag(); ++ components.put("minecraft:storage_item", storage); ++ final var first = component("test:first_storage", 30011, ItemVersion.DataDriven, components); ++ storage.putInt("max_slots", 3); ++ storage.putByte("allow_nested_storage_items", (byte) 0); ++ blocked.putString("name", "minecraft:stone"); ++ final var second = component("test:second_storage", 30011, ItemVersion.DataDriven, components); ++ final var registry = new ItemRegistry(new ItemEntry[]{first, second}); ++ final var retained = new BedrockItem(registry.definition("test:first_storage"), (short) 0, (byte) 1); ++ final var original = registry.storageProperties(retained).policy(); ++ assertEquals(new ItemStoragePolicy(64, true, List.of(), List.of(Map.of("name", "minecraft:shulker_box"))), original); ++ assertEquals(new ItemStoragePolicy(3, false, List.of(), List.of(Map.of("name", "minecraft:stone"))), ++ registry.storageProperties(new BedrockItem(30011)).policy()); ++ components.clear(); ++ registry.registrations().getFirst().componentData().clear(); ++ assertEquals("minecraft:shulker_box", original.bannedItems().getFirst().get("name")); ++ assertThrows(UnsupportedOperationException.class, () -> original.bannedItems().clear()); ++ assertThrows(UnsupportedOperationException.class, () -> original.bannedItems().getFirst().put("name", "minecraft:stone")); ++ } ++ ++ @Test + void emptyDeclarationsKeepBuiltinAndLateBlockDefinitions() { + final var registry = new ItemRegistry(new ItemEntry[0]); + assertTrue(registry.registrations().isEmpty()); @@ -38507,6 +38631,63 @@ index 00000000..914b28a1 + } + +} +diff --git a/src/test/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicyTest.java b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicyTest.java +new file mode 100644 +index 00000000..bc8b1962 +--- /dev/null ++++ b/src/test/java/net/raphimc/viabedrock/protocol/model/ItemStoragePolicyTest.java +@@ -0,0 +1,51 @@ ++/* ++ * This file is part of ViaBedrock - https://github.com/RaphiMC/ViaBedrock ++ * Copyright (C) 2026 RK_01/RaphiMC and contributors ++ * SPDX-License-Identifier: GPL-3.0-or-later ++ */ ++package net.raphimc.viabedrock.protocol.model; ++ ++import com.viaversion.nbt.tag.CompoundTag; ++import com.viaversion.nbt.tag.ListTag; ++import org.junit.jupiter.api.Test; ++ ++import java.util.List; ++import java.util.Map; ++ ++import static org.junit.jupiter.api.Assertions.*; ++ ++class ItemStoragePolicyTest { ++ ++ @Test ++ void absentComponentsRetainPolicyButUnverifiedReplacementCannotClearItsFilters() { ++ final var storage = new CompoundTag(); ++ storage.putInt("max_slots", 64); ++ storage.putByte("allow_nested_storage_items", (byte) 1); ++ storage.put("allowed_items", new ListTag<>(CompoundTag.class)); ++ final var descriptor = new CompoundTag(); ++ descriptor.putString("tags", "q.any_tag('fixture')"); ++ descriptor.putString("name", "minecraft:stone:3"); ++ final var banned = new ListTag<>(CompoundTag.class); ++ banned.add(descriptor); ++ storage.put("banned_items", banned); ++ final var components = new CompoundTag(); ++ components.put("minecraft:storage_item", storage); ++ final var properties = ItemStorageProperties.NONE.withComponentData(components); ++ assertEquals(new ItemStoragePolicy(64, true, List.of(), ++ List.of(Map.of("tags", "q.any_tag('fixture')", "name", "minecraft:stone:3"))), properties.policy()); ++ assertSame(properties.policy(), properties.withComponentData(new CompoundTag()).policy()); ++ descriptor.putInt("name", 3); ++ assertNull(properties.withComponentData(components).policy()); ++ descriptor.putString("name", "minecraft:stone:3"); ++ storage.remove("allowed_items"); ++ assertNull(properties.withComponentData(components).policy()); ++ storage.put("allowed_items", new ListTag<>(CompoundTag.class)); ++ storage.putString("allow_nested_storage_items", "true"); ++ assertNull(properties.withComponentData(components).policy()); ++ storage.putByte("allow_nested_storage_items", (byte) 1); ++ storage.putShort("max_slots", (short) 64); ++ assertNull(properties.withComponentData(components).policy()); ++ assertEquals("minecraft:stone:3", properties.policy().bannedItems().getFirst().get("name")); ++ } ++ ++} diff --git a/src/test/java/net/raphimc/viabedrock/protocol/model/NativeItemDefinitionsTest.java b/src/test/java/net/raphimc/viabedrock/protocol/model/NativeItemDefinitionsTest.java new file mode 100644 index 00000000..ccbc7903 diff --git a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md index 248841e6..bf68237d 100644 --- a/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md +++ b/patches/viabedrock/upstreamable/0095-integrate-authored-native-ui-presentation.pr.md @@ -29,6 +29,10 @@ Original storage admission and child lookup controls execute the native Compound Local regressions cover zero-container weight, unknown contents, tooltip transport, and physical insertion. Full protocol tag construction and installed controller behavior remain outside these controls. +`ItemStoragePolicy` retains typed slot limits, nesting flags, and immutable lowercase descriptor maps on each selected definition. +Registry regressions cover packet mutation, numeric-ID collisions, absent updates, and malformed replacements without inventing unrestricted filters. +Descriptor binding, its version context, and live request execution remain unfinished. + Packet, menu-lifetime, and action tests cover supported adapters. Complete installed player/cooking controllers and live native parity remain unfinished. Action-form dialog labels use the accepted pack translator, as the title and body already do.