ComponentSerialization.java

net.minecraft.network.chat.ComponentSerialization

信息

  • 全限定名:net.minecraft.network.chat.ComponentSerialization
  • 类型:public class
  • 包:net.minecraft.network.chat
  • 源码路径:src/main/java/net/minecraft/network/chat/ComponentSerialization.java
  • 起始行号:L36
  • 职责:

    TODO

字段/常量

  • CODEC

    • 类型: Codec<Component>
    • 修饰符: public static final
    • 源码定位: L37
    • 说明:

      TODO

  • STREAM_CODEC

    • 类型: StreamCodec<RegistryFriendlyByteBuf,Component>
    • 修饰符: public static final
    • 源码定位: L38
    • 说明:

      TODO

  • OPTIONAL_STREAM_CODEC

    • 类型: StreamCodec<RegistryFriendlyByteBuf,Optional<Component>>
    • 修饰符: public static final
    • 源码定位: L39
    • 说明:

      TODO

  • TRUSTED_STREAM_CODEC

    • 类型: StreamCodec<RegistryFriendlyByteBuf,Component>
    • 修饰符: public static final
    • 源码定位: L40
    • 说明:

      TODO

  • TRUSTED_OPTIONAL_STREAM_CODEC

    • 类型: StreamCodec<RegistryFriendlyByteBuf,Optional<Component>>
    • 修饰符: public static final
    • 源码定位: L41
    • 说明:

      TODO

  • TRUSTED_CONTEXT_FREE_STREAM_CODEC

    • 类型: StreamCodec<ByteBuf,Component>
    • 修饰符: public static final
    • 源码定位: L44
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.network.chat.ComponentSerialization.FuzzyCodec

    • 类型: class
    • 修饰符: private static
    • 源码定位: L127
    • 说明:

      TODO

  • net.minecraft.network.chat.ComponentSerialization.StrictEither

    • 类型: class
    • 修饰符: private static
    • 源码定位: L165
    • 说明:

      TODO

构造器

方法

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

public static Codec<Component> flatRestrictedCodec(int maxFlatSize) @ L46

  • 方法名:flatRestrictedCodec
  • 源码定位:L46
  • 返回类型:Codec
  • 修饰符:public static

参数:

  • maxFlatSize: int

说明:

TODO

private static MutableComponent createFromList(List<Component> list) @ L74

  • 方法名:createFromList
  • 源码定位:L74
  • 返回类型:MutableComponent
  • 修饰符:private static

参数:

  • list: List

说明:

TODO

public static <T> MapCodec<T> createLegacyComponentMatcher(ExtraCodecs.LateBoundIdMapper<String,MapCodec<?extends T>> types, Function<T,MapCodec<?extends T>> codecGetter, String typeFieldName) @ L84

  • 方法名:createLegacyComponentMatcher
  • 源码定位:L84
  • 返回类型: MapCodec
  • 修饰符:public static

参数:

  • types: ExtraCodecs.LateBoundIdMapper<String,MapCodec<?extends T>>
  • codecGetter: Function<T,MapCodec<?extends T>>
  • typeFieldName: String

说明:

TODO

private static Codec<Component> createCodec(Codec<Component> topSerializer) @ L93

  • 方法名:createCodec
  • 源码定位:L93
  • 返回类型:Codec
  • 修饰符:private static

参数:

  • topSerializer: Codec

说明:

TODO

private static void bootstrap(ExtraCodecs.LateBoundIdMapper<String,MapCodec<?extends ComponentContents>> contentTypes) @ L117

  • 方法名:bootstrap
  • 源码定位:L117
  • 返回类型:void
  • 修饰符:private static

参数:

  • contentTypes: ExtraCodecs.LateBoundIdMapper<String,MapCodec<?extends ComponentContents>>

说明:

TODO

代码

public class ComponentSerialization {
    public static final Codec<Component> CODEC = Codec.recursive("Component", ComponentSerialization::createCodec);
    public static final StreamCodec<RegistryFriendlyByteBuf, Component> STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC);
    public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> OPTIONAL_STREAM_CODEC = STREAM_CODEC.apply(ByteBufCodecs::optional);
    public static final StreamCodec<RegistryFriendlyByteBuf, Component> TRUSTED_STREAM_CODEC = ByteBufCodecs.fromCodecWithRegistriesTrusted(CODEC);
    public static final StreamCodec<RegistryFriendlyByteBuf, Optional<Component>> TRUSTED_OPTIONAL_STREAM_CODEC = TRUSTED_STREAM_CODEC.apply(
        ByteBufCodecs::optional
    );
    public static final StreamCodec<ByteBuf, Component> TRUSTED_CONTEXT_FREE_STREAM_CODEC = ByteBufCodecs.fromCodecTrusted(CODEC);
 
    public static Codec<Component> flatRestrictedCodec(int maxFlatSize) {
        return new Codec<Component>() {
            @Override
            public <T> DataResult<Pair<Component, T>> decode(DynamicOps<T> ops, T input) {
                return ComponentSerialization.CODEC
                    .decode(ops, input)
                    .flatMap(
                        pair -> this.isTooLarge(ops, pair.getFirst())
                            ? DataResult.error(() -> "Component was too large: greater than max size " + maxFlatSize)
                            : DataResult.success((Pair<Component, T>)pair)
                    );
            }
 
            public <T> DataResult<T> encode(Component input, DynamicOps<T> ops, T prefix) {
                return ComponentSerialization.CODEC.encodeStart(ops, input);
            }
 
            private <T> boolean isTooLarge(DynamicOps<T> ops, Component input) {
                DataResult<JsonElement> json = ComponentSerialization.CODEC.encodeStart(asJsonOps(ops), input);
                return json.isSuccess() && GsonHelper.encodesLongerThan(json.getOrThrow(), maxFlatSize);
            }
 
            private static <T> DynamicOps<JsonElement> asJsonOps(DynamicOps<T> ops) {
                return (DynamicOps<JsonElement>)(ops instanceof RegistryOps<T> registryOps ? registryOps.withParent(JsonOps.INSTANCE) : JsonOps.INSTANCE);
            }
        };
    }
 
    private static MutableComponent createFromList(List<Component> list) {
        MutableComponent result = list.get(0).copy();
 
        for (int i = 1; i < list.size(); i++) {
            result.append(list.get(i));
        }
 
        return result;
    }
 
    public static <T> MapCodec<T> createLegacyComponentMatcher(
        ExtraCodecs.LateBoundIdMapper<String, MapCodec<? extends T>> types, Function<T, MapCodec<? extends T>> codecGetter, String typeFieldName
    ) {
        MapCodec<T> compactCodec = new ComponentSerialization.FuzzyCodec<>(types.values(), codecGetter);
        MapCodec<T> discriminatorCodec = types.codec(Codec.STRING).dispatchMap(typeFieldName, codecGetter, c -> c);
        MapCodec<T> contentsCodec = new ComponentSerialization.StrictEither<>(typeFieldName, discriminatorCodec, compactCodec);
        return ExtraCodecs.orCompressed(contentsCodec, discriminatorCodec);
    }
 
    private static Codec<Component> createCodec(Codec<Component> topSerializer) {
        ExtraCodecs.LateBoundIdMapper<String, MapCodec<? extends ComponentContents>> contentTypes = new ExtraCodecs.LateBoundIdMapper<>();
        bootstrap(contentTypes);
        MapCodec<ComponentContents> compressedContentsCodec = createLegacyComponentMatcher(contentTypes, ComponentContents::codec, "type");
        Codec<Component> fullCodec = RecordCodecBuilder.create(
            i -> i.group(
                    compressedContentsCodec.forGetter(Component::getContents),
                    ExtraCodecs.nonEmptyList(topSerializer.listOf()).optionalFieldOf("extra", List.of()).forGetter(Component::getSiblings),
                    Style.Serializer.MAP_CODEC.forGetter(Component::getStyle)
                )
                .apply(i, MutableComponent::new)
        );
        return Codec.either(Codec.either(Codec.STRING, ExtraCodecs.nonEmptyList(topSerializer.listOf())), fullCodec)
            .xmap(
                specialOrComponent -> specialOrComponent.map(
                    special -> special.map(Component::literal, ComponentSerialization::createFromList), c -> (Component)c
                ),
                component -> {
                    String text = component.tryCollapseToString();
                    return text != null ? Either.left(Either.left(text)) : Either.right(component);
                }
            );
    }
 
    private static void bootstrap(ExtraCodecs.LateBoundIdMapper<String, MapCodec<? extends ComponentContents>> contentTypes) {
        contentTypes.put("text", PlainTextContents.MAP_CODEC);
        contentTypes.put("translatable", TranslatableContents.MAP_CODEC);
        contentTypes.put("keybind", KeybindContents.MAP_CODEC);
        contentTypes.put("score", ScoreContents.MAP_CODEC);
        contentTypes.put("selector", SelectorContents.MAP_CODEC);
        contentTypes.put("nbt", NbtContents.MAP_CODEC);
        contentTypes.put("object", ObjectContents.MAP_CODEC);
    }
 
    private static class FuzzyCodec<T> extends MapCodec<T> {
        private final Collection<MapCodec<? extends T>> codecs;
        private final Function<T, ? extends MapEncoder<? extends T>> encoderGetter;
 
        public FuzzyCodec(Collection<MapCodec<? extends T>> codecs, Function<T, ? extends MapEncoder<? extends T>> encoderGetter) {
            this.codecs = codecs;
            this.encoderGetter = encoderGetter;
        }
 
        @Override
        public <S> DataResult<T> decode(DynamicOps<S> ops, MapLike<S> input) {
            for (MapDecoder<? extends T> codec : this.codecs) {
                DataResult<? extends T> result = codec.decode(ops, input);
                if (result.result().isPresent()) {
                    return (DataResult<T>)result;
                }
            }
 
            return DataResult.error(() -> "No matching codec found");
        }
 
        @Override
        public <S> RecordBuilder<S> encode(T input, DynamicOps<S> ops, RecordBuilder<S> prefix) {
            MapEncoder<T> encoder = (MapEncoder<T>)this.encoderGetter.apply(input);
            return encoder.encode(input, ops, prefix);
        }
 
        @Override
        public <S> Stream<S> keys(DynamicOps<S> ops) {
            return this.codecs.stream().flatMap(c -> c.keys(ops)).distinct();
        }
 
        @Override
        public String toString() {
            return "FuzzyCodec[" + this.codecs + "]";
        }
    }
 
    private static class StrictEither<T> extends MapCodec<T> {
        private final String typeFieldName;
        private final MapCodec<T> typed;
        private final MapCodec<T> fuzzy;
 
        public StrictEither(String typeFieldName, MapCodec<T> typed, MapCodec<T> fuzzy) {
            this.typeFieldName = typeFieldName;
            this.typed = typed;
            this.fuzzy = fuzzy;
        }
 
        @Override
        public <O> DataResult<T> decode(DynamicOps<O> ops, MapLike<O> input) {
            return input.get(this.typeFieldName) != null ? this.typed.decode(ops, input) : this.fuzzy.decode(ops, input);
        }
 
        @Override
        public <O> RecordBuilder<O> encode(T input, DynamicOps<O> ops, RecordBuilder<O> prefix) {
            return this.fuzzy.encode(input, ops, prefix);
        }
 
        @Override
        public <T1> Stream<T1> keys(DynamicOps<T1> ops) {
            return Stream.concat(this.typed.keys(ops), this.fuzzy.keys(ops)).distinct();
        }
    }
}

引用的其他类

  • RegistryFriendlyByteBuf

    • 引用位置: 字段
  • Component

    • 引用位置: 参数/字段/返回值
  • ComponentContents

    • 引用位置: 参数
  • MutableComponent

    • 引用位置: 返回值
  • ByteBufCodecs

    • 引用位置: 方法调用
    • 关联成员: ByteBufCodecs.fromCodecTrusted(), ByteBufCodecs.fromCodecWithRegistries(), ByteBufCodecs.fromCodecWithRegistriesTrusted()
  • StreamCodec

    • 引用位置: 字段
  • ExtraCodecs

    • 引用位置: 参数/方法调用
    • 关联成员: ExtraCodecs.nonEmptyList(), ExtraCodecs.orCompressed()
  • GsonHelper

    • 引用位置: 方法调用
    • 关联成员: GsonHelper.encodesLongerThan()