diff --git a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java index f4d67251e..fff63bbbe 100644 --- a/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/BlockNBTComponentImpl.java @@ -38,21 +38,31 @@ final class BlockNBTComponentImpl extends NBTComponentImpl implements BlockNBTComponent { private final Pos pos; - BlockNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @NotNull Pos pos) { - super(children, style, nbtPath, interpret); + BlockNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final @NotNull Pos pos) { + super(children, style, nbtPath, interpret, separator); this.pos = pos; } @Override public @NotNull BlockNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; - return new BlockNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.pos); + return new BlockNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.separator, this.pos); } @Override public @NotNull BlockNBTComponent interpret(final boolean interpret) { if (this.interpret == interpret) return this; - return new BlockNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.pos); + return new BlockNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.separator, this.pos); + } + + @Override + public @Nullable Component separator() { + return this.separator; + } + + @Override + public @NotNull BlockNBTComponent separator(final @Nullable ComponentLike separator) { + return new BlockNBTComponentImpl(this.children, this.style, this.nbtPath, this.interpret, separator, this.pos); } @Override @@ -62,17 +72,17 @@ final class BlockNBTComponentImpl extends NBTComponentImpl children) { - return new BlockNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.pos); + return new BlockNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.separator, this.pos); } @Override public @NotNull BlockNBTComponent style(final @NotNull Style style) { - return new BlockNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.pos); + return new BlockNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.separator, this.pos); } @Override @@ -127,7 +137,7 @@ static final class BuilderImpl extends NBTComponentImpl.BuilderImpl implements EntityNBTComponent { private final String selector; - EntityNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final String selector) { - super(children, style, nbtPath, interpret); + EntityNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final String selector) { + super(children, style, nbtPath, interpret, separator); this.selector = selector; } @Override public @NotNull EntityNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; - return new EntityNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.selector); + return new EntityNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.separator, this.selector); } @Override public @NotNull EntityNBTComponent interpret(final boolean interpret) { if (this.interpret == interpret) return this; - return new EntityNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.selector); + return new EntityNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.separator, this.selector); + } + + @Override + public @Nullable Component separator() { + return this.separator; + } + + @Override + public @NotNull EntityNBTComponent separator(final @Nullable ComponentLike separator) { + return new EntityNBTComponentImpl(this.children, this.style, this.nbtPath, this.interpret, separator, this.selector); } @Override @@ -59,17 +69,17 @@ final class EntityNBTComponentImpl extends NBTComponentImpl children) { - return new EntityNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.selector); + return new EntityNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.separator, this.selector); } @Override public @NotNull EntityNBTComponent style(final @NotNull Style style) { - return new EntityNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.selector); + return new EntityNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.separator, this.selector); } @Override @@ -124,7 +134,7 @@ static final class BuilderImpl extends NBTComponentImpl.BuilderImpl, B extends NBTCompone */ @Contract(pure = true) @NotNull C interpret(final boolean interpret); + + /** + * Gets the separator. + * + * @return the separator + * @since 4.8.0 + */ + @Nullable Component separator(); + + /** + * Sets the separator. + * + * @param separator the separator + * @return the separator + * @since 4.8.0 + */ + @NotNull C separator(final @Nullable ComponentLike separator); } diff --git a/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java b/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java index db27d5e0f..28b1d0edf 100644 --- a/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java +++ b/api/src/main/java/net/kyori/adventure/text/NBTComponentBuilder.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /* * This can't be a child of NBTComponent. @@ -55,4 +56,14 @@ public interface NBTComponentBuilder, B extends NBT */ @Contract("_ -> this") @NotNull B interpret(final boolean interpret); + + /** + * Sets the separator. + * + * @param separator the separator + * @return this builder + * @since 4.8.0 + */ + @Contract("_ -> this") + @NotNull B separator(final @Nullable ComponentLike separator); } diff --git a/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java index 9cd247596..dfe9ea5f1 100644 --- a/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/NBTComponentImpl.java @@ -35,11 +35,13 @@ abstract class NBTComponentImpl, B extends NBTCompo static final boolean INTERPRET_DEFAULT = false; final String nbtPath; final boolean interpret; + final @Nullable Component separator; - NBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret) { + NBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator) { super(children, style); this.nbtPath = nbtPath; this.interpret = interpret; + this.separator = ComponentLike.unbox(separator); } @Override @@ -58,7 +60,7 @@ public boolean equals(final @Nullable Object other) { if (!(other instanceof NBTComponent)) return false; if (!super.equals(other)) return false; final NBTComponent that = (NBTComponent) other; - return Objects.equals(this.nbtPath, that.nbtPath()) && this.interpret == that.interpret(); + return Objects.equals(this.nbtPath, that.nbtPath()) && this.interpret == that.interpret() && Objects.equals(this.separator, that.separator()); } @Override @@ -66,6 +68,7 @@ public int hashCode() { int result = super.hashCode(); result = (31 * result) + this.nbtPath.hashCode(); result = (31 * result) + Boolean.hashCode(this.interpret); + result = (31 * result) + Objects.hashCode(this.separator); return result; } @@ -74,7 +77,8 @@ public int hashCode() { return Stream.concat( Stream.of( ExaminableProperty.of("nbtPath", this.nbtPath), - ExaminableProperty.of("interpret", this.interpret) + ExaminableProperty.of("interpret", this.interpret), + ExaminableProperty.of("separator", this.separator) ), super.examinablePropertiesWithoutChildren() ); @@ -83,6 +87,7 @@ public int hashCode() { static abstract class BuilderImpl, B extends NBTComponentBuilder> extends AbstractComponentBuilder implements NBTComponentBuilder { protected @Nullable String nbtPath; protected boolean interpret = INTERPRET_DEFAULT; + protected @Nullable Component separator; BuilderImpl() { } @@ -106,5 +111,12 @@ static abstract class BuilderImpl, B extends NBTCom this.interpret = interpret; return (B) this; } + + @Override + @SuppressWarnings("unchecked") + public @NotNull B separator(final @Nullable ComponentLike separator) { + this.separator = ComponentLike.unbox(separator); + return (B) this; + } } } diff --git a/api/src/main/java/net/kyori/adventure/text/SelectorComponent.java b/api/src/main/java/net/kyori/adventure/text/SelectorComponent.java index bd17808e9..537d4cfb6 100644 --- a/api/src/main/java/net/kyori/adventure/text/SelectorComponent.java +++ b/api/src/main/java/net/kyori/adventure/text/SelectorComponent.java @@ -25,6 +25,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A component that can display the name of entities found with a given selector. @@ -60,6 +61,23 @@ public interface SelectorComponent extends BuildableComponent { */ @Contract("_ -> this") @NotNull Builder pattern(final @NotNull String pattern); + + /** + * Sets the separator. + * + * @param separator the separator + * @return this builder + * @since 4.8.0 + */ + @Contract("_ -> this") + @NotNull Builder separator(final @Nullable ComponentLike separator); } } diff --git a/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java b/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java index 144b96456..ccdd25766 100644 --- a/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java +++ b/api/src/main/java/net/kyori/adventure/text/SelectorComponentImpl.java @@ -35,10 +35,12 @@ final class SelectorComponentImpl extends AbstractComponent implements SelectorComponent { private final String pattern; + private final @Nullable Component separator; - SelectorComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String pattern) { + SelectorComponentImpl(final @NotNull List children, final @NotNull Style style, final @NotNull String pattern, final @Nullable ComponentLike separator) { super(children, style); this.pattern = pattern; + this.separator = ComponentLike.unbox(separator); } @Override @@ -49,17 +51,27 @@ final class SelectorComponentImpl extends AbstractComponent implements SelectorC @Override public @NotNull SelectorComponent pattern(final @NotNull String pattern) { if (Objects.equals(this.pattern, pattern)) return this; - return new SelectorComponentImpl(this.children, this.style, requireNonNull(pattern, "pattern")); + return new SelectorComponentImpl(this.children, this.style, requireNonNull(pattern, "pattern"), this.separator); + } + + @Override + public @Nullable Component separator() { + return this.separator; + } + + @Override + public @NotNull SelectorComponent separator(final @Nullable ComponentLike separator) { + return new SelectorComponentImpl(this.children, this.style, this.pattern, separator); } @Override public @NotNull SelectorComponent children(final @NotNull List children) { - return new SelectorComponentImpl(children, this.style, this.pattern); + return new SelectorComponentImpl(children, this.style, this.pattern, this.separator); } @Override public @NotNull SelectorComponent style(final @NotNull Style style) { - return new SelectorComponentImpl(this.children, style, this.pattern); + return new SelectorComponentImpl(this.children, style, this.pattern, this.separator); } @Override @@ -68,13 +80,14 @@ public boolean equals(final @Nullable Object other) { if (!(other instanceof SelectorComponent)) return false; if (!super.equals(other)) return false; final SelectorComponent that = (SelectorComponent) other; - return Objects.equals(this.pattern, that.pattern()); + return Objects.equals(this.pattern, that.pattern()) && Objects.equals(this.separator, that.separator()); } @Override public int hashCode() { int result = super.hashCode(); result = (31 * result) + this.pattern.hashCode(); + result = (31 * result) + Objects.hashCode(this.separator); return result; } @@ -82,7 +95,8 @@ public int hashCode() { protected @NotNull Stream examinablePropertiesWithoutChildren() { return Stream.concat( Stream.of( - ExaminableProperty.of("pattern", this.pattern) + ExaminableProperty.of("pattern", this.pattern), + ExaminableProperty.of("separator", this.separator) ), super.examinablePropertiesWithoutChildren() ); @@ -95,6 +109,7 @@ public int hashCode() { static final class BuilderImpl extends AbstractComponentBuilder implements SelectorComponent.Builder { private @Nullable String pattern; + private @Nullable Component separator; BuilderImpl() { } @@ -110,10 +125,16 @@ static final class BuilderImpl extends AbstractComponentBuilder implements StorageNBTComponent { private final Key storage; - StorageNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final Key storage) { - super(children, style, nbtPath, interpret); + StorageNBTComponentImpl(final @NotNull List children, final @NotNull Style style, final String nbtPath, final boolean interpret, final @Nullable ComponentLike separator, final Key storage) { + super(children, style, nbtPath, interpret, separator); this.storage = storage; } @Override public @NotNull StorageNBTComponent nbtPath(final @NotNull String nbtPath) { if (Objects.equals(this.nbtPath, nbtPath)) return this; - return new StorageNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.storage); + return new StorageNBTComponentImpl(this.children, this.style, nbtPath, this.interpret, this.separator, this.storage); } @Override public @NotNull StorageNBTComponent interpret(final boolean interpret) { if (this.interpret == interpret) return this; - return new StorageNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.storage); + return new StorageNBTComponentImpl(this.children, this.style, this.nbtPath, interpret, this.separator, this.storage); + } + + @Override + public @Nullable Component separator() { + return this.separator; + } + + @Override + public @NotNull StorageNBTComponent separator(final @Nullable ComponentLike separator) { + return new StorageNBTComponentImpl(this.children, this.style, this.nbtPath, this.interpret, separator, this.storage); } @Override @@ -60,17 +70,17 @@ final class StorageNBTComponentImpl extends NBTComponentImpl children) { - return new StorageNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.storage); + return new StorageNBTComponentImpl(children, this.style, this.nbtPath, this.interpret, this.separator, this.storage); } @Override public @NotNull StorageNBTComponent style(final @NotNull Style style) { - return new StorageNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.storage); + return new StorageNBTComponentImpl(this.children, style, this.nbtPath, this.interpret, this.separator, this.storage); } @Override @@ -125,7 +135,7 @@ static class BuilderImpl extends NBTComponentImpl.BuilderImpl, Json static final String NBT_BLOCK = "block"; static final String NBT_ENTITY = "entity"; static final String NBT_STORAGE = "storage"; + static final String SEPARATOR = "separator"; @Override public Component deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException { @@ -127,19 +128,21 @@ public Component deserialize(final JsonElement json, final Type typeOfT, final J component = builder; } } else if (object.has(SELECTOR)) { - component = Component.selector().pattern(object.get(SELECTOR).getAsString()); + final @Nullable Component separator = this.deserializeSeparator(object, context); + component = Component.selector().pattern(object.get(SELECTOR).getAsString()).separator(separator); } else if (object.has(KEYBIND)) { component = Component.keybind().keybind(object.get(KEYBIND).getAsString()); } else if (object.has(NBT)) { final String nbt = object.get(NBT).getAsString(); final boolean interpret = object.has(NBT_INTERPRET) && object.getAsJsonPrimitive(NBT_INTERPRET).getAsBoolean(); + final @Nullable Component separator = this.deserializeSeparator(object, context); if (object.has(NBT_BLOCK)) { final BlockNBTComponent.Pos pos = context.deserialize(object.get(NBT_BLOCK), BlockNBTComponent.Pos.class); - component = nbt(Component.blockNBT(), nbt, interpret).pos(pos); + component = nbt(Component.blockNBT(), nbt, interpret, separator).pos(pos); } else if (object.has(NBT_ENTITY)) { - component = nbt(Component.entityNBT(), nbt, interpret).selector(object.get(NBT_ENTITY).getAsString()); + component = nbt(Component.entityNBT(), nbt, interpret, separator).selector(object.get(NBT_ENTITY).getAsString()); } else if (object.has(NBT_STORAGE)) { - component = nbt(Component.storageNBT(), nbt, interpret).storage(context.deserialize(object.get(NBT_STORAGE), Key.class)); + component = nbt(Component.storageNBT(), nbt, interpret, separator).storage(context.deserialize(object.get(NBT_STORAGE), Key.class)); } else { throw notSureHowToDeserialize(element); } @@ -163,10 +166,18 @@ public Component deserialize(final JsonElement json, final Type typeOfT, final J return component.build(); } - private static , B extends NBTComponentBuilder> B nbt(final B builder, final String nbt, final boolean interpret) { + private @Nullable Component deserializeSeparator(final JsonObject json, final JsonDeserializationContext context) { + if (json.has(SEPARATOR)) { + return this.deserialize0(json.get(SEPARATOR), context); + } + return null; + } + + private static , B extends NBTComponentBuilder> B nbt(final B builder, final String nbt, final boolean interpret, final @Nullable Component separator) { return builder .nbtPath(nbt) - .interpret(interpret); + .interpret(interpret) + .separator(separator); } @Override @@ -214,7 +225,9 @@ public JsonElement serialize(final Component src, final Type typeOfSrc, final Js if (value != null) score.addProperty(SCORE_VALUE, value); object.add(SCORE, score); } else if (src instanceof SelectorComponent) { - object.addProperty(SELECTOR, ((SelectorComponent) src).pattern()); + final SelectorComponent sc = (SelectorComponent) src; + object.addProperty(SELECTOR, sc.pattern()); + this.serializeSeparator(context, object, sc.separator()); } else if (src instanceof KeybindComponent) { object.addProperty(KEYBIND, ((KeybindComponent) src).keybind()); } else if (src instanceof NBTComponent) { @@ -224,6 +237,7 @@ public JsonElement serialize(final Component src, final Type typeOfSrc, final Js if (src instanceof BlockNBTComponent) { final JsonElement position = context.serialize(((BlockNBTComponent) nc).pos()); object.add(NBT_BLOCK, position); + this.serializeSeparator(context, object, nc.separator()); } else if (src instanceof EntityNBTComponent) { object.addProperty(NBT_ENTITY, ((EntityNBTComponent) nc).selector()); } else if (src instanceof StorageNBTComponent) { @@ -238,6 +252,12 @@ public JsonElement serialize(final Component src, final Type typeOfSrc, final Js return object; } + private void serializeSeparator(final JsonSerializationContext context, final JsonObject json, final @Nullable Component separator) { + if (separator != null) { + json.add(SEPARATOR, context.serialize(separator)); + } + } + static JsonParseException notSureHowToDeserialize(final Object element) { return new JsonParseException("Don't know how to turn " + element + " into a Component"); }