minecraft-src/net/minecraft/network/chat/contents/NbtContents.java
2025-07-04 01:41:11 +03:00

145 lines
5.5 KiB
Java

package net.minecraft.network.chat.contents;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.datafixers.DataFixUtils;
import com.mojang.logging.LogUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.arguments.NbtPathArgument;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
import net.minecraft.network.chat.ComponentSerialization;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.world.entity.Entity;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class NbtContents implements ComponentContents {
private static final Logger LOGGER = LogUtils.getLogger();
public static final MapCodec<NbtContents> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
Codec.STRING.fieldOf("nbt").forGetter(NbtContents::getNbtPath),
Codec.BOOL.lenientOptionalFieldOf("interpret", false).forGetter(NbtContents::isInterpreting),
ComponentSerialization.CODEC.lenientOptionalFieldOf("separator").forGetter(NbtContents::getSeparator),
DataSource.CODEC.forGetter(NbtContents::getDataSource)
)
.apply(instance, NbtContents::new)
);
public static final ComponentContents.Type<NbtContents> TYPE = new ComponentContents.Type<>(CODEC, "nbt");
private final boolean interpreting;
private final Optional<Component> separator;
private final String nbtPathPattern;
private final DataSource dataSource;
@Nullable
protected final NbtPathArgument.NbtPath compiledNbtPath;
public NbtContents(String nbtPathPattern, boolean interpreting, Optional<Component> separator, DataSource dataSource) {
this(nbtPathPattern, compileNbtPath(nbtPathPattern), interpreting, separator, dataSource);
}
private NbtContents(
String nbtPathPattern, @Nullable NbtPathArgument.NbtPath compiledNbtPath, boolean interpreting, Optional<Component> separator, DataSource dataSource
) {
this.nbtPathPattern = nbtPathPattern;
this.compiledNbtPath = compiledNbtPath;
this.interpreting = interpreting;
this.separator = separator;
this.dataSource = dataSource;
}
@Nullable
private static NbtPathArgument.NbtPath compileNbtPath(String nbtPathPattern) {
try {
return new NbtPathArgument().parse(new StringReader(nbtPathPattern));
} catch (CommandSyntaxException var2) {
return null;
}
}
public String getNbtPath() {
return this.nbtPathPattern;
}
public boolean isInterpreting() {
return this.interpreting;
}
public Optional<Component> getSeparator() {
return this.separator;
}
public DataSource getDataSource() {
return this.dataSource;
}
public boolean equals(Object object) {
return this == object
? true
: object instanceof NbtContents nbtContents
&& this.dataSource.equals(nbtContents.dataSource)
&& this.separator.equals(nbtContents.separator)
&& this.interpreting == nbtContents.interpreting
&& this.nbtPathPattern.equals(nbtContents.nbtPathPattern);
}
public int hashCode() {
int i = this.interpreting ? 1 : 0;
i = 31 * i + this.separator.hashCode();
i = 31 * i + this.nbtPathPattern.hashCode();
return 31 * i + this.dataSource.hashCode();
}
public String toString() {
return "nbt{" + this.dataSource + ", interpreting=" + this.interpreting + ", separator=" + this.separator + "}";
}
@Override
public MutableComponent resolve(@Nullable CommandSourceStack nbtPathPattern, @Nullable Entity entity, int recursionDepth) throws CommandSyntaxException {
if (nbtPathPattern != null && this.compiledNbtPath != null) {
Stream<String> stream = this.dataSource.getData(nbtPathPattern).flatMap(compoundTag -> {
try {
return this.compiledNbtPath.get(compoundTag).stream();
} catch (CommandSyntaxException var3) {
return Stream.empty();
}
}).map(Tag::getAsString);
if (this.interpreting) {
Component component = DataFixUtils.orElse(
ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth), ComponentUtils.DEFAULT_NO_STYLE_SEPARATOR
);
return (MutableComponent)stream.flatMap(string -> {
try {
MutableComponent mutableComponent = Component.Serializer.fromJson(string, nbtPathPattern.registryAccess());
return Stream.of(ComponentUtils.updateForEntity(nbtPathPattern, mutableComponent, entity, recursionDepth));
} catch (Exception var5x) {
LOGGER.warn("Failed to parse component: {}", string, var5x);
return Stream.of();
}
}).reduce((mutableComponent, mutableComponent2) -> mutableComponent.append(component).append(mutableComponent2)).orElseGet(Component::empty);
} else {
return (MutableComponent)ComponentUtils.updateForEntity(nbtPathPattern, this.separator, entity, recursionDepth)
.map(
mutableComponent -> (MutableComponent)stream.map(Component::literal)
.reduce((mutableComponent2, mutableComponent3) -> mutableComponent2.append(mutableComponent).append(mutableComponent3))
.orElseGet(Component::empty)
)
.orElseGet(() -> Component.literal((String)stream.collect(Collectors.joining(", "))));
}
} else {
return Component.empty();
}
}
@Override
public ComponentContents.Type<?> type() {
return TYPE;
}
}