TextComponentTagVisitor.java

net.minecraft.nbt.TextComponentTagVisitor

信息

  • 全限定名:net.minecraft.nbt.TextComponentTagVisitor
  • 类型:public class
  • 包:net.minecraft.nbt
  • 源码路径:src/main/java/net/minecraft/nbt/TextComponentTagVisitor.java
  • 起始行号:L19
  • 实现:TagVisitor
  • 职责:

    TODO

字段/常量

  • LOGGER

    • 类型: Logger
    • 修饰符: private static final
    • 源码定位: L20
    • 说明:

      TODO

  • INLINE_LIST_THRESHOLD

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L21
    • 说明:

      TODO

  • MAX_DEPTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L22
    • 说明:

      TODO

  • MAX_LENGTH

    • 类型: int
    • 修饰符: private static final
    • 源码定位: L23
    • 说明:

      TODO

  • SIMPLE_VALUE

    • 类型: Pattern
    • 修饰符: private static final
    • 源码定位: L24
    • 说明:

      TODO

  • NEWLINE

    • 类型: Component
    • 修饰符: private static final
    • 源码定位: L25
    • 说明:

      TODO

  • ELEMENT_SPACING

    • 类型: Component
    • 修饰符: private static final
    • 源码定位: L26
    • 说明:

      TODO

  • indentation

    • 类型: String
    • 修饰符: private final
    • 源码定位: L27
    • 说明:

      TODO

  • styling

    • 类型: TextComponentTagVisitor.Styling
    • 修饰符: private final
    • 源码定位: L28
    • 说明:

      TODO

  • sortKeys

    • 类型: boolean
    • 修饰符: private final
    • 源码定位: L29
    • 说明:

      TODO

  • indentDepth

    • 类型: int
    • 修饰符: private
    • 源码定位: L30
    • 说明:

      TODO

  • depth

    • 类型: int
    • 修饰符: private
    • 源码定位: L31
    • 说明:

      TODO

  • result

    • 类型: MutableComponent
    • 修饰符: private final
    • 源码定位: L32
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.nbt.TextComponentTagVisitor.PlainStyling

    • 类型: class
    • 修饰符: public static
    • 源码定位: L309
    • 说明:

      TODO

  • net.minecraft.nbt.TextComponentTagVisitor.RichStyling

    • 类型: class
    • 修饰符: public static
    • 源码定位: L340
    • 说明:

      TODO

  • net.minecraft.nbt.TextComponentTagVisitor.Styling

    • 类型: interface
    • 修饰符: public
    • 源码定位: L389
    • 说明:

      TODO

  • net.minecraft.nbt.TextComponentTagVisitor.Token

    • 类型: enum
    • 修饰符: public static
    • 源码定位: L399
    • 说明:

      TODO

构造器

public TextComponentTagVisitor(String indentation) @ L34

  • 构造器名:TextComponentTagVisitor
  • 源码定位:L34
  • 修饰符:public

参数:

  • indentation: String

说明:

TODO

public TextComponentTagVisitor(String indentation, TextComponentTagVisitor.Styling styling) @ L38

  • 构造器名:TextComponentTagVisitor
  • 源码定位:L38
  • 修饰符:public

参数:

  • indentation: String
  • styling: TextComponentTagVisitor.Styling

说明:

TODO

public TextComponentTagVisitor(String indentation, TextComponentTagVisitor.Styling styling, boolean sortKeys) @ L42

  • 构造器名:TextComponentTagVisitor
  • 源码定位:L42
  • 修饰符:public

参数:

  • indentation: String
  • styling: TextComponentTagVisitor.Styling
  • sortKeys: boolean

说明:

TODO

方法

下面的方法块按源码顺序生成。

public Component visit(Tag tag) @ L48

  • 方法名:visit
  • 源码定位:L48
  • 返回类型:Component
  • 修饰符:public

参数:

  • tag: Tag

说明:

TODO

private TextComponentTagVisitor append(String string, Style style) @ L53

  • 方法名:append
  • 源码定位:L53
  • 返回类型:TextComponentTagVisitor
  • 修饰符:private

参数:

  • string: String
  • style: Style

说明:

TODO

private TextComponentTagVisitor append(Component component) @ L58

  • 方法名:append
  • 源码定位:L58
  • 返回类型:TextComponentTagVisitor
  • 修饰符:private

参数:

  • component: Component

说明:

TODO

private TextComponentTagVisitor append(TextComponentTagVisitor.Token token) @ L63

  • 方法名:append
  • 源码定位:L63
  • 返回类型:TextComponentTagVisitor
  • 修饰符:private

参数:

  • token: TextComponentTagVisitor.Token

说明:

TODO

public void visitString(StringTag tag) @ L68

  • 方法名:visitString
  • 源码定位:L68
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: StringTag

说明:

TODO

public void visitByte(ByteTag tag) @ L75

  • 方法名:visitByte
  • 源码定位:L75
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: ByteTag

说明:

TODO

public void visitShort(ShortTag tag) @ L80

  • 方法名:visitShort
  • 源码定位:L80
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: ShortTag

说明:

TODO

public void visitInt(IntTag tag) @ L85

  • 方法名:visitInt
  • 源码定位:L85
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: IntTag

说明:

TODO

public void visitLong(LongTag tag) @ L90

  • 方法名:visitLong
  • 源码定位:L90
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: LongTag

说明:

TODO

public void visitFloat(FloatTag tag) @ L95

  • 方法名:visitFloat
  • 源码定位:L95
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: FloatTag

说明:

TODO

public void visitDouble(DoubleTag tag) @ L100

  • 方法名:visitDouble
  • 源码定位:L100
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: DoubleTag

说明:

TODO

public void visitByteArray(ByteArrayTag tag) @ L105

  • 方法名:visitByteArray
  • 源码定位:L105
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: ByteArrayTag

说明:

TODO

public void visitIntArray(IntArrayTag tag) @ L126

  • 方法名:visitIntArray
  • 源码定位:L126
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: IntArrayTag

说明:

TODO

public void visitLongArray(LongArrayTag tag) @ L147

  • 方法名:visitLongArray
  • 源码定位:L147
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: LongArrayTag

说明:

TODO

private static boolean shouldWrapListElements(ListTag list) @ L168

  • 方法名:shouldWrapListElements
  • 源码定位:L168
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • list: ListTag

说明:

TODO

public void visitList(ListTag tag) @ L182

  • 方法名:visitList
  • 源码定位:L182
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: ListTag

说明:

TODO

public void visitCompound(CompoundTag tag) @ L229

  • 方法名:visitCompound
  • 源码定位:L229
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: CompoundTag

说明:

TODO

private void appendSubTag(Tag tag, boolean indent) @ L276

  • 方法名:appendSubTag
  • 源码定位:L276
  • 返回类型:void
  • 修饰符:private

参数:

  • tag: Tag
  • indent: boolean

说明:

TODO

private Component handleEscapePretty(String input) @ L294

  • 方法名:handleEscapePretty
  • 源码定位:L294
  • 返回类型:Component
  • 修饰符:private

参数:

  • input: String

说明:

TODO

public void visitEnd(EndTag tag) @ L305

  • 方法名:visitEnd
  • 源码定位:L305
  • 返回类型:void
  • 修饰符:public

参数:

  • tag: EndTag

说明:

TODO

代码

public class TextComponentTagVisitor implements TagVisitor {
    private static final Logger LOGGER = LogUtils.getLogger();
    private static final int INLINE_LIST_THRESHOLD = 8;
    private static final int MAX_DEPTH = 64;
    private static final int MAX_LENGTH = 128;
    private static final Pattern SIMPLE_VALUE = Pattern.compile("[A-Za-z0-9._+-]+");
    private static final Component NEWLINE = Component.literal("\n");
    private static final Component ELEMENT_SPACING = Component.literal(" ");
    private final String indentation;
    private final TextComponentTagVisitor.Styling styling;
    private final boolean sortKeys;
    private int indentDepth;
    private int depth;
    private final MutableComponent result = Component.empty();
 
    public TextComponentTagVisitor(String indentation) {
        this(indentation, TextComponentTagVisitor.RichStyling.INSTANCE);
    }
 
    public TextComponentTagVisitor(String indentation, TextComponentTagVisitor.Styling styling) {
        this(indentation, styling, LOGGER.isDebugEnabled());
    }
 
    public TextComponentTagVisitor(String indentation, TextComponentTagVisitor.Styling styling, boolean sortKeys) {
        this.indentation = indentation;
        this.styling = styling;
        this.sortKeys = sortKeys;
    }
 
    public Component visit(Tag tag) {
        tag.accept(this);
        return this.result;
    }
 
    private TextComponentTagVisitor append(String string, Style style) {
        this.result.append(Component.literal(string).withStyle(style));
        return this;
    }
 
    private TextComponentTagVisitor append(Component component) {
        this.result.append(component);
        return this;
    }
 
    private TextComponentTagVisitor append(TextComponentTagVisitor.Token token) {
        this.result.append(this.styling.token(token));
        return this;
    }
 
    @Override
    public void visitString(StringTag tag) {
        String quoted = StringTag.quoteAndEscape(tag.value());
        Component quote = Component.literal(quoted.substring(0, 1));
        this.append(quote).append(quoted.substring(1, quoted.length() - 1), this.styling.stringStyle()).append(quote);
    }
 
    @Override
    public void visitByte(ByteTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.BYTE_SUFFIX);
    }
 
    @Override
    public void visitShort(ShortTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.SHORT_SUFFIX);
    }
 
    @Override
    public void visitInt(IntTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle());
    }
 
    @Override
    public void visitLong(LongTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.LONG_SUFFIX);
    }
 
    @Override
    public void visitFloat(FloatTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.FLOAT_SUFFIX);
    }
 
    @Override
    public void visitDouble(DoubleTag tag) {
        this.append(String.valueOf(tag.value()), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.DOUBLE_SUFFIX);
    }
 
    @Override
    public void visitByteArray(ByteArrayTag tag) {
        this.append(TextComponentTagVisitor.Token.LIST_OPEN)
            .append(TextComponentTagVisitor.Token.BYTE_ARRAY_PREFIX)
            .append(TextComponentTagVisitor.Token.LIST_TYPE_SEPARATOR);
        byte[] data = tag.getAsByteArray();
 
        for (int i = 0; i < data.length && i < 128; i++) {
            this.append(ELEMENT_SPACING).append(String.valueOf(data[i]), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.BYTE_SUFFIX);
            if (i != data.length - 1) {
                this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR);
            }
        }
 
        if (data.length > 128) {
            this.append(TextComponentTagVisitor.Token.FOLDED);
        }
 
        this.append(TextComponentTagVisitor.Token.LIST_CLOSE);
    }
 
    @Override
    public void visitIntArray(IntArrayTag tag) {
        this.append(TextComponentTagVisitor.Token.LIST_OPEN)
            .append(TextComponentTagVisitor.Token.INT_ARRAY_PREFIX)
            .append(TextComponentTagVisitor.Token.LIST_TYPE_SEPARATOR);
        int[] data = tag.getAsIntArray();
 
        for (int i = 0; i < data.length && i < 128; i++) {
            this.append(ELEMENT_SPACING).append(String.valueOf(data[i]), this.styling.numberStyle());
            if (i != data.length - 1) {
                this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR);
            }
        }
 
        if (data.length > 128) {
            this.append(TextComponentTagVisitor.Token.FOLDED);
        }
 
        this.append(TextComponentTagVisitor.Token.LIST_CLOSE);
    }
 
    @Override
    public void visitLongArray(LongArrayTag tag) {
        this.append(TextComponentTagVisitor.Token.LIST_OPEN)
            .append(TextComponentTagVisitor.Token.LONG_ARRAY_PREFIX)
            .append(TextComponentTagVisitor.Token.LIST_TYPE_SEPARATOR);
        long[] data = tag.getAsLongArray();
 
        for (int i = 0; i < data.length && i < 128; i++) {
            this.append(ELEMENT_SPACING).append(String.valueOf(data[i]), this.styling.numberStyle()).append(TextComponentTagVisitor.Token.LONG_SUFFIX);
            if (i != data.length - 1) {
                this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR);
            }
        }
 
        if (data.length > 128) {
            this.append(TextComponentTagVisitor.Token.FOLDED);
        }
 
        this.append(TextComponentTagVisitor.Token.LIST_CLOSE);
    }
 
    private static boolean shouldWrapListElements(ListTag list) {
        if (list.size() >= 8) {
            return false;
        } else {
            for (Tag element : list) {
                if (!(element instanceof NumericTag)) {
                    return true;
                }
            }
 
            return false;
        }
    }
 
    @Override
    public void visitList(ListTag tag) {
        if (tag.isEmpty()) {
            this.append(TextComponentTagVisitor.Token.LIST_OPEN).append(TextComponentTagVisitor.Token.LIST_CLOSE);
        } else if (this.depth >= 64) {
            this.append(TextComponentTagVisitor.Token.LIST_OPEN).append(TextComponentTagVisitor.Token.FOLDED).append(TextComponentTagVisitor.Token.LIST_CLOSE);
        } else if (!shouldWrapListElements(tag)) {
            this.append(TextComponentTagVisitor.Token.LIST_OPEN);
 
            for (int i = 0; i < tag.size(); i++) {
                if (i != 0) {
                    this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR).append(ELEMENT_SPACING);
                }
 
                this.appendSubTag(tag.get(i), false);
            }
 
            this.append(TextComponentTagVisitor.Token.LIST_CLOSE);
        } else {
            this.append(TextComponentTagVisitor.Token.LIST_OPEN);
            if (!this.indentation.isEmpty()) {
                this.append(NEWLINE);
            }
 
            Component entryIndent = Component.literal(this.indentation.repeat(this.indentDepth + 1));
            Component elementSpacing = this.indentation.isEmpty() ? ELEMENT_SPACING : NEWLINE;
 
            for (int i = 0; i < tag.size() && i < 128; i++) {
                this.append(entryIndent);
                this.appendSubTag(tag.get(i), true);
                if (i != tag.size() - 1) {
                    this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR).append(elementSpacing);
                }
            }
 
            if (tag.size() > 128) {
                this.append(entryIndent).append(TextComponentTagVisitor.Token.FOLDED);
            }
 
            if (!this.indentation.isEmpty()) {
                this.append(NEWLINE).append(Component.literal(this.indentation.repeat(this.indentDepth)));
            }
 
            this.append(TextComponentTagVisitor.Token.LIST_CLOSE);
        }
    }
 
    @Override
    public void visitCompound(CompoundTag tag) {
        if (tag.isEmpty()) {
            this.append(TextComponentTagVisitor.Token.STRUCT_OPEN).append(TextComponentTagVisitor.Token.STRUCT_CLOSE);
        } else if (this.depth >= 64) {
            this.append(TextComponentTagVisitor.Token.STRUCT_OPEN)
                .append(TextComponentTagVisitor.Token.FOLDED)
                .append(TextComponentTagVisitor.Token.STRUCT_CLOSE);
        } else {
            this.append(TextComponentTagVisitor.Token.STRUCT_OPEN);
            Collection<String> keys;
            if (this.sortKeys) {
                List<String> keyCopy = new ArrayList<>(tag.keySet());
                Collections.sort(keyCopy);
                keys = keyCopy;
            } else {
                keys = tag.keySet();
            }
 
            if (!this.indentation.isEmpty()) {
                this.append(NEWLINE);
            }
 
            Component entryIndent = Component.literal(this.indentation.repeat(this.indentDepth + 1));
            Component elementSpacing = this.indentation.isEmpty() ? ELEMENT_SPACING : NEWLINE;
            Iterator<String> iterator = keys.iterator();
 
            while (iterator.hasNext()) {
                String key = iterator.next();
                this.append(entryIndent)
                    .append(this.handleEscapePretty(key))
                    .append(TextComponentTagVisitor.Token.NAME_VALUE_SEPARATOR)
                    .append(ELEMENT_SPACING);
                this.appendSubTag(tag.get(key), true);
                if (iterator.hasNext()) {
                    this.append(TextComponentTagVisitor.Token.ELEMENT_SEPARATOR).append(elementSpacing);
                }
            }
 
            if (!this.indentation.isEmpty()) {
                this.append(NEWLINE).append(Component.literal(this.indentation.repeat(this.indentDepth)));
            }
 
            this.append(TextComponentTagVisitor.Token.STRUCT_CLOSE);
        }
    }
 
    private void appendSubTag(Tag tag, boolean indent) {
        if (indent) {
            this.indentDepth++;
        }
 
        this.depth++;
 
        try {
            tag.accept(this);
        } finally {
            if (indent) {
                this.indentDepth--;
            }
 
            this.depth--;
        }
    }
 
    private Component handleEscapePretty(String input) {
        if (SIMPLE_VALUE.matcher(input).matches()) {
            return Component.literal(input).withStyle(this.styling.keyStyle());
        } else {
            String quoted = StringTag.quoteAndEscape(input);
            String quote = quoted.substring(0, 1);
            Component inner = Component.literal(quoted.substring(1, quoted.length() - 1)).withStyle(this.styling.keyStyle());
            return Component.literal(quote).append(inner).append(quote);
        }
    }
 
    @Override
    public void visitEnd(EndTag tag) {
    }
 
    public static class PlainStyling implements TextComponentTagVisitor.Styling {
        public static final TextComponentTagVisitor.Styling INSTANCE = new TextComponentTagVisitor.PlainStyling();
        private final Map<TextComponentTagVisitor.Token, Component> tokens = new HashMap<>();
 
        private PlainStyling() {
            for (TextComponentTagVisitor.Token value : TextComponentTagVisitor.Token.values()) {
                this.tokens.put(value, Component.literal(value.text));
            }
        }
 
        @Override
        public Style keyStyle() {
            return Style.EMPTY;
        }
 
        @Override
        public Style stringStyle() {
            return Style.EMPTY;
        }
 
        @Override
        public Style numberStyle() {
            return Style.EMPTY;
        }
 
        @Override
        public Component token(TextComponentTagVisitor.Token token) {
            return Objects.requireNonNull(this.tokens.get(token));
        }
    }
 
    public static class RichStyling implements TextComponentTagVisitor.Styling {
        private static final Style SYNTAX_HIGHLIGHTING_NUMBER_TYPE = Style.EMPTY.withColor(ChatFormatting.RED);
        public static final TextComponentTagVisitor.Styling INSTANCE = new TextComponentTagVisitor.RichStyling();
        private final Map<TextComponentTagVisitor.Token, Component> tokens = new HashMap<>();
        private static final Style SYNTAX_HIGHLIGHTING_KEY = Style.EMPTY.withColor(ChatFormatting.AQUA);
        private static final Style SYNTAX_HIGHLIGHTING_STRING = Style.EMPTY.withColor(ChatFormatting.GREEN);
        private static final Style SYNTAX_HIGHLIGHTING_NUMBER = Style.EMPTY.withColor(ChatFormatting.GOLD);
 
        private RichStyling() {
            this.overrideToken(TextComponentTagVisitor.Token.FOLDED, Style.EMPTY.withColor(ChatFormatting.GRAY));
            this.overrideToken(TextComponentTagVisitor.Token.BYTE_SUFFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.BYTE_ARRAY_PREFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.SHORT_SUFFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.INT_ARRAY_PREFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.LONG_SUFFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.LONG_ARRAY_PREFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.FLOAT_SUFFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
            this.overrideToken(TextComponentTagVisitor.Token.DOUBLE_SUFFIX, SYNTAX_HIGHLIGHTING_NUMBER_TYPE);
 
            for (TextComponentTagVisitor.Token value : TextComponentTagVisitor.Token.values()) {
                this.tokens.putIfAbsent(value, Component.literal(value.text));
            }
        }
 
        private void overrideToken(TextComponentTagVisitor.Token token, Style style) {
            this.tokens.put(token, Component.literal(token.text).withStyle(style));
        }
 
        @Override
        public Style keyStyle() {
            return SYNTAX_HIGHLIGHTING_KEY;
        }
 
        @Override
        public Style stringStyle() {
            return SYNTAX_HIGHLIGHTING_STRING;
        }
 
        @Override
        public Style numberStyle() {
            return SYNTAX_HIGHLIGHTING_NUMBER;
        }
 
        @Override
        public Component token(TextComponentTagVisitor.Token token) {
            return Objects.requireNonNull(this.tokens.get(token));
        }
    }
 
    public interface Styling {
        Style keyStyle();
 
        Style stringStyle();
 
        Style numberStyle();
 
        Component token(final TextComponentTagVisitor.Token token);
    }
 
    public static enum Token {
        FOLDED("<...>"),
        ELEMENT_SEPARATOR(","),
        LIST_CLOSE("]"),
        LIST_OPEN("["),
        LIST_TYPE_SEPARATOR(";"),
        STRUCT_CLOSE("}"),
        STRUCT_OPEN("{"),
        NAME_VALUE_SEPARATOR(":"),
        BYTE_SUFFIX("b"),
        BYTE_ARRAY_PREFIX("B"),
        SHORT_SUFFIX("s"),
        INT_ARRAY_PREFIX("I"),
        LONG_SUFFIX("L"),
        LONG_ARRAY_PREFIX("L"),
        FLOAT_SUFFIX("f"),
        DOUBLE_SUFFIX("d");
 
        public final String text;
 
        private Token(String text) {
            this.text = text;
        }
    }
}

引用的其他类