DataComponentPatch.java

net.minecraft.core.component.DataComponentPatch

信息

  • 全限定名:net.minecraft.core.component.DataComponentPatch
  • 类型:public final class
  • 包:net.minecraft.core.component
  • 源码路径:src/main/java/net/minecraft/core/component/DataComponentPatch.java
  • 起始行号:L21
  • 职责:

    TODO

字段/常量

  • EMPTY

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

      TODO

  • CODEC

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

      TODO

  • STREAM_CODEC

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

      TODO

  • DELIMITED_STREAM_CODEC

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

      TODO

  • REMOVED_PREFIX

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

      TODO

  • map

    • 类型: Reference2ObjectMap<DataComponentType<?>,Optional<?>>
    • 修饰符: final
    • 源码定位: L74
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.core.component.DataComponentPatch.Builder

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

      TODO

  • net.minecraft.core.component.DataComponentPatch.CodecGetter

    • 类型: interface
    • 修饰符: private
    • 源码定位: L285
    • 说明:

      TODO

  • net.minecraft.core.component.DataComponentPatch.PatchKey

    • 类型: record
    • 修饰符: private
    • 源码定位: L289
    • 说明:

      TODO

  • net.minecraft.core.component.DataComponentPatch.SplitResult

    • 类型: record
    • 修饰符: public
    • 源码定位: L322
    • 说明:

      TODO

构造器

DataComponentPatch(Reference2ObjectMap<DataComponentType<?>,Optional<?>> map) @ L151

  • 构造器名:DataComponentPatch
  • 源码定位:L151
  • 修饰符:package-private

参数:

  • map: Reference2ObjectMap<DataComponentType,Optional>

说明:

TODO

方法

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

private static StreamCodec<RegistryFriendlyByteBuf,DataComponentPatch> createStreamCodec(DataComponentPatch.CodecGetter codecGetter) @ L76

  • 方法名:createStreamCodec
  • 源码定位:L76
  • 返回类型:StreamCodec<RegistryFriendlyByteBuf,DataComponentPatch>
  • 修饰符:private static

参数:

  • codecGetter: DataComponentPatch.CodecGetter

说明:

TODO

public static DataComponentPatch.Builder builder() @ L155

  • 方法名:builder
  • 源码定位:L155
  • 返回类型:DataComponentPatch.Builder
  • 修饰符:public static

参数:

说明:

TODO

public <T> T get(DataComponentGetter prototype, DataComponentType<?extends T> type) @ L159

  • 方法名:get
  • 源码定位:L159
  • 返回类型: T
  • 修饰符:public

参数:

  • prototype: DataComponentGetter
  • type: DataComponentType<?extends T>

说明:

TODO

static <T> T getFromPatchAndPrototype(Reference2ObjectMap<DataComponentType<?>,Optional<?>> patch, DataComponentGetter prototype, DataComponentType<?extends T> type) @ L163

  • 方法名:getFromPatchAndPrototype
  • 源码定位:L163
  • 返回类型: T
  • 修饰符:static

参数:

  • patch: Reference2ObjectMap<DataComponentType,Optional>
  • prototype: DataComponentGetter
  • type: DataComponentType<?extends T>

说明:

TODO

public Set<Entry<DataComponentType<?>,Optional<?>>> entrySet() @ L170

  • 方法名:entrySet
  • 源码定位:L170
  • 返回类型:Set<Entry<DataComponentType,Optional>>
  • 修饰符:public

参数:

说明:

TODO

public int size() @ L174

  • 方法名:size
  • 源码定位:L174
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public DataComponentPatch forget(Predicate<DataComponentType<?>> test) @ L178

  • 方法名:forget
  • 源码定位:L178
  • 返回类型:DataComponentPatch
  • 修饰符:public

参数:

  • test: Predicate<DataComponentType<?>>

说明:

TODO

public boolean isEmpty() @ L188

  • 方法名:isEmpty
  • 源码定位:L188
  • 返回类型:boolean
  • 修饰符:public

参数:

说明:

TODO

public DataComponentPatch.SplitResult split() @ L192

  • 方法名:split
  • 源码定位:L192
  • 返回类型:DataComponentPatch.SplitResult
  • 修饰符:public

参数:

说明:

TODO

public boolean equals(Object obj) @ L209

  • 方法名:equals
  • 源码定位:L209
  • 返回类型:boolean
  • 修饰符:public

参数:

  • obj: Object

说明:

TODO

public int hashCode() @ L214

  • 方法名:hashCode
  • 源码定位:L214
  • 返回类型:int
  • 修饰符:public

参数:

说明:

TODO

public String toString() @ L219

  • 方法名:toString
  • 源码定位:L219
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

static String toString(Reference2ObjectMap<DataComponentType<?>,Optional<?>> map) @ L224

  • 方法名:toString
  • 源码定位:L224
  • 返回类型:String
  • 修饰符:static

参数:

  • map: Reference2ObjectMap<DataComponentType,Optional>

说明:

TODO

代码

public final class DataComponentPatch {
    public static final DataComponentPatch EMPTY = new DataComponentPatch(Reference2ObjectMaps.emptyMap());
    public static final Codec<DataComponentPatch> CODEC = Codec.<DataComponentPatch.PatchKey, Object>dispatchedMap(DataComponentPatch.PatchKey.CODEC, DataComponentPatch.PatchKey::valueCodec)
        .xmap(data -> {
            if (data.isEmpty()) {
                return EMPTY;
            } else {
                Reference2ObjectMap<DataComponentType<?>, Optional<?>> map = new Reference2ObjectArrayMap<>(data.size());
 
                for (Entry<DataComponentPatch.PatchKey, ?> entry : data.entrySet()) {
                    DataComponentPatch.PatchKey key = entry.getKey();
                    if (key.removed()) {
                        map.put(key.type(), Optional.empty());
                    } else {
                        map.put(key.type(), Optional.of(entry.getValue()));
                    }
                }
 
                return new DataComponentPatch(map);
            }
        }, patch -> {
            Reference2ObjectMap<DataComponentPatch.PatchKey, Object> map = new Reference2ObjectArrayMap<>(patch.map.size());
 
            for (Entry<DataComponentType<?>, Optional<?>> entry : Reference2ObjectMaps.fastIterable(patch.map)) {
                DataComponentType<?> type = entry.getKey();
                if (!type.isTransient()) {
                    Optional<?> value = entry.getValue();
                    if (value.isPresent()) {
                        map.put(new DataComponentPatch.PatchKey(type, false), value.get());
                    } else {
                        map.put(new DataComponentPatch.PatchKey(type, true), Unit.INSTANCE);
                    }
                }
            }
 
            return map;
        });
    public static final StreamCodec<RegistryFriendlyByteBuf, DataComponentPatch> STREAM_CODEC = createStreamCodec(new DataComponentPatch.CodecGetter() {
        @Override
        public <T> StreamCodec<RegistryFriendlyByteBuf, T> apply(DataComponentType<T> type) {
            return type.streamCodec().cast();
        }
    });
    public static final StreamCodec<RegistryFriendlyByteBuf, DataComponentPatch> DELIMITED_STREAM_CODEC = createStreamCodec(
        new DataComponentPatch.CodecGetter() {
            @Override
            public <T> StreamCodec<RegistryFriendlyByteBuf, T> apply(DataComponentType<T> type) {
                StreamCodec<RegistryFriendlyByteBuf, T> original = type.streamCodec().cast();
                return original.apply(ByteBufCodecs.registryFriendlyLengthPrefixed(Integer.MAX_VALUE));
            }
        }
    );
    private static final String REMOVED_PREFIX = "!";
    final Reference2ObjectMap<DataComponentType<?>, Optional<?>> map;
 
    private static StreamCodec<RegistryFriendlyByteBuf, DataComponentPatch> createStreamCodec(DataComponentPatch.CodecGetter codecGetter) {
        return new StreamCodec<RegistryFriendlyByteBuf, DataComponentPatch>() {
            public DataComponentPatch decode(RegistryFriendlyByteBuf input) {
                int positiveCount = input.readVarInt();
                int negativeCount = input.readVarInt();
                if (positiveCount == 0 && negativeCount == 0) {
                    return DataComponentPatch.EMPTY;
                } else {
                    int expectedSize = positiveCount + negativeCount;
                    Reference2ObjectMap<DataComponentType<?>, Optional<?>> map = new Reference2ObjectArrayMap<>(Math.min(expectedSize, 65536));
 
                    for (int i = 0; i < positiveCount; i++) {
                        DataComponentType<?> type = DataComponentType.STREAM_CODEC.decode(input);
                        Object value = codecGetter.apply(type).decode(input);
                        map.put(type, Optional.of(value));
                    }
 
                    for (int i = 0; i < negativeCount; i++) {
                        DataComponentType<?> type = DataComponentType.STREAM_CODEC.decode(input);
                        map.put(type, Optional.empty());
                    }
 
                    return new DataComponentPatch(map);
                }
            }
 
            public void encode(RegistryFriendlyByteBuf output, DataComponentPatch patch) {
                if (patch.isEmpty()) {
                    output.writeVarInt(0);
                    output.writeVarInt(0);
                } else {
                    int positiveCount = 0;
                    int negativeCount = 0;
 
                    for (it.unimi.dsi.fastutil.objects.Reference2ObjectMap.Entry<DataComponentType<?>, Optional<?>> entry : Reference2ObjectMaps.fastIterable(
                        patch.map
                    )) {
                        if (entry.getValue().isPresent()) {
                            positiveCount++;
                        } else {
                            negativeCount++;
                        }
                    }
 
                    output.writeVarInt(positiveCount);
                    output.writeVarInt(negativeCount);
 
                    for (it.unimi.dsi.fastutil.objects.Reference2ObjectMap.Entry<DataComponentType<?>, Optional<?>> entryx : Reference2ObjectMaps.fastIterable(
                        patch.map
                    )) {
                        Optional<?> value = entryx.getValue();
                        if (value.isPresent()) {
                            DataComponentType<?> type = entryx.getKey();
                            DataComponentType.STREAM_CODEC.encode(output, type);
                            this.encodeComponent(output, type, value.get());
                        }
                    }
 
                    for (it.unimi.dsi.fastutil.objects.Reference2ObjectMap.Entry<DataComponentType<?>, Optional<?>> entryxx : Reference2ObjectMaps.fastIterable(
                        patch.map
                    )) {
                        if (entryxx.getValue().isEmpty()) {
                            DataComponentType<?> type = entryxx.getKey();
                            DataComponentType.STREAM_CODEC.encode(output, type);
                        }
                    }
                }
            }
 
            private <T> void encodeComponent(RegistryFriendlyByteBuf output, DataComponentType<T> type, Object value) {
                codecGetter.apply(type).encode(output, (T)value);
            }
        };
    }
 
    DataComponentPatch(Reference2ObjectMap<DataComponentType<?>, Optional<?>> map) {
        this.map = map;
    }
 
    public static DataComponentPatch.Builder builder() {
        return new DataComponentPatch.Builder();
    }
 
    public <T> @Nullable T get(DataComponentGetter prototype, DataComponentType<? extends T> type) {
        return getFromPatchAndPrototype(this.map, prototype, type);
    }
 
    static <T> @Nullable T getFromPatchAndPrototype(
        Reference2ObjectMap<DataComponentType<?>, Optional<?>> patch, DataComponentGetter prototype, DataComponentType<? extends T> type
    ) {
        Optional<? extends T> value = (Optional<? extends T>)patch.get(type);
        return (T)(value != null ? value.orElse(null) : prototype.get(type));
    }
 
    public Set<Entry<DataComponentType<?>, Optional<?>>> entrySet() {
        return this.map.entrySet();
    }
 
    public int size() {
        return this.map.size();
    }
 
    public DataComponentPatch forget(Predicate<DataComponentType<?>> test) {
        if (this.isEmpty()) {
            return EMPTY;
        } else {
            Reference2ObjectMap<DataComponentType<?>, Optional<?>> newMap = new Reference2ObjectArrayMap<>(this.map);
            newMap.keySet().removeIf(test);
            return newMap.isEmpty() ? EMPTY : new DataComponentPatch(newMap);
        }
    }
 
    public boolean isEmpty() {
        return this.map.isEmpty();
    }
 
    public DataComponentPatch.SplitResult split() {
        if (this.isEmpty()) {
            return DataComponentPatch.SplitResult.EMPTY;
        } else {
            DataComponentMap.Builder added = DataComponentMap.builder();
            Set<DataComponentType<?>> removed = Sets.newIdentityHashSet();
            this.map.forEach((type, optionalValue) -> {
                if (optionalValue.isPresent()) {
                    added.setUnchecked((DataComponentType<?>)type, optionalValue.get());
                } else {
                    removed.add((DataComponentType<?>)type);
                }
            });
            return new DataComponentPatch.SplitResult(added.build(), removed);
        }
    }
 
    @Override
    public boolean equals(Object obj) {
        return this == obj ? true : obj instanceof DataComponentPatch patch && this.map.equals(patch.map);
    }
 
    @Override
    public int hashCode() {
        return this.map.hashCode();
    }
 
    @Override
    public String toString() {
        return toString(this.map);
    }
 
    static String toString(Reference2ObjectMap<DataComponentType<?>, Optional<?>> map) {
        StringBuilder builder = new StringBuilder();
        builder.append('{');
        boolean first = true;
 
        for (Entry<DataComponentType<?>, Optional<?>> entry : Reference2ObjectMaps.fastIterable(map)) {
            if (first) {
                first = false;
            } else {
                builder.append(", ");
            }
 
            Optional<?> value = entry.getValue();
            if (value.isPresent()) {
                builder.append(entry.getKey());
                builder.append("=>");
                builder.append(value.get());
            } else {
                builder.append("!");
                builder.append(entry.getKey());
            }
        }
 
        builder.append('}');
        return builder.toString();
    }
 
    public static class Builder {
        private final Reference2ObjectMap<DataComponentType<?>, Optional<?>> map = new Reference2ObjectArrayMap<>();
 
        private Builder() {
        }
 
        public <T> DataComponentPatch.Builder set(DataComponentType<T> type, T value) {
            this.map.put(type, Optional.of(value));
            return this;
        }
 
        public <T> DataComponentPatch.Builder remove(DataComponentType<T> type) {
            this.map.put(type, Optional.empty());
            return this;
        }
 
        public <T> DataComponentPatch.Builder set(TypedDataComponent<T> component) {
            return this.set(component.type(), component.value());
        }
 
        public <T> DataComponentPatch.Builder set(Iterable<TypedDataComponent<?>> components) {
            for (TypedDataComponent<?> component : components) {
                this.set(component);
            }
 
            return this;
        }
 
        public DataComponentPatch build() {
            return this.map.isEmpty() ? DataComponentPatch.EMPTY : new DataComponentPatch(this.map);
        }
    }
 
    @FunctionalInterface
    private interface CodecGetter {
        <T> StreamCodec<? super RegistryFriendlyByteBuf, T> apply(DataComponentType<T> type);
    }
 
    private record PatchKey(DataComponentType<?> type, boolean removed) {
        public static final Codec<DataComponentPatch.PatchKey> CODEC = Codec.STRING
            .flatXmap(
                string -> {
                    boolean removed = string.startsWith("!");
                    if (removed) {
                        string = string.substring("!".length());
                    }
 
                    Identifier id = Identifier.tryParse(string);
                    DataComponentType<?> type = BuiltInRegistries.DATA_COMPONENT_TYPE.getValue(id);
                    if (type == null) {
                        return DataResult.error(() -> "No component with type: '" + id + "'");
                    } else {
                        return type.isTransient()
                            ? DataResult.error(() -> "'" + id + "' is not a persistent component")
                            : DataResult.success(new DataComponentPatch.PatchKey(type, removed));
                    }
                },
                key -> {
                    DataComponentType<?> type = key.type();
                    Identifier id = BuiltInRegistries.DATA_COMPONENT_TYPE.getKey(type);
                    return id == null
                        ? DataResult.error(() -> "Unregistered component: " + type)
                        : DataResult.success(key.removed() ? "!" + id : id.toString());
                }
            );
 
        public Codec<?> valueCodec() {
            return this.removed ? Codec.EMPTY.codec() : this.type.codecOrThrow();
        }
    }
 
    public record SplitResult(DataComponentMap added, Set<DataComponentType<?>> removed) {
        public static final DataComponentPatch.SplitResult EMPTY = new DataComponentPatch.SplitResult(DataComponentMap.EMPTY, Set.of());
    }
}

引用的其他类