MappedRegistry.java

net.minecraft.core.MappedRegistry

信息

  • 全限定名:net.minecraft.core.MappedRegistry
  • 类型:public class
  • 包:net.minecraft.core
  • 源码路径:src/main/java/net/minecraft/core/MappedRegistry.java
  • 起始行号:L33
  • 实现:WritableRegistry
  • 职责:

    TODO

字段/常量

  • key

    • 类型: ResourceKey<?extends Registry<T>>
    • 修饰符: private final
    • 源码定位: L34
    • 说明:

      TODO

  • byId

    • 类型: ObjectList<Holder.Reference<T>>
    • 修饰符: private final
    • 源码定位: L35
    • 说明:

      TODO

  • toId

    • 类型: Reference2IntMap<T>
    • 修饰符: private final
    • 源码定位: L36
    • 说明:

      TODO

  • byLocation

    • 类型: Map<Identifier,Holder.Reference<T>>
    • 修饰符: private final
    • 源码定位: L37
    • 说明:

      TODO

  • byKey

    • 类型: Map<ResourceKey<T>,Holder.Reference<T>>
    • 修饰符: private final
    • 源码定位: L38
    • 说明:

      TODO

  • byValue

    • 类型: Map<T,Holder.Reference<T>>
    • 修饰符: private final
    • 源码定位: L39
    • 说明:

      TODO

  • registrationInfos

    • 类型: Map<ResourceKey<T>,RegistrationInfo>
    • 修饰符: private final
    • 源码定位: L40
    • 说明:

      TODO

  • registryLifecycle

    • 类型: Lifecycle
    • 修饰符: private
    • 源码定位: L41
    • 说明:

      TODO

  • frozenTags

    • 类型: Map<TagKey<T>,HolderSet.Named<T>>
    • 修饰符: private final
    • 源码定位: L42
    • 说明:

      TODO

  • allTags

    • 类型: MappedRegistry.TagSet<T>
    • 修饰符: private
    • 源码定位: L43
    • 说明:

      TODO

  • componentLookup

    • 类型: DataComponentLookup<T>
    • 修饰符: private
    • 源码定位: L44
    • 说明:

      TODO

  • frozen

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

      TODO

  • unregisteredIntrusiveHolders

    • 类型: Map<T,Holder.Reference<T>>
    • 修饰符: private
    • 源码定位: L46
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.core.MappedRegistry.TagSet
    • 类型: interface
    • 修饰符: private
    • 源码定位: L468
    • 说明:

      TODO

构造器

public MappedRegistry(ResourceKey<?extends Registry<T>> key, Lifecycle lifecycle) @ L53

  • 构造器名:MappedRegistry
  • 源码定位:L53
  • 修饰符:public

参数:

  • key: ResourceKey<?extends Registry>
  • lifecycle: Lifecycle

说明:

TODO

public MappedRegistry(ResourceKey<?extends Registry<T>> key, Lifecycle initialLifecycle, boolean intrusiveHolders) @ L57

  • 构造器名:MappedRegistry
  • 源码定位:L57
  • 修饰符:public

参数:

  • key: ResourceKey<?extends Registry>
  • initialLifecycle: Lifecycle
  • intrusiveHolders: boolean

说明:

TODO

方法

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

public Stream<HolderSet.Named<T>> listTags() @ L48

  • 方法名:listTags
  • 源码定位:L48
  • 返回类型:Stream<HolderSet.Named>
  • 修饰符:public

参数:

说明:

TODO

public ResourceKey<?extends Registry<T>> key() @ L65

  • 方法名:key
  • 源码定位:L65
  • 返回类型:ResourceKey<?extends Registry>
  • 修饰符:public

参数:

说明:

TODO

public String toString() @ L70

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

参数:

说明:

TODO

private void validateWrite() @ L75

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

参数:

说明:

TODO

private void validateWrite(ResourceKey<T> key) @ L81

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

参数:

  • key: ResourceKey

说明:

TODO

public Holder.Reference<T> register(ResourceKey<T> key, T value, RegistrationInfo registrationInfo) @ L87

  • 方法名:register
  • 源码定位:L87
  • 返回类型:Holder.Reference
  • 修饰符:public

参数:

  • key: ResourceKey
  • value: T
  • registrationInfo: RegistrationInfo

说明:

TODO

public Identifier getKey(T thing) @ L121

  • 方法名:getKey
  • 源码定位:L121
  • 返回类型:Identifier
  • 修饰符:public

参数:

  • thing: T

说明:

TODO

public Optional<ResourceKey<T>> getResourceKey(T thing) @ L127

  • 方法名:getResourceKey
  • 源码定位:L127
  • 返回类型:Optional<ResourceKey>
  • 修饰符:public

参数:

  • thing: T

说明:

TODO

public int getId(T thing) @ L132

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

参数:

  • thing: T

说明:

TODO

public T getValue(ResourceKey<T> key) @ L137

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

参数:

  • key: ResourceKey

说明:

TODO

public T byId(int id) @ L142

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

参数:

  • id: int

说明:

TODO

public Optional<Holder.Reference<T>> get(int id) @ L147

  • 方法名:get
  • 源码定位:L147
  • 返回类型:Optional<Holder.Reference>
  • 修饰符:public

参数:

  • id: int

说明:

TODO

public Optional<Holder.Reference<T>> get(Identifier id) @ L152

  • 方法名:get
  • 源码定位:L152
  • 返回类型:Optional<Holder.Reference>
  • 修饰符:public

参数:

  • id: Identifier

说明:

TODO

public Optional<Holder.Reference<T>> get(ResourceKey<T> id) @ L157

  • 方法名:get
  • 源码定位:L157
  • 返回类型:Optional<Holder.Reference>
  • 修饰符:public

参数:

  • id: ResourceKey

说明:

TODO

public Optional<Holder.Reference<T>> getAny() @ L162

  • 方法名:getAny
  • 源码定位:L162
  • 返回类型:Optional<Holder.Reference>
  • 修饰符:public

参数:

说明:

TODO

public Holder<T> wrapAsHolder(T value) @ L167

  • 方法名:wrapAsHolder
  • 源码定位:L167
  • 返回类型:Holder
  • 修饰符:public

参数:

  • value: T

说明:

TODO

private Holder.Reference<T> getOrCreateHolderOrThrow(ResourceKey<T> key) @ L173

  • 方法名:getOrCreateHolderOrThrow
  • 源码定位:L173
  • 返回类型:Holder.Reference
  • 修饰符:private

参数:

  • key: ResourceKey

说明:

TODO

public int size() @ L184

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

参数:

说明:

TODO

public Optional<RegistrationInfo> registrationInfo(ResourceKey<T> element) @ L189

  • 方法名:registrationInfo
  • 源码定位:L189
  • 返回类型:Optional
  • 修饰符:public

参数:

  • element: ResourceKey

说明:

TODO

public Lifecycle registryLifecycle() @ L194

  • 方法名:registryLifecycle
  • 源码定位:L194
  • 返回类型:Lifecycle
  • 修饰符:public

参数:

说明:

TODO

public Iterator<T> iterator() @ L199

  • 方法名:iterator
  • 源码定位:L199
  • 返回类型:Iterator
  • 修饰符:public

参数:

说明:

TODO

public T getValue(Identifier key) @ L204

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

参数:

  • key: Identifier

说明:

TODO

private static <T> T getValueFromNullable(Holder.Reference<T> result) @ L210

  • 方法名:getValueFromNullable
  • 源码定位:L210
  • 返回类型: T
  • 修饰符:private static

参数:

  • result: Holder.Reference

说明:

TODO

public Set<Identifier> keySet() @ L214

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

参数:

说明:

TODO

public Set<ResourceKey<T>> registryKeySet() @ L219

  • 方法名:registryKeySet
  • 源码定位:L219
  • 返回类型:Set<ResourceKey>
  • 修饰符:public

参数:

说明:

TODO

public Set<Entry<ResourceKey<T>,T>> entrySet() @ L224

  • 方法名:entrySet
  • 源码定位:L224
  • 返回类型:Set<Entry<ResourceKey,T>>
  • 修饰符:public

参数:

说明:

TODO

public Stream<Holder.Reference<T>> listElements() @ L229

  • 方法名:listElements
  • 源码定位:L229
  • 返回类型:Stream<Holder.Reference>
  • 修饰符:public

参数:

说明:

TODO

public Stream<HolderSet.Named<T>> getTags() @ L234

  • 方法名:getTags
  • 源码定位:L234
  • 返回类型:Stream<HolderSet.Named>
  • 修饰符:public

参数:

说明:

TODO

private HolderSet.Named<T> getOrCreateTagForRegistration(TagKey<T> tag) @ L239

  • 方法名:getOrCreateTagForRegistration
  • 源码定位:L239
  • 返回类型:HolderSet.Named
  • 修饰符:private

参数:

  • tag: TagKey

说明:

TODO

private HolderSet.Named<T> createTag(TagKey<T> tag) @ L243

  • 方法名:createTag
  • 源码定位:L243
  • 返回类型:HolderSet.Named
  • 修饰符:private

参数:

  • tag: TagKey

说明:

TODO

public boolean isEmpty() @ L247

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

参数:

说明:

TODO

public Optional<Holder.Reference<T>> getRandom(RandomSource random) @ L252

  • 方法名:getRandom
  • 源码定位:L252
  • 返回类型:Optional<Holder.Reference>
  • 修饰符:public

参数:

  • random: RandomSource

说明:

TODO

public boolean containsKey(Identifier key) @ L257

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

参数:

  • key: Identifier

说明:

TODO

public boolean containsKey(ResourceKey<T> key) @ L262

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

参数:

  • key: ResourceKey

说明:

TODO

public DataComponentLookup<T> componentLookup() @ L267

  • 方法名:componentLookup
  • 源码定位:L267
  • 返回类型:DataComponentLookup
  • 修饰符:public

参数:

说明:

TODO

public Registry<T> freeze() @ L272

  • 方法名:freeze
  • 源码定位:L272
  • 返回类型:Registry
  • 修饰符:public

参数:

说明:

TODO

public Holder.Reference<T> createIntrusiveHolder(T value) @ L320

  • 方法名:createIntrusiveHolder
  • 源码定位:L320
  • 返回类型:Holder.Reference
  • 修饰符:public

参数:

  • value: T

说明:

TODO

public Optional<HolderSet.Named<T>> get(TagKey<T> id) @ L330

  • 方法名:get
  • 源码定位:L330
  • 返回类型:Optional<HolderSet.Named>
  • 修饰符:public

参数:

  • id: TagKey

说明:

TODO

private Holder.Reference<T> validateAndUnwrapTagElement(TagKey<T> id, Holder<T> value) @ L335

  • 方法名:validateAndUnwrapTagElement
  • 源码定位:L335
  • 返回类型:Holder.Reference
  • 修饰符:private

参数:

  • id: TagKey
  • value: Holder

说明:

TODO

public void bindTags(Map<TagKey<T>,List<Holder<T>>> pendingTags) @ L345

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

参数:

  • pendingTags: Map<TagKey,List<Holder>>

说明:

TODO

private void refreshTagsInHolders() @ L351

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

参数:

说明:

TODO

public void bindAllTagsToEmpty() @ L363

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

参数:

说明:

TODO

public HolderGetter<T> createRegistrationLookup() @ L368

  • 方法名:createRegistrationLookup
  • 源码定位:L368
  • 返回类型:HolderGetter
  • 修饰符:public

参数:

说明:

TODO

public Registry.PendingTags<T> prepareTagReload(TagLoader.LoadResult<T> tags) @ L398

  • 方法名:prepareTagReload
  • 源码定位:L398
  • 返回类型:Registry.PendingTags
  • 修饰符:public

参数:

  • tags: TagLoader.LoadResult

说明:

TODO

代码

public class MappedRegistry<T> implements WritableRegistry<T> {
    private final ResourceKey<? extends Registry<T>> key;
    private final ObjectList<Holder.Reference<T>> byId = new ObjectArrayList<>(256);
    private final Reference2IntMap<T> toId = Util.make(new Reference2IntOpenHashMap<>(), t -> t.defaultReturnValue(-1));
    private final Map<Identifier, Holder.Reference<T>> byLocation = new HashMap<>();
    private final Map<ResourceKey<T>, Holder.Reference<T>> byKey = new HashMap<>();
    private final Map<T, Holder.Reference<T>> byValue = new IdentityHashMap<>();
    private final Map<ResourceKey<T>, RegistrationInfo> registrationInfos = new IdentityHashMap<>();
    private Lifecycle registryLifecycle;
    private final Map<TagKey<T>, HolderSet.Named<T>> frozenTags = new IdentityHashMap<>();
    private MappedRegistry.TagSet<T> allTags = MappedRegistry.TagSet.unbound();
    private @Nullable DataComponentLookup<T> componentLookup;
    private boolean frozen;
    private @Nullable Map<T, Holder.Reference<T>> unregisteredIntrusiveHolders;
 
    @Override
    public Stream<HolderSet.Named<T>> listTags() {
        return this.getTags();
    }
 
    public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle lifecycle) {
        this(key, lifecycle, false);
    }
 
    public MappedRegistry(ResourceKey<? extends Registry<T>> key, Lifecycle initialLifecycle, boolean intrusiveHolders) {
        this.key = key;
        this.registryLifecycle = initialLifecycle;
        if (intrusiveHolders) {
            this.unregisteredIntrusiveHolders = new IdentityHashMap<>();
        }
    }
 
    @Override
    public ResourceKey<? extends Registry<T>> key() {
        return this.key;
    }
 
    @Override
    public String toString() {
        return "Registry[" + this.key + " (" + this.registryLifecycle + ")]";
    }
 
    private void validateWrite() {
        if (this.frozen) {
            throw new IllegalStateException("Registry is already frozen");
        }
    }
 
    private void validateWrite(ResourceKey<T> key) {
        if (this.frozen) {
            throw new IllegalStateException("Registry is already frozen (trying to add key " + key + ")");
        }
    }
 
    @Override
    public Holder.Reference<T> register(ResourceKey<T> key, T value, RegistrationInfo registrationInfo) {
        this.validateWrite(key);
        Objects.requireNonNull(key);
        Objects.requireNonNull(value);
        if (this.byLocation.containsKey(key.identifier())) {
            throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("Adding duplicate key '" + key + "' to registry"));
        } else if (this.byValue.containsKey(value)) {
            throw (IllegalStateException)Util.pauseInIde(new IllegalStateException("Adding duplicate value '" + value + "' to registry"));
        } else {
            Holder.Reference<T> holder;
            if (this.unregisteredIntrusiveHolders != null) {
                holder = this.unregisteredIntrusiveHolders.remove(value);
                if (holder == null) {
                    throw new AssertionError("Missing intrusive holder for " + key + ":" + value);
                }
 
                holder.bindKey(key);
            } else {
                holder = this.byKey.computeIfAbsent(key, k -> Holder.Reference.createStandAlone(this, (ResourceKey<T>)k));
            }
 
            this.byKey.put(key, holder);
            this.byLocation.put(key.identifier(), holder);
            this.byValue.put(value, holder);
            int newId = this.byId.size();
            this.byId.add(holder);
            this.toId.put(value, newId);
            this.registrationInfos.put(key, registrationInfo);
            this.registryLifecycle = this.registryLifecycle.add(registrationInfo.lifecycle());
            return holder;
        }
    }
 
    @Override
    public @Nullable Identifier getKey(T thing) {
        Holder.Reference<T> holder = this.byValue.get(thing);
        return holder != null ? holder.key().identifier() : null;
    }
 
    @Override
    public Optional<ResourceKey<T>> getResourceKey(T thing) {
        return Optional.ofNullable(this.byValue.get(thing)).map(Holder.Reference::key);
    }
 
    @Override
    public int getId(@Nullable T thing) {
        return this.toId.getInt(thing);
    }
 
    @Override
    public @Nullable T getValue(@Nullable ResourceKey<T> key) {
        return getValueFromNullable(this.byKey.get(key));
    }
 
    @Override
    public @Nullable T byId(int id) {
        return id >= 0 && id < this.byId.size() ? this.byId.get(id).value() : null;
    }
 
    @Override
    public Optional<Holder.Reference<T>> get(int id) {
        return id >= 0 && id < this.byId.size() ? Optional.ofNullable(this.byId.get(id)) : Optional.empty();
    }
 
    @Override
    public Optional<Holder.Reference<T>> get(Identifier id) {
        return Optional.ofNullable(this.byLocation.get(id));
    }
 
    @Override
    public Optional<Holder.Reference<T>> get(ResourceKey<T> id) {
        return Optional.ofNullable(this.byKey.get(id));
    }
 
    @Override
    public Optional<Holder.Reference<T>> getAny() {
        return this.byId.isEmpty() ? Optional.empty() : Optional.of(this.byId.getFirst());
    }
 
    @Override
    public Holder<T> wrapAsHolder(T value) {
        Holder.Reference<T> existingHolder = this.byValue.get(value);
        return (Holder<T>)(existingHolder != null ? existingHolder : Holder.direct(value));
    }
 
    private Holder.Reference<T> getOrCreateHolderOrThrow(ResourceKey<T> key) {
        return this.byKey.computeIfAbsent(key, id -> {
            if (this.unregisteredIntrusiveHolders != null) {
                throw new IllegalStateException("This registry can't create new holders without value");
            } else {
                this.validateWrite((ResourceKey<T>)id);
                return Holder.Reference.createStandAlone(this, (ResourceKey<T>)id);
            }
        });
    }
 
    @Override
    public int size() {
        return this.byKey.size();
    }
 
    @Override
    public Optional<RegistrationInfo> registrationInfo(ResourceKey<T> element) {
        return Optional.ofNullable(this.registrationInfos.get(element));
    }
 
    @Override
    public Lifecycle registryLifecycle() {
        return this.registryLifecycle;
    }
 
    @Override
    public Iterator<T> iterator() {
        return Iterators.transform(this.byId.iterator(), Holder::value);
    }
 
    @Override
    public @Nullable T getValue(@Nullable Identifier key) {
        Holder.Reference<T> result = this.byLocation.get(key);
        return getValueFromNullable(result);
    }
 
    private static <T> @Nullable T getValueFromNullable(Holder.@Nullable Reference<T> result) {
        return result != null ? result.value() : null;
    }
 
    @Override
    public Set<Identifier> keySet() {
        return Collections.unmodifiableSet(this.byLocation.keySet());
    }
 
    @Override
    public Set<ResourceKey<T>> registryKeySet() {
        return Collections.unmodifiableSet(this.byKey.keySet());
    }
 
    @Override
    public Set<Entry<ResourceKey<T>, T>> entrySet() {
        return Collections.unmodifiableSet(Util.mapValuesLazy(this.byKey, Holder::value).entrySet());
    }
 
    @Override
    public Stream<Holder.Reference<T>> listElements() {
        return this.byId.stream();
    }
 
    @Override
    public Stream<HolderSet.Named<T>> getTags() {
        return this.allTags.getTags();
    }
 
    private HolderSet.Named<T> getOrCreateTagForRegistration(TagKey<T> tag) {
        return this.frozenTags.computeIfAbsent(tag, this::createTag);
    }
 
    private HolderSet.Named<T> createTag(TagKey<T> tag) {
        return new HolderSet.Named<>(this, tag);
    }
 
    @Override
    public boolean isEmpty() {
        return this.byKey.isEmpty();
    }
 
    @Override
    public Optional<Holder.Reference<T>> getRandom(RandomSource random) {
        return Util.getRandomSafe(this.byId, random);
    }
 
    @Override
    public boolean containsKey(Identifier key) {
        return this.byLocation.containsKey(key);
    }
 
    @Override
    public boolean containsKey(ResourceKey<T> key) {
        return this.byKey.containsKey(key);
    }
 
    @Override
    public DataComponentLookup<T> componentLookup() {
        return Objects.requireNonNull(this.componentLookup, "Registry not frozen yet");
    }
 
    @Override
    public Registry<T> freeze() {
        if (this.frozen) {
            return this;
        } else {
            this.frozen = true;
            this.byValue.forEach((value, holder) -> holder.bindValue((T)value));
            List<Identifier> unboundEntries = this.byKey
                .entrySet()
                .stream()
                .filter(e -> !e.getValue().isBound())
                .map(e -> e.getKey().identifier())
                .sorted()
                .toList();
            if (!unboundEntries.isEmpty()) {
                throw new IllegalStateException("Unbound values in registry " + this.key() + ": " + unboundEntries);
            } else {
                if (this.unregisteredIntrusiveHolders != null) {
                    if (!this.unregisteredIntrusiveHolders.isEmpty()) {
                        throw new IllegalStateException("Some intrusive holders were not registered: " + this.unregisteredIntrusiveHolders.values());
                    }
 
                    this.unregisteredIntrusiveHolders = null;
                }
 
                if (this.allTags.isBound()) {
                    throw new IllegalStateException("Tags already present before freezing");
                } else {
                    List<Identifier> unboundTags = this.frozenTags
                        .entrySet()
                        .stream()
                        .filter(e -> !e.getValue().isBound())
                        .map(e -> e.getKey().location())
                        .sorted()
                        .toList();
                    if (!unboundTags.isEmpty()) {
                        throw new IllegalStateException("Unbound tags in registry " + this.key() + ": " + unboundTags);
                    } else {
                        this.componentLookup = new DataComponentLookup<>(this.byId);
                        this.allTags = MappedRegistry.TagSet.fromMap(this.frozenTags);
                        this.refreshTagsInHolders();
                        return this;
                    }
                }
            }
        }
    }
 
    @Override
    public Holder.Reference<T> createIntrusiveHolder(T value) {
        if (this.unregisteredIntrusiveHolders == null) {
            throw new IllegalStateException("This registry can't create intrusive holders");
        } else {
            this.validateWrite();
            return this.unregisteredIntrusiveHolders.computeIfAbsent(value, v -> Holder.Reference.createIntrusive(this, (T)v));
        }
    }
 
    @Override
    public Optional<HolderSet.Named<T>> get(TagKey<T> id) {
        return this.allTags.get(id);
    }
 
    private Holder.Reference<T> validateAndUnwrapTagElement(TagKey<T> id, Holder<T> value) {
        if (!value.canSerializeIn(this)) {
            throw new IllegalStateException("Can't create named set " + id + " containing value " + value + " from outside registry " + this);
        } else if (value instanceof Holder.Reference<T> reference) {
            return reference;
        } else {
            throw new IllegalStateException("Found direct holder " + value + " value in tag " + id);
        }
    }
 
    @Override
    public void bindTags(Map<TagKey<T>, List<Holder<T>>> pendingTags) {
        this.validateWrite();
        pendingTags.forEach((id, values) -> this.getOrCreateTagForRegistration((TagKey<T>)id).bind((List<Holder<T>>)values));
    }
 
    private void refreshTagsInHolders() {
        Map<Holder.Reference<T>, List<TagKey<T>>> tagsForElement = new IdentityHashMap<>();
        this.byKey.values().forEach(h -> tagsForElement.put((Holder.Reference<T>)h, new ArrayList<>()));
        this.allTags.forEach((id, values) -> {
            for (Holder<T> value : values) {
                Holder.Reference<T> reference = this.validateAndUnwrapTagElement((TagKey<T>)id, value);
                tagsForElement.get(reference).add((TagKey<T>)id);
            }
        });
        tagsForElement.forEach(Holder.Reference::bindTags);
    }
 
    public void bindAllTagsToEmpty() {
        this.validateWrite();
        this.frozenTags.values().forEach(e -> e.bind(List.of()));
    }
 
    @Override
    public HolderGetter<T> createRegistrationLookup() {
        this.validateWrite();
        return new HolderGetter<T>() {
            {
                Objects.requireNonNull(MappedRegistry.this);
            }
 
            @Override
            public Optional<Holder.Reference<T>> get(ResourceKey<T> id) {
                return Optional.of(this.getOrThrow(id));
            }
 
            @Override
            public Holder.Reference<T> getOrThrow(ResourceKey<T> id) {
                return MappedRegistry.this.getOrCreateHolderOrThrow(id);
            }
 
            @Override
            public Optional<HolderSet.Named<T>> get(TagKey<T> id) {
                return Optional.of(this.getOrThrow(id));
            }
 
            @Override
            public HolderSet.Named<T> getOrThrow(TagKey<T> id) {
                return MappedRegistry.this.getOrCreateTagForRegistration(id);
            }
        };
    }
 
    @Override
    public Registry.PendingTags<T> prepareTagReload(TagLoader.LoadResult<T> tags) {
        if (!this.frozen) {
            throw new IllegalStateException("Invalid method used for tag loading");
        } else {
            Builder<TagKey<T>, HolderSet.Named<T>> pendingTagsBuilder = ImmutableMap.builder();
            final Map<TagKey<T>, List<Holder<T>>> pendingContents = new HashMap<>();
            tags.tags().forEach((id, contents) -> {
                HolderSet.Named<T> tagToAdd = this.frozenTags.get(id);
                if (tagToAdd == null) {
                    tagToAdd = this.createTag((TagKey<T>)id);
                }
 
                pendingTagsBuilder.put((TagKey<T>)id, tagToAdd);
                pendingContents.put((TagKey<T>)id, List.copyOf(contents));
            });
            final ImmutableMap<TagKey<T>, HolderSet.Named<T>> pendingTags = pendingTagsBuilder.build();
            final HolderLookup.RegistryLookup<T> patchedHolder = new HolderLookup.RegistryLookup.Delegate<T>() {
                {
                    Objects.requireNonNull(MappedRegistry.this);
                }
 
                @Override
                public HolderLookup.RegistryLookup<T> parent() {
                    return MappedRegistry.this;
                }
 
                @Override
                public Optional<HolderSet.Named<T>> get(TagKey<T> id) {
                    return Optional.ofNullable(pendingTags.get(id));
                }
 
                @Override
                public Stream<HolderSet.Named<T>> listTags() {
                    return pendingTags.values().stream();
                }
            };
            return new Registry.PendingTags<T>() {
                {
                    Objects.requireNonNull(MappedRegistry.this);
                }
 
                @Override
                public ResourceKey<? extends Registry<? extends T>> key() {
                    return MappedRegistry.this.key();
                }
 
                @Override
                public int size() {
                    return pendingContents.size();
                }
 
                @Override
                public HolderLookup.RegistryLookup<T> lookup() {
                    return patchedHolder;
                }
 
                @Override
                public void apply() {
                    pendingTags.forEach((id, tag) -> {
                        List<Holder<T>> values = pendingContents.getOrDefault(id, List.of());
                        tag.bind(values);
                    });
                    MappedRegistry.this.allTags = MappedRegistry.TagSet.fromMap(pendingTags);
                    MappedRegistry.this.refreshTagsInHolders();
                }
            };
        }
    }
 
    private interface TagSet<T> {
        static <T> MappedRegistry.TagSet<T> unbound() {
            return new MappedRegistry.TagSet<T>() {
                @Override
                public boolean isBound() {
                    return false;
                }
 
                @Override
                public Optional<HolderSet.Named<T>> get(TagKey<T> id) {
                    throw new IllegalStateException("Tags not bound, trying to access " + id);
                }
 
                @Override
                public void forEach(BiConsumer<? super TagKey<T>, ? super HolderSet.Named<T>> action) {
                    throw new IllegalStateException("Tags not bound");
                }
 
                @Override
                public Stream<HolderSet.Named<T>> getTags() {
                    throw new IllegalStateException("Tags not bound");
                }
            };
        }
 
        static <T> MappedRegistry.TagSet<T> fromMap(Map<TagKey<T>, HolderSet.Named<T>> tags) {
            return new MappedRegistry.TagSet<T>() {
                @Override
                public boolean isBound() {
                    return true;
                }
 
                @Override
                public Optional<HolderSet.Named<T>> get(TagKey<T> id) {
                    return Optional.ofNullable(tags.get(id));
                }
 
                @Override
                public void forEach(BiConsumer<? super TagKey<T>, ? super HolderSet.Named<T>> action) {
                    tags.forEach(action);
                }
 
                @Override
                public Stream<HolderSet.Named<T>> getTags() {
                    return tags.values().stream();
                }
            };
        }
 
        boolean isBound();
 
        Optional<HolderSet.Named<T>> get(TagKey<T> id);
 
        void forEach(BiConsumer<? super TagKey<T>, ? super HolderSet.Named<T>> action);
 
        Stream<HolderSet.Named<T>> getTags();
    }
}

引用的其他类

  • Holder

    • 引用位置: 参数/字段/方法调用/返回值
    • 关联成员: Holder.Reference.createIntrusive(), Holder.Reference.createStandAlone(), Holder.direct()
  • HolderGetter

    • 引用位置: 返回值
  • HolderSet

    • 引用位置: 字段/返回值
  • RegistrationInfo

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

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

    • 引用位置: 实现
  • DataComponentLookup

    • 引用位置: 字段/返回值
  • Identifier

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

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

    • 引用位置: 参数/字段
  • TagLoader

    • 引用位置: 参数
  • RandomSource

    • 引用位置: 参数
  • Util

    • 引用位置: 方法调用
    • 关联成员: Util.getRandomSafe(), Util.make(), Util.mapValuesLazy(), Util.pauseInIde()