/* * Copyright (c) Forge Development LLC and contributors * SPDX-License-Identifier: LGPL-2.1-only */ package net.minecraftforge.registries; import com.google.common.collect.Lists; import net.minecraft.core.Holder; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.registries.IForgeRegistry.AddCallback; import net.minecraftforge.registries.IForgeRegistry.BakeCallback; import net.minecraftforge.registries.IForgeRegistry.ClearCallback; import net.minecraftforge.registries.IForgeRegistry.CreateCallback; import net.minecraftforge.registries.IForgeRegistry.DummyFactory; import net.minecraftforge.registries.IForgeRegistry.MissingFactory; import net.minecraftforge.registries.IForgeRegistry.ValidateCallback; import org.jetbrains.annotations.Nullable; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Function; public class RegistryBuilder { private static final int MAX_ID = Integer.MAX_VALUE - 1; private ResourceLocation registryName; private ResourceLocation optionalDefaultKey; private int minId = 0; private int maxId = MAX_ID; private List> addCallback = Lists.newArrayList(); private List> clearCallback = Lists.newArrayList(); private List> createCallback = Lists.newArrayList(); private List> validateCallback = Lists.newArrayList(); private List> bakeCallback = Lists.newArrayList(); private boolean saveToDisc = true; private boolean sync = true; private boolean allowOverrides = true; private boolean allowModifications = false; private boolean hasWrapper = false; private DummyFactory dummyFactory; private MissingFactory missingFactory; private Set legacyNames = new HashSet<>(); @Nullable private Function> intrusiveHolderCallback = null; public RegistryBuilder setName(ResourceLocation name) { this.registryName = name; return this; } public RegistryBuilder setIDRange(int min, int max) { this.minId = Math.max(min, 0); this.maxId = Math.min(max, MAX_ID); return this; } public RegistryBuilder setMaxID(int max) { return this.setIDRange(0, max); } public RegistryBuilder setDefaultKey(ResourceLocation key) { this.optionalDefaultKey = key; return this; } @SuppressWarnings("unchecked") public RegistryBuilder addCallback(Object inst) { if (inst instanceof AddCallback) this.add((AddCallback)inst); if (inst instanceof ClearCallback) this.add((ClearCallback)inst); if (inst instanceof CreateCallback) this.add((CreateCallback)inst); if (inst instanceof ValidateCallback) this.add((ValidateCallback)inst); if (inst instanceof BakeCallback) this.add((BakeCallback)inst); if (inst instanceof DummyFactory) this.set((DummyFactory)inst); if (inst instanceof MissingFactory) this.set((MissingFactory)inst); return this; } public RegistryBuilder add(AddCallback add) { this.addCallback.add(add); return this; } public RegistryBuilder onAdd(AddCallback add) { return this.add(add); } public RegistryBuilder add(ClearCallback clear) { this.clearCallback.add(clear); return this; } public RegistryBuilder onClear(ClearCallback clear) { return this.add(clear); } public RegistryBuilder add(CreateCallback create) { this.createCallback.add(create); return this; } public RegistryBuilder onCreate(CreateCallback create) { return this.add(create); } public RegistryBuilder add(ValidateCallback validate) { this.validateCallback.add(validate); return this; } public RegistryBuilder onValidate(ValidateCallback validate) { return this.add(validate); } public RegistryBuilder add(BakeCallback bake) { this.bakeCallback.add(bake); return this; } public RegistryBuilder onBake(BakeCallback bake) { return this.add(bake); } public RegistryBuilder set(DummyFactory factory) { this.dummyFactory = factory; return this; } public RegistryBuilder dummy(DummyFactory factory) { return this.set(factory); } public RegistryBuilder set(MissingFactory missing) { this.missingFactory = missing; return this; } public RegistryBuilder missing(MissingFactory missing) { return this.set(missing); } public RegistryBuilder disableSaving() { this.saveToDisc = false; return this; } /** * Prevents the registry from being synced to clients. * * @return this */ public RegistryBuilder disableSync() { this.sync = false; return this; } public RegistryBuilder disableOverrides() { this.allowOverrides = false; return this; } public RegistryBuilder allowModification() { this.allowModifications = true; return this; } RegistryBuilder hasWrapper() { this.hasWrapper = true; return this; } public RegistryBuilder legacyName(String name) { return legacyName(new ResourceLocation(name)); } public RegistryBuilder legacyName(ResourceLocation name) { this.legacyNames.add(name); return this; } RegistryBuilder intrusiveHolderCallback(Function> intrusiveHolderCallback) { this.intrusiveHolderCallback = intrusiveHolderCallback; return this; } /** * Enables tags for this registry if not already. * All forge registries with wrappers inherently support tags. * * @return this builder * @see RegistryBuilder#hasWrapper() */ public RegistryBuilder hasTags() { // Tag system heavily relies on Registry objects, so we need a wrapper for this registry to take advantage this.hasWrapper(); return this; } /** * Modders: Use {@link NewRegistryEvent#create(RegistryBuilder)} instead */ IForgeRegistry create() { if (hasWrapper) { if (getDefault() == null) addCallback(new NamespacedWrapper.Factory()); else addCallback(new NamespacedDefaultedWrapper.Factory()); } return RegistryManager.ACTIVE.createRegistry(registryName, this); } @Nullable public AddCallback getAdd() { if (addCallback.isEmpty()) return null; if (addCallback.size() == 1) return addCallback.get(0); return (owner, stage, id, key, obj, old) -> { for (AddCallback cb : this.addCallback) cb.onAdd(owner, stage, id, key, obj, old); }; } @Nullable public ClearCallback getClear() { if (clearCallback.isEmpty()) return null; if (clearCallback.size() == 1) return clearCallback.get(0); return (owner, stage) -> { for (ClearCallback cb : this.clearCallback) cb.onClear(owner, stage); }; } @Nullable public CreateCallback getCreate() { if (createCallback.isEmpty()) return null; if (createCallback.size() == 1) return createCallback.get(0); return (owner, stage) -> { for (CreateCallback cb : this.createCallback) cb.onCreate(owner, stage); }; } @Nullable public ValidateCallback getValidate() { if (validateCallback.isEmpty()) return null; if (validateCallback.size() == 1) return validateCallback.get(0); return (owner, stage, id, key, obj) -> { for (ValidateCallback cb : this.validateCallback) cb.onValidate(owner, stage, id, key, obj); }; } @Nullable public BakeCallback getBake() { if (bakeCallback.isEmpty()) return null; if (bakeCallback.size() == 1) return bakeCallback.get(0); return (owner, stage) -> { for (BakeCallback cb : this.bakeCallback) cb.onBake(owner, stage); }; } @Nullable public ResourceLocation getDefault() { return this.optionalDefaultKey; } public int getMinId() { return minId; } public int getMaxId() { return maxId; } public boolean getAllowOverrides() { return allowOverrides; } public boolean getAllowModifications() { return allowModifications; } @Nullable public DummyFactory getDummyFactory() { return dummyFactory; } @Nullable public MissingFactory getMissingFactory() { return missingFactory; } public boolean getSaveToDisc() { return saveToDisc; } public boolean getSync() { return sync; } public Set getLegacyNames() { return legacyNames; } Function> getIntrusiveHolderCallback() { return this.intrusiveHolderCallback; } boolean getHasWrapper() { return this.hasWrapper; } }