diff --git a/src/main/java/net/minecraftforge/fml/RegistryObject.java b/src/main/java/net/minecraftforge/fml/RegistryObject.java index 6b2240b64..8c326e67a 100644 --- a/src/main/java/net/minecraftforge/fml/RegistryObject.java +++ b/src/main/java/net/minecraftforge/fml/RegistryObject.java @@ -22,9 +22,12 @@ package net.minecraftforge.fml; import net.minecraft.util.ResourceLocation; import net.minecraftforge.registries.IForgeRegistry; import net.minecraftforge.registries.IForgeRegistryEntry; +import net.minecraftforge.registries.IRegistryDelegate; import net.minecraftforge.registries.ObjectHolderRegistry; import net.minecraftforge.registries.RegistryManager; +import javax.annotation.Nullable; + import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; @@ -33,19 +36,27 @@ import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Stream; -import javax.annotation.Nullable; - public final class RegistryObject> implements Supplier { private final ResourceLocation name; @Nullable private T value; + @Deprecated public static , U extends T> RegistryObject of(final String name, Supplier> registryType) { + return of(new ResourceLocation(name), registryType); + } + + public static , U extends T> RegistryObject of(final ResourceLocation name, Supplier> registryType) { return new RegistryObject<>(name, registryType); } + @Deprecated public static , U extends T> RegistryObject of(final String name, IForgeRegistry registry) { + return of(new ResourceLocation(name), registry); + } + + public static , U extends T> RegistryObject of(final ResourceLocation name, IForgeRegistry registry) { return new RegistryObject<>(name, registry); } @@ -61,17 +72,17 @@ public final class RegistryObject> impl this.name = null; } - private > RegistryObject(String name, Supplier> registryType) + private > RegistryObject(ResourceLocation name, Supplier> registryType) { this(name, RegistryManager.ACTIVE.getRegistry(registryType.get())); } @SuppressWarnings("unchecked") - private > RegistryObject(String name, IForgeRegistry registry) + private > RegistryObject(ResourceLocation name, IForgeRegistry registry) { if (registry == null) throw new IllegalArgumentException("Invalid registry argument, must not be null"); - this.name = new ResourceLocation(name); + this.name = name; ObjectHolderRegistry.addHandler(pred -> { if (pred.test(registry.getRegistryName())) @@ -83,13 +94,28 @@ public final class RegistryObject> impl * Directly retrieves the wrapped Registry Object. This value will automatically be updated when the backing registry is updated. */ @Nullable + @Override public T get() { return this.value; } + public void updateReference(IForgeRegistry registry) + { + this.value = registry.getValue(getId()); + } + + public ResourceLocation getId() + { + return this.name; + } + + /** + * @deprecated Prefer {@link #getId()} + */ + @Deprecated public String getName() { - return this.name.toString(); + return getId().toString(); } public Stream stream() { @@ -186,6 +212,26 @@ public final class RegistryObject> impl return Objects.requireNonNull(mapper.apply(get())); } } + + /** + * If a mod object is present, lazily apply the provided mapping function to it, + * returning a supplier for the transformed result. If this object is empty, or the + * mapping function returns {@code null}, the supplier will return {@code null}. + * + * @apiNote This method supports post-processing on optional values, without + * the need to explicitly check for a return status. + * + * @param The type of the result of the mapping function + * @param mapper A mapping function to apply to the mod object, if present + * @return A {@code Supplier} lazily providing the result of applying a mapping + * function to the mod object of this {@code RegistryObject}, if a mod object is present, + * otherwise a supplier returning {@code null} + * @throws NullPointerException if the mapping function is {@code null} + */ + public Supplier lazyMap(Function mapper) { + Objects.requireNonNull(mapper); + return () -> isPresent() ? mapper.apply(get()) : null; + } /** * Return the mod object if present, otherwise return {@code other}. @@ -195,7 +241,7 @@ public final class RegistryObject> impl * @return the mod object, if present, otherwise {@code other} */ public T orElse(T other) { - return get() != null ? get() : other; + return isPresent() ? get() : other; } /** @@ -209,7 +255,7 @@ public final class RegistryObject> impl * null */ public T orElseGet(Supplier other) { - return get() != null ? get() : other.get(); + return isPresent() ? get() : other.get(); } /** diff --git a/src/main/java/net/minecraftforge/registries/DeferredRegister.java b/src/main/java/net/minecraftforge/registries/DeferredRegister.java index eae15e452..aac37c1cf 100644 --- a/src/main/java/net/minecraftforge/registries/DeferredRegister.java +++ b/src/main/java/net/minecraftforge/registries/DeferredRegister.java @@ -19,15 +19,17 @@ package net.minecraftforge.registries; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.IEventBus; import net.minecraftforge.fml.RegistryObject; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.function.Supplier; + /** * Utility class to help with managing registry entries. * Maintains a list of all suppliers for entries and registers them during the proper Register event. @@ -53,7 +55,7 @@ public class DeferredRegister> { private final IForgeRegistry type; private final String modid; - private List> entries = new ArrayList<>(); + private Map, Supplier> entries = new LinkedHashMap<>(); public DeferredRegister(IForgeRegistry reg, String modid) { @@ -68,11 +70,17 @@ public class DeferredRegister> * @param sup A factory for the new entry, it should return a new instance every time it is called. * @return A RegistryObject that will be updated with when the entries in the registry change. */ + @SuppressWarnings("unchecked") public RegistryObject register(final String name, final Supplier sup) { + Objects.requireNonNull(name); + Objects.requireNonNull(sup); final ResourceLocation key = new ResourceLocation(modid, name); - entries.add(() -> sup.get().setRegistryName(key)); - return RegistryObject.of(key.toString(), this.type); + RegistryObject ret = RegistryObject.of(key, this.type); + if (entries.putIfAbsent((RegistryObject) ret, () -> sup.get().setRegistryName(key)) != null) { + throw new IllegalArgumentException("Duplicate registration " + name); + } + return ret; } /** @@ -92,7 +100,11 @@ public class DeferredRegister> { @SuppressWarnings("unchecked") IForgeRegistry reg = (IForgeRegistry)event.getRegistry(); - entries.stream().map(Supplier::get).forEach(reg::register); + for (Entry, Supplier> e : entries.entrySet()) + { + reg.register(e.getValue().get()); + e.getKey().updateReference(reg); + } } } } diff --git a/src/main/java/net/minecraftforge/registries/IRegistryDelegate.java b/src/main/java/net/minecraftforge/registries/IRegistryDelegate.java index f4ddc656d..cc12944a1 100644 --- a/src/main/java/net/minecraftforge/registries/IRegistryDelegate.java +++ b/src/main/java/net/minecraftforge/registries/IRegistryDelegate.java @@ -41,6 +41,7 @@ public interface IRegistryDelegate extends Supplier { * * @return The referred object */ + @Override T get(); /**