From 0ce1c5792c1b2059edd735eb4c604e1a1c451a6b Mon Sep 17 00:00:00 2001 From: Taskeren Date: Sun, 7 Jun 2026 16:38:18 +0800 Subject: [PATCH 1/6] Add NBTPath#of(Tag, Tag) --- src/main/java/org/glavo/nbt/NBTPath.java | 40 +++++++++++++ src/test/java/org/glavo/nbt/TestNBTPath.java | 62 ++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 src/test/java/org/glavo/nbt/TestNBTPath.java diff --git a/src/main/java/org/glavo/nbt/NBTPath.java b/src/main/java/org/glavo/nbt/NBTPath.java index a6fdc2e..de17b54 100644 --- a/src/main/java/org/glavo/nbt/NBTPath.java +++ b/src/main/java/org/glavo/nbt/NBTPath.java @@ -17,11 +17,15 @@ import org.glavo.nbt.internal.path.NBTPathImpl; import org.glavo.nbt.internal.snbt.SNBTParser; +import org.glavo.nbt.tag.CompoundTag; +import org.glavo.nbt.tag.ParentTag; import org.glavo.nbt.tag.Tag; import org.glavo.nbt.tag.TagType; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.Nullable; +import java.util.*; + /// An NBT path is a descriptive string used to specify one or more particular elements from an NBT data tree. /// /// @see NBT Path - Minecraft Wiki @@ -34,6 +38,42 @@ static NBTPath of(String path) throws IllegalArgumentException { return new SNBTParser(path, 0, path.length()).nextPath(); } + /// Get the path from the root to the given tag. + /// + /// @param expectedRoot the expected root instead of the top of the tree. + /// @return the path or `null` if parent is null. + @SuppressWarnings({"DataFlowIssue", "unchecked"}) + @Contract(pure = true) + static @Nullable NBTPath of(T tag, @Nullable Tag expectedRoot) { + ParentTag parentTag = tag.getParentTag(); + if (parentTag == null) return null; + + List paths = new ArrayList<>(); + paths.add(getIndicator(tag)); + while (true) { + if (parentTag == expectedRoot) break; + paths.add(getIndicator(parentTag)); + ParentTag parent = parentTag.getParentTag(); + if (parent == null) break; + parentTag = parent; + } + + if (parentTag != expectedRoot) + throw new IllegalStateException("Unexpected root tag " + parentTag + ", expected " + expectedRoot + "."); + Collections.reverse(paths); + String pathString = String.join(".", paths); + return (NBTPath) of(pathString).withTagType(tag.getType()); + } + + /// Get the indicator of the given tag, depends on its parent tag. + /// + /// @return the name if parent is [CompoundTag], the index if parent is other [ParentTag], or `null` if parent is null. + @Contract(pure = true) + static @Nullable String getIndicator(Tag tag) { + ParentTag parentTag = tag.getParentTag(); + return parentTag == null ? null : parentTag instanceof CompoundTag ? tag.getName() : ('[' + String.valueOf(tag.getIndex()) + ']'); + } + /// Returns the tag type of this path. @Contract(pure = true) @Nullable TagType getTagType(); diff --git a/src/test/java/org/glavo/nbt/TestNBTPath.java b/src/test/java/org/glavo/nbt/TestNBTPath.java new file mode 100644 index 0000000..1d0b841 --- /dev/null +++ b/src/test/java/org/glavo/nbt/TestNBTPath.java @@ -0,0 +1,62 @@ +/* + * Copyright 2026 Taskeren + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.glavo.nbt; + +import org.glavo.nbt.tag.*; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +final class TestNBTPath { + + @Test + void testOfPath() { + CompoundTag root = new CompoundTag().setName("root"); + IntTag tag; + + root.addTag("foo", new CompoundTag() + .addTag("bar", new ListTag() + .addTag(new IntTag(0)) + .addTag(new IntTag(1)) + .addTag(tag = new IntTag(2)) + )); + + NBTPath pathTo2 = NBTPath.of(tag, root); + assertNotNull(pathTo2); + assertEquals(2, root.getFirstInt(pathTo2)); + assertEquals(NBTPath.of("foo.bar[2]").withTagType(TagType.INT), pathTo2); + } + + @Test + void testOfPath2() { + CompoundTag root = new CompoundTag().setName("root"); + CompoundTag expectedRoot; + IntTag tag; + + root.addTag("foo", expectedRoot = new CompoundTag() + .addTag("bar", new CompoundTag() + .addTag("baz", new ListTag() + .addTag(new IntTag(0)) + .addTag(new IntTag(1)) + .addTag(tag = new IntTag(2)) + ))); + + NBTPath pathTo2 = NBTPath.of(tag, expectedRoot); + assertNotNull(pathTo2); + assertEquals(2, expectedRoot.getFirstInt(pathTo2)); + assertEquals(NBTPath.of("bar.baz[2]").withTagType(TagType.INT), pathTo2); + } +} From 6feb8db7f7d6cd9a6c8042afbffa3e0859edbe76 Mon Sep 17 00:00:00 2001 From: Taskeren Date: Sun, 7 Jun 2026 16:43:11 +0800 Subject: [PATCH 2/6] Add throwing information --- src/main/java/org/glavo/nbt/NBTPath.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/glavo/nbt/NBTPath.java b/src/main/java/org/glavo/nbt/NBTPath.java index de17b54..d718aee 100644 --- a/src/main/java/org/glavo/nbt/NBTPath.java +++ b/src/main/java/org/glavo/nbt/NBTPath.java @@ -42,9 +42,10 @@ static NBTPath of(String path) throws IllegalArgumentException { /// /// @param expectedRoot the expected root instead of the top of the tree. /// @return the path or `null` if parent is null. + /// @throws IllegalStateException when the expected root doesn't match the actual root. @SuppressWarnings({"DataFlowIssue", "unchecked"}) @Contract(pure = true) - static @Nullable NBTPath of(T tag, @Nullable Tag expectedRoot) { + static @Nullable NBTPath of(T tag, @Nullable Tag expectedRoot) throws IllegalArgumentException, IllegalStateException { ParentTag parentTag = tag.getParentTag(); if (parentTag == null) return null; From 2436731ed1558a30f2fe2de8ee8fa8d8eba6b72e Mon Sep 17 00:00:00 2001 From: Taskeren Date: Mon, 8 Jun 2026 22:51:54 +0800 Subject: [PATCH 3/6] Add NBTPath#toPathString --- src/main/java/org/glavo/nbt/NBTPath.java | 12 +++++ .../glavo/nbt/internal/path/NBTPathImpl.java | 46 +++++++++---------- src/test/java/org/glavo/nbt/NBTPathTest.java | 36 +++++++++++++++ 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/glavo/nbt/NBTPath.java b/src/main/java/org/glavo/nbt/NBTPath.java index d718aee..5331679 100644 --- a/src/main/java/org/glavo/nbt/NBTPath.java +++ b/src/main/java/org/glavo/nbt/NBTPath.java @@ -91,4 +91,16 @@ static NBTPath of(String path) throws IllegalArgumentException { @Contract(pure = true) NBTPath withTagType(TagType tagType) throws IllegalStateException; + /// Returns the path string. + /// + /// @param omitDots `true` to omit dots if possible. + @Contract(pure = true) + String toPathString(boolean omitDots); + + /// Returns the path string with dots omitted if possible. + @Contract(pure = true) + default String toPathString() { + return toPathString(true); + } + } diff --git a/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java b/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java index 6a9c432..d063e42 100644 --- a/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java +++ b/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java @@ -107,33 +107,31 @@ public int hashCode() { } @Override - public String toString() { - if (cachedString == null) { - StringBuilder builder = new StringBuilder(); - - if (tagType != null) { - builder.append("<").append(tagType).append("> "); + public String toPathString(boolean omitDots) { + StringBuilder builder = new StringBuilder(); + + SNBTWriter writer = new SNBTWriter<>(SNBTCodec.ofCompact(), builder); + for (int i = 0; i < nodes.length; i++) { + NBTPathNode node = nodes[i]; + try { + node.appendTo(writer); + } catch (IOException e) { + throw new AssertionError(e); } - - var writer = new SNBTWriter<>(SNBTCodec.ofCompact(), builder); - - boolean first = true; - for (NBTPathNode node : nodes) { - if (first) { - first = false; - } else if (node.needDot()) { - writer.getAppendable().append('.'); - } - - try { - node.appendTo(writer); - } catch (IOException e) { - throw new AssertionError(e); - } + if (i + 1 < nodes.length && (!omitDots || nodes[i + 1].needDot())) { + writer.getAppendable().append('.'); } + } - builder.append(']'); - cachedString = builder.toString(); + return builder.toString(); + } + + @Override + public String toString() { + if (cachedString == null) { + String pathString = toPathString(); + if (tagType != null) pathString = "<" + tagType + ">" + " " + pathString; + cachedString = pathString; } return cachedString; diff --git a/src/test/java/org/glavo/nbt/NBTPathTest.java b/src/test/java/org/glavo/nbt/NBTPathTest.java index ce5d648..84721e8 100644 --- a/src/test/java/org/glavo/nbt/NBTPathTest.java +++ b/src/test/java/org/glavo/nbt/NBTPathTest.java @@ -188,4 +188,40 @@ void testInvalidPathSyntax() { assertThrows(IllegalArgumentException.class, () -> NBTPath.of("\"unterminated")); assertThrows(IllegalArgumentException.class, () -> NBTPath.of("[2147483648]")); } + + @Test + void testPathString() { + assertEquals("{}", NBTPath.of("{}").toPathString()); + assertEquals("{Invisible:1B}", NBTPath.of("{Invisible:1b}").toPathString()); + assertEquals("\"A Very Cool Name[]\"", NBTPath.of("\"A Very Cool Name[]\"").toPathString()); + assertEquals("\"A Very Cool Name[]\"{}", NBTPath.of("\"A Very Cool Name[]\"{}").toPathString()); + assertEquals("\"A Very Cool Name[]\"[]", NBTPath.of("\"A Very Cool Name[]\"[]").toPathString()); + assertEquals("\"A Very Cool Name[]\"[{}]", NBTPath.of("\"A Very Cool Name[]\"[{}]").toPathString()); + assertEquals("\"A Very Cool Name[]\"[{Count:25B}]", NBTPath.of("\"A Very Cool Name[]\"[{Count:25b}]").toPathString()); + assertEquals("\"A Very Cool Name[]\"[][][]", NBTPath.of("\"A Very Cool Name[]\"[][][]").toPathString()); + assertEquals("foo.bar", NBTPath.of("foo.bar").toPathString()); + assertEquals("foo.bar[]", NBTPath.of("foo.bar.[]").toPathString()); + assertEquals("foo.bar[{}]", NBTPath.of("foo.bar.[{}]").toPathString()); + assertEquals("foo.bar[0]", NBTPath.of("foo.bar.[0]").toPathString()); + assertEquals("foo.bar[-1]", NBTPath.of("foo.bar.[-1]").toPathString()); + assertEquals("foo.bar.\"0123\"", NBTPath.of("foo.bar.\"0123\"").toPathString()); + } + + @Test + void testPathStringKeepDots() { + assertEquals("{}", NBTPath.of("{}").toPathString(false)); + assertEquals("{Invisible:1B}", NBTPath.of("{Invisible:1b}").toPathString(false)); + assertEquals("\"A Very Cool Name[]\"", NBTPath.of("\"A Very Cool Name[]\"").toPathString(false)); + assertEquals("\"A Very Cool Name[]\"{}", NBTPath.of("\"A Very Cool Name[]\"{}").toPathString(false)); + assertEquals("\"A Very Cool Name[]\".[]", NBTPath.of("\"A Very Cool Name[]\"[]").toPathString(false)); + assertEquals("\"A Very Cool Name[]\".[{}]", NBTPath.of("\"A Very Cool Name[]\"[{}]").toPathString(false)); + assertEquals("\"A Very Cool Name[]\".[{Count:25B}]", NBTPath.of("\"A Very Cool Name[]\"[{Count:25b}]").toPathString(false)); + assertEquals("\"A Very Cool Name[]\".[].[].[]", NBTPath.of("\"A Very Cool Name[]\"[][][]").toPathString(false)); + assertEquals("foo.bar", NBTPath.of("foo.bar").toPathString(false)); + assertEquals("foo.bar.[]", NBTPath.of("foo.bar.[]").toPathString(false)); + assertEquals("foo.bar.[{}]", NBTPath.of("foo.bar.[{}]").toPathString(false)); + assertEquals("foo.bar.[0]", NBTPath.of("foo.bar.[0]").toPathString(false)); + assertEquals("foo.bar.[-1]", NBTPath.of("foo.bar.[-1]").toPathString(false)); + assertEquals("foo.bar.\"0123\"", NBTPath.of("foo.bar.\"0123\"").toPathString(false)); + } } From 7617c8c5c7923356e279c6804e103b85186539d9 Mon Sep 17 00:00:00 2001 From: Taskeren Date: Mon, 8 Jun 2026 23:09:36 +0800 Subject: [PATCH 4/6] Fix --- src/main/java/org/glavo/nbt/NBTPath.java | 21 ++++++------------- .../glavo/nbt/internal/path/NBTPathImpl.java | 9 ++++++++ src/test/java/org/glavo/nbt/TestNBTPath.java | 15 +++++++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/main/java/org/glavo/nbt/NBTPath.java b/src/main/java/org/glavo/nbt/NBTPath.java index 5331679..93ba15f 100644 --- a/src/main/java/org/glavo/nbt/NBTPath.java +++ b/src/main/java/org/glavo/nbt/NBTPath.java @@ -16,8 +16,8 @@ package org.glavo.nbt; import org.glavo.nbt.internal.path.NBTPathImpl; +import org.glavo.nbt.internal.path.NBTPathNode; import org.glavo.nbt.internal.snbt.SNBTParser; -import org.glavo.nbt.tag.CompoundTag; import org.glavo.nbt.tag.ParentTag; import org.glavo.nbt.tag.Tag; import org.glavo.nbt.tag.TagType; @@ -49,11 +49,11 @@ static NBTPath of(String path) throws IllegalArgumentException { ParentTag parentTag = tag.getParentTag(); if (parentTag == null) return null; - List paths = new ArrayList<>(); - paths.add(getIndicator(tag)); + List paths = new ArrayList<>(); + paths.add(NBTPathImpl.getIndicator(tag)); while (true) { if (parentTag == expectedRoot) break; - paths.add(getIndicator(parentTag)); + paths.add(NBTPathImpl.getIndicator(parentTag)); ParentTag parent = parentTag.getParentTag(); if (parent == null) break; parentTag = parent; @@ -62,17 +62,8 @@ static NBTPath of(String path) throws IllegalArgumentException { if (parentTag != expectedRoot) throw new IllegalStateException("Unexpected root tag " + parentTag + ", expected " + expectedRoot + "."); Collections.reverse(paths); - String pathString = String.join(".", paths); - return (NBTPath) of(pathString).withTagType(tag.getType()); - } - - /// Get the indicator of the given tag, depends on its parent tag. - /// - /// @return the name if parent is [CompoundTag], the index if parent is other [ParentTag], or `null` if parent is null. - @Contract(pure = true) - static @Nullable String getIndicator(Tag tag) { - ParentTag parentTag = tag.getParentTag(); - return parentTag == null ? null : parentTag instanceof CompoundTag ? tag.getName() : ('[' + String.valueOf(tag.getIndex()) + ']'); + NBTPathNode[] nodes = paths.toArray(NBTPathNode[]::new); + return (NBTPath) new NBTPathImpl<>(nodes, tag.getType()); } /// Returns the tag type of this path. diff --git a/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java b/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java index d063e42..3ded6e9 100644 --- a/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java +++ b/src/main/java/org/glavo/nbt/internal/path/NBTPathImpl.java @@ -22,6 +22,7 @@ import org.glavo.nbt.internal.snbt.SNBTWriter; import org.glavo.nbt.io.SNBTCodec; import org.glavo.nbt.tag.CompoundTag; +import org.glavo.nbt.tag.ParentTag; import org.glavo.nbt.tag.Tag; import org.glavo.nbt.tag.TagType; import org.jetbrains.annotations.Nullable; @@ -59,6 +60,14 @@ public static Stream select(NBTParent parent, NBTPath) tags; } + /// Get the indicator of the given tag, depends on its parent tag. + /// + /// @return the name node if parent is [CompoundTag], the index node if parent is other [ParentTag], or `null` if parent is null. + public static @Nullable NBTPathNode getIndicator(Tag tag) { + ParentTag parentTag = tag.getParentTag(); + return parentTag == null ? null : parentTag instanceof CompoundTag ? new NBTPathNode.NamedSubTag(tag.getName()) : new NBTPathNode.Index(tag.getIndex()); + } + private final NBTPathNode @Unmodifiable [] nodes; private final @Nullable TagType tagType; diff --git a/src/test/java/org/glavo/nbt/TestNBTPath.java b/src/test/java/org/glavo/nbt/TestNBTPath.java index 1d0b841..4a94ab7 100644 --- a/src/test/java/org/glavo/nbt/TestNBTPath.java +++ b/src/test/java/org/glavo/nbt/TestNBTPath.java @@ -59,4 +59,19 @@ void testOfPath2() { assertEquals(2, expectedRoot.getFirstInt(pathTo2)); assertEquals(NBTPath.of("bar.baz[2]").withTagType(TagType.INT), pathTo2); } + + @Test + void testOfPath3() { + CompoundTag root = new CompoundTag().setName("root"); + StringTag tag; + + root.addTag("Very Cool Name", new CompoundTag() + .addTag("bar", new CompoundTag() + .addTag("baz", tag = new StringTag(":D")))); + + NBTPath pathToSmile = NBTPath.of(tag, root); + assertNotNull(pathToSmile); + assertEquals(":D", root.getFirstString(pathToSmile)); + assertEquals(NBTPath.of("\"Very Cool Name\".bar.baz").withTagType(TagType.STRING), pathToSmile); + } } From 656c87b8e8cb6aa9b507553e43b689886d312e21 Mon Sep 17 00:00:00 2001 From: Taskeren Date: Mon, 8 Jun 2026 23:09:57 +0800 Subject: [PATCH 5/6] Merge tests --- src/test/java/org/glavo/nbt/NBTPathTest.java | 61 ++++++++++++++-- src/test/java/org/glavo/nbt/TestNBTPath.java | 77 -------------------- 2 files changed, 55 insertions(+), 83 deletions(-) delete mode 100644 src/test/java/org/glavo/nbt/TestNBTPath.java diff --git a/src/test/java/org/glavo/nbt/NBTPathTest.java b/src/test/java/org/glavo/nbt/NBTPathTest.java index 84721e8..ea2816e 100644 --- a/src/test/java/org/glavo/nbt/NBTPathTest.java +++ b/src/test/java/org/glavo/nbt/NBTPathTest.java @@ -21,12 +21,8 @@ import java.util.List; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertIterableEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNotNull; final class NBTPathTest { @@ -224,4 +220,57 @@ void testPathStringKeepDots() { assertEquals("foo.bar.[-1]", NBTPath.of("foo.bar.[-1]").toPathString(false)); assertEquals("foo.bar.\"0123\"", NBTPath.of("foo.bar.\"0123\"").toPathString(false)); } + + @Test + void testOfPath() { + CompoundTag root = new CompoundTag().setName("root"); + IntTag tag; + + root.addTag("foo", new CompoundTag() + .addTag("bar", new ListTag() + .addTag(new IntTag(0)) + .addTag(new IntTag(1)) + .addTag(tag = new IntTag(2)) + )); + + NBTPath pathTo2 = NBTPath.of(tag, root); + assertNotNull(pathTo2); + assertEquals(2, root.getFirstInt(pathTo2)); + assertEquals(NBTPath.of("foo.bar[2]").withTagType(TagType.INT), pathTo2); + } + + @Test + void testOfPath2() { + CompoundTag root = new CompoundTag().setName("root"); + CompoundTag expectedRoot; + IntTag tag; + + root.addTag("foo", expectedRoot = new CompoundTag() + .addTag("bar", new CompoundTag() + .addTag("baz", new ListTag() + .addTag(new IntTag(0)) + .addTag(new IntTag(1)) + .addTag(tag = new IntTag(2)) + ))); + + NBTPath pathTo2 = NBTPath.of(tag, expectedRoot); + assertNotNull(pathTo2); + assertEquals(2, expectedRoot.getFirstInt(pathTo2)); + assertEquals(NBTPath.of("bar.baz[2]").withTagType(TagType.INT), pathTo2); + } + + @Test + void testOfPath3() { + CompoundTag root = new CompoundTag().setName("root"); + StringTag tag; + + root.addTag("Very Cool Name", new CompoundTag() + .addTag("bar", new CompoundTag() + .addTag("baz", tag = new StringTag(":D")))); + + NBTPath pathToSmile = NBTPath.of(tag, root); + assertNotNull(pathToSmile); + assertEquals(":D", root.getFirstString(pathToSmile)); + assertEquals(NBTPath.of("\"Very Cool Name\".bar.baz").withTagType(TagType.STRING), pathToSmile); + } } diff --git a/src/test/java/org/glavo/nbt/TestNBTPath.java b/src/test/java/org/glavo/nbt/TestNBTPath.java deleted file mode 100644 index 4a94ab7..0000000 --- a/src/test/java/org/glavo/nbt/TestNBTPath.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2026 Taskeren - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.glavo.nbt; - -import org.glavo.nbt.tag.*; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -final class TestNBTPath { - - @Test - void testOfPath() { - CompoundTag root = new CompoundTag().setName("root"); - IntTag tag; - - root.addTag("foo", new CompoundTag() - .addTag("bar", new ListTag() - .addTag(new IntTag(0)) - .addTag(new IntTag(1)) - .addTag(tag = new IntTag(2)) - )); - - NBTPath pathTo2 = NBTPath.of(tag, root); - assertNotNull(pathTo2); - assertEquals(2, root.getFirstInt(pathTo2)); - assertEquals(NBTPath.of("foo.bar[2]").withTagType(TagType.INT), pathTo2); - } - - @Test - void testOfPath2() { - CompoundTag root = new CompoundTag().setName("root"); - CompoundTag expectedRoot; - IntTag tag; - - root.addTag("foo", expectedRoot = new CompoundTag() - .addTag("bar", new CompoundTag() - .addTag("baz", new ListTag() - .addTag(new IntTag(0)) - .addTag(new IntTag(1)) - .addTag(tag = new IntTag(2)) - ))); - - NBTPath pathTo2 = NBTPath.of(tag, expectedRoot); - assertNotNull(pathTo2); - assertEquals(2, expectedRoot.getFirstInt(pathTo2)); - assertEquals(NBTPath.of("bar.baz[2]").withTagType(TagType.INT), pathTo2); - } - - @Test - void testOfPath3() { - CompoundTag root = new CompoundTag().setName("root"); - StringTag tag; - - root.addTag("Very Cool Name", new CompoundTag() - .addTag("bar", new CompoundTag() - .addTag("baz", tag = new StringTag(":D")))); - - NBTPath pathToSmile = NBTPath.of(tag, root); - assertNotNull(pathToSmile); - assertEquals(":D", root.getFirstString(pathToSmile)); - assertEquals(NBTPath.of("\"Very Cool Name\".bar.baz").withTagType(TagType.STRING), pathToSmile); - } -} From 3e247e8bd48ec263fde5034aedeee851c62cdf9e Mon Sep 17 00:00:00 2001 From: Taskeren Date: Tue, 9 Jun 2026 14:05:38 +0800 Subject: [PATCH 6/6] Fix doc --- src/main/java/org/glavo/nbt/NBTPath.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/glavo/nbt/NBTPath.java b/src/main/java/org/glavo/nbt/NBTPath.java index 93ba15f..a2647db 100644 --- a/src/main/java/org/glavo/nbt/NBTPath.java +++ b/src/main/java/org/glavo/nbt/NBTPath.java @@ -38,7 +38,7 @@ static NBTPath of(String path) throws IllegalArgumentException { return new SNBTParser(path, 0, path.length()).nextPath(); } - /// Get the path from the root to the given tag. + /// Get the path from the root tag to the given tag. /// /// @param expectedRoot the expected root instead of the top of the tree. /// @return the path or `null` if parent is null.