Update to 20.2.59-beta & Adapt to Registry Changes

This commit is contained in:
shedaniel
2023-11-20 21:00:36 +08:00
parent 426ca41331
commit 9aba3cf1dc
13 changed files with 755 additions and 20 deletions

View File

@@ -0,0 +1,98 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.impl;
import com.mojang.datafixers.util.Either;
import dev.architectury.registry.registries.RegistrySupplier;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderOwner;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Stream;
@ApiStatus.Internal
public interface RegistrySupplierImpl<T> extends RegistrySupplier<T> {
@Nullable
Holder<T> getHolder();
@Override
default T value() {
return get();
}
@Override
default boolean isBound() {
return isPresent();
}
@Override
default boolean is(ResourceLocation resourceLocation) {
return getId().equals(resourceLocation);
}
@Override
default boolean is(ResourceKey<T> resourceKey) {
return getKey().equals(resourceKey);
}
@Override
default boolean is(Predicate<ResourceKey<T>> predicate) {
return predicate.test(getKey());
}
@Override
default boolean is(TagKey<T> tagKey) {
Holder<T> holder = getHolder();
return holder != null && holder.is(tagKey);
}
@Override
default Stream<TagKey<T>> tags() {
Holder<T> holder = getHolder();
return holder != null ? holder.tags() : Stream.empty();
}
@Override
default Either<ResourceKey<T>, T> unwrap() {
return Either.left(getKey());
}
@Override
default Optional<ResourceKey<T>> unwrapKey() {
return Optional.of(getKey());
}
@Override
default Kind kind() {
return Kind.REFERENCE;
}
@Override
default boolean canSerializeIn(HolderOwner<T> holderOwner) {
Holder<T> holder = getHolder();
return holder != null && holder.canSerializeIn(holderOwner);
}
}

View File

@@ -20,6 +20,8 @@
package dev.architectury.registry.registries;
import com.google.common.base.Suppliers;
import dev.architectury.impl.RegistrySupplierImpl;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
@@ -90,16 +92,25 @@ public class DeferredRegister<T> implements Iterable<RegistrySupplier<T>> {
return registriesSupplier.get().get(key);
}
private class Entry<R> implements RegistrySupplier<R> {
private class Entry<R> implements RegistrySupplierImpl<R> {
private final ResourceLocation id;
private final Supplier<R> supplier;
private RegistrySupplier<R> value;
@Nullable
private Holder<R> holder = null;
public Entry(ResourceLocation id, Supplier<R> supplier) {
this.id = id;
this.supplier = supplier;
}
@Nullable
@Override
public Holder<R> getHolder() {
if (holder != null) return holder;
return holder = getRegistrar().getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return DeferredRegister.this.getRegistrarManager();

View File

@@ -19,6 +19,7 @@
package dev.architectury.registry.registries;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
@@ -68,6 +69,14 @@ public interface Registrar<T> extends Iterable<T> {
ResourceKey<? extends Registry<T>> key();
@Nullable
Holder<T> getHolder(ResourceKey<T> key);
@Nullable
default Holder<T> getHolder(ResourceLocation id) {
return getHolder(ResourceKey.create(key(), id));
}
/**
* Listens to when the registry entry is registered, and calls the given action.
* Evaluates immediately if the entry is already registered.

View File

@@ -19,12 +19,13 @@
package dev.architectury.registry.registries;
import net.minecraft.core.Holder;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Consumer;
@ApiStatus.NonExtendable
public interface RegistrySupplier<T> extends DeferredSupplier<T> {
public interface RegistrySupplier<T> extends DeferredSupplier<T>, Holder<T> {
RegistrarManager getRegistrarManager();
Registrar<T> getRegistrar();

View File

@@ -23,6 +23,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import dev.architectury.impl.RegistrySupplierImpl;
import dev.architectury.registry.registries.Registrar;
import dev.architectury.registry.registries.RegistrarBuilder;
import dev.architectury.registry.registries.RegistrarManager;
@@ -32,6 +33,7 @@ import dev.architectury.registry.registries.options.StandardRegistrarOption;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
import net.minecraft.core.Holder;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
@@ -153,7 +155,17 @@ public class RegistrarManagerImpl {
public RegistrySupplier<T> delegate(ResourceLocation id) {
Supplier<T> value = Suppliers.memoize(() -> get(id));
RegistrarImpl<T> registrar = this;
return new RegistrySupplier<>() {
return new RegistrySupplierImpl<T>() {
@Nullable
Holder<T> holder = null;
@Nullable
@Override
public Holder<T> getHolder() {
if (holder != null) return holder;
return holder = registrar.getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
@@ -259,6 +271,12 @@ public class RegistrarManagerImpl {
return delegate.key();
}
@Override
@Nullable
public Holder<T> getHolder(ResourceKey<T> key) {
return delegate.getHolder(key).orElse(null);
}
@Override
public Iterator<T> iterator() {
return delegate.iterator();

View File

@@ -0,0 +1,36 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.hooks.forgelike;
import com.mojang.serialization.Codec;
import dev.architectury.injectables.annotations.ExpectPlatform;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.world.BiomeModifier;
import org.jetbrains.annotations.ApiStatus;
import java.util.function.Supplier;
@ApiStatus.Internal
public class ForgeLikeHooks {
@ExpectPlatform
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
throw new AssertionError();
}
}

View File

@@ -21,8 +21,8 @@ package dev.architectury.registry.level.biome.forge;
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import dev.architectury.hooks.forgelike.ForgeLikeHooks;
import dev.architectury.hooks.level.biome.*;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.registry.level.biome.BiomeModifications.BiomeContext;
import dev.architectury.utils.ArchitecturyConstants;
import dev.architectury.utils.GameInstance;
@@ -42,8 +42,6 @@ import net.minecraft.world.level.levelgen.GenerationStep;
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
import net.minecraftforge.common.world.*;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.Nullable;
@@ -64,14 +62,8 @@ public class BiomeModificationsImpl {
private static Codec<BiomeModifierImpl> noneBiomeModCodec = null;
public static void init() {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID,bus -> {
bus.<RegisterEvent>addListener(event -> {
event.register(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
registry.register(new ResourceLocation(ArchitecturyConstants.MOD_ID, "none_biome_mod_codec"),
noneBiomeModCodec = Codec.unit(BiomeModifierImpl.INSTANCE));
});
});
});
ForgeLikeHooks.registerBiomeModifier(new ResourceLocation(ArchitecturyConstants.MOD_ID, "none_biome_mod_codec"),
() -> noneBiomeModCodec = Codec.unit(BiomeModifierImpl.INSTANCE));
}
public static void addProperties(Predicate<BiomeContext> predicate, BiConsumer<BiomeContext, BiomeProperties.Mutable> modifier) {

View File

@@ -18,7 +18,7 @@ fabric_api_version=0.89.1+1.20.2
mod_menu_version=7.0.0
forge_version=48.0.38
neoforge_version=20.2.52-beta
neoforge_version=20.2.59-beta
curseforge_id=419699
modrinth_id=lhGA9TYQ

View File

@@ -0,0 +1,42 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.hooks.forgelike.forge;
import com.mojang.serialization.Codec;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.world.BiomeModifier;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
import java.util.function.Supplier;
public class ForgeLikeHooksImpl {
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
EventBusesHooks.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.<RegisterEvent>addListener(event -> {
event.register(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
registry.register(id, codecSupplier.get());
});
});
});
}
}

View File

@@ -23,6 +23,7 @@ import com.google.common.base.Objects;
import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import dev.architectury.impl.RegistrySupplierImpl;
import dev.architectury.platform.hooks.EventBusesHooks;
import dev.architectury.registry.registries.Registrar;
import dev.architectury.registry.registries.RegistrarBuilder;
@@ -30,6 +31,7 @@ import dev.architectury.registry.registries.RegistrarManager;
import dev.architectury.registry.registries.RegistrySupplier;
import dev.architectury.registry.registries.options.RegistrarOption;
import dev.architectury.registry.registries.options.StandardRegistrarOption;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
@@ -322,7 +324,17 @@ public class RegistrarManagerImpl {
public RegistrySupplier<T> delegate(ResourceLocation id) {
Supplier<T> value = Suppliers.memoize(() -> get(id));
Registrar<T> registrar = this;
return new RegistrySupplier<>() {
return new RegistrySupplierImpl<T>() {
@Nullable
Holder<T> holder = null;
@Nullable
@Override
public Holder<T> getHolder() {
if (holder != null) return holder;
return holder = registrar.getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
@@ -432,6 +444,12 @@ public class RegistrarManagerImpl {
return delegate.key();
}
@Override
@Nullable
public Holder<T> getHolder(ResourceKey<T> key) {
return delegate.getHolder(key).orElse(null);
}
@Override
public Iterator<T> iterator() {
return delegate.iterator();
@@ -462,7 +480,17 @@ public class RegistrarManagerImpl {
public RegistrySupplier<T> delegate(ResourceLocation id) {
Supplier<T> value = Suppliers.memoize(() -> get(id));
Registrar<T> registrar = this;
return new RegistrySupplier<>() {
return new RegistrySupplierImpl<T>() {
@Nullable
Holder<T> holder = null;
@Nullable
@Override
public Holder<T> getHolder() {
if (holder != null) return holder;
return holder = registrar.getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
@@ -519,7 +547,17 @@ public class RegistrarManagerImpl {
Data<T> data = (Data<T>) registry.computeIfAbsent(key(), type -> new Data<>());
data.registerForForge(delegate, id, objectArr, supplier);
Registrar<T> registrar = this;
return new RegistrySupplier<>() {
return new RegistrySupplierImpl<E>() {
@Nullable
Holder<E> holder = null;
@Nullable
@Override
public Holder<E> getHolder() {
if (holder != null) return holder;
return holder = getRegistrar().getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
@@ -625,6 +663,12 @@ public class RegistrarManagerImpl {
return ResourceKey.createRegistryKey(delegate.getRegistryName());
}
@Override
@Nullable
public Holder<T> getHolder(ResourceKey<T> key) {
return delegate.getHolder(key).orElse(null);
}
@Override
public Iterator<T> iterator() {
return delegate.iterator();
@@ -668,7 +712,17 @@ public class RegistrarManagerImpl {
@Override
public RegistrySupplier<T> delegate(ResourceLocation id) {
if (isReady()) return delegate.get().delegate(id);
return new RegistrySupplier<>() {
return new RegistrySupplierImpl<T>() {
@Nullable
Holder<T> holder = null;
@Nullable
@Override
public Holder<T> getHolder() {
if (holder != null || !isReady()) return holder;
return holder = delegate.get().getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
@@ -761,6 +815,12 @@ public class RegistrarManagerImpl {
return isReady() ? delegate.get().key() : ResourceKey.createRegistryKey(registryId);
}
@Override
@Nullable
public Holder<T> getHolder(ResourceKey<T> key) {
return isReady() ? delegate.get().getHolder(key) : null;
}
@Override
public void listen(ResourceLocation id, Consumer<T> callback) {
if (isReady()) {

View File

@@ -0,0 +1,42 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.hooks.forgelike.forge;
import com.mojang.serialization.Codec;
import dev.architectury.platform.hooks.forge.EventBusesHooksImpl;
import dev.architectury.utils.ArchitecturyConstants;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.neoforge.common.world.BiomeModifier;
import net.neoforged.neoforge.registries.NeoForgeRegistries;
import net.neoforged.neoforge.registries.RegisterEvent;
import java.util.function.Supplier;
public class ForgeLikeHooksImpl {
public static void registerBiomeModifier(ResourceLocation id, Supplier<Codec<? extends BiomeModifier>> codecSupplier) {
EventBusesHooksImpl.whenAvailable(ArchitecturyConstants.MOD_ID, bus -> {
bus.<RegisterEvent>addListener(event -> {
event.register(NeoForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, registry -> {
registry.register(id, codecSupplier.get());
});
});
});
}
}

View File

@@ -0,0 +1,426 @@
/*
* This file is part of architectury.
* Copyright (C) 2020, 2021, 2022 architectury
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package dev.architectury.registry.registries.forge;
import com.google.common.base.Objects;
import com.google.common.base.Suppliers;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import dev.architectury.impl.RegistrySupplierImpl;
import dev.architectury.platform.hooks.forge.EventBusesHooksImpl;
import dev.architectury.registry.registries.Registrar;
import dev.architectury.registry.registries.RegistrarBuilder;
import dev.architectury.registry.registries.RegistrarManager;
import dev.architectury.registry.registries.RegistrySupplier;
import dev.architectury.registry.registries.options.RegistrarOption;
import dev.architectury.registry.registries.options.StandardRegistrarOption;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.bus.api.EventPriority;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.neoforge.registries.NewRegistryEvent;
import net.neoforged.neoforge.registries.RegisterEvent;
import net.neoforged.neoforge.registries.RegistryBuilder;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.function.BooleanSupplier;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class RegistrarManagerImpl {
private static final Logger LOGGER = LogManager.getLogger(RegistrarManagerImpl.class);
private static final Multimap<RegistryEntryId<?>, Consumer<?>> LISTENERS = HashMultimap.create();
private static void listen(ResourceKey<?> resourceKey, ResourceLocation id, Consumer<?> listener) {
LISTENERS.put(new RegistryEntryId<>(resourceKey, id), listener);
}
public static RegistrarManager.RegistryProvider _get(String modId) {
return new RegistryProviderImpl(modId);
}
public static class Data<T> {
private boolean registered = false;
private final Map<ResourceLocation, Supplier<? extends T>> objects = new LinkedHashMap<>();
public void register(Registry<T> registry, ResourceLocation location, Mutable<T> object, Supplier<? extends T> reference) {
if (!registered) {
objects.put(location, () -> {
T value = reference.get();
object.setValue(value);
return value;
});
} else {
ResourceKey<? extends Registry<T>> resourceKey = registry.key();
T value = reference.get();
Registry.register(registry, location, value);
object.setValue(value);
RegistryEntryId<?> registryEntryId = new RegistryEntryId<>(resourceKey, location);
for (Consumer<?> consumer : LISTENERS.get(registryEntryId)) {
((Consumer<Object>) consumer).accept(value);
}
LISTENERS.removeAll(registryEntryId);
}
}
}
public record RegistryEntryId<T>(ResourceKey<T> registryKey, ResourceLocation id) {
@Override
public String toString() {
return "Registry Entry [%s / %s]".formatted(registryKey.location(), id);
}
}
public static class RegistryProviderImpl implements RegistrarManager.RegistryProvider {
private static final Map<ResourceKey<Registry<?>>, Registrar<?>> CUSTOM_REGS = new HashMap<>();
private final String modId;
private final Supplier<IEventBus> eventBus;
private final Map<ResourceKey<? extends Registry<?>>, Data<?>> registry = new HashMap<>();
private final Multimap<ResourceKey<Registry<?>>, Consumer<Registrar<?>>> listeners = HashMultimap.create();
@Nullable
private List<Registry<?>> newRegistries = new ArrayList<>();
public RegistryProviderImpl(String modId) {
this.modId = modId;
this.eventBus = Suppliers.memoize(() -> {
IEventBus eventBus = EventBusesHooksImpl.getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Can't get event bus for mod '" + modId + "' because it was not registered!"));
eventBus.register(new EventListener());
return eventBus;
});
}
private void updateEventBus() {
synchronized (eventBus) {
// Make sure that the eventbus is setup
this.eventBus.get();
}
}
@Override
public <T> Registrar<T> get(ResourceKey<Registry<T>> registryKey) {
updateEventBus();
Registry<T> registry = (Registry<T>) BuiltInRegistries.REGISTRY.get(registryKey.location());
if (registry != null) {
return get(registry);
}
Registrar<?> customReg = RegistryProviderImpl.CUSTOM_REGS.get(registryKey);
if (customReg != null) return (Registrar<T>) customReg;
throw new IllegalArgumentException("Registry " + registryKey + " does not exist!");
}
@Override
public <T> Registrar<T> get(Registry<T> registry) {
updateEventBus();
return new RegistrarImpl<>(modId, this.registry, registry);
}
@Override
public <T> void forRegistry(ResourceKey<Registry<T>> key, Consumer<Registrar<T>> consumer) {
this.listeners.put((ResourceKey<Registry<?>>) (ResourceKey<? extends Registry<?>>) key,
(Consumer<Registrar<?>>) (Consumer<? extends Registrar<?>>) consumer);
}
@Override
public <T> RegistrarBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
return new RegistryBuilderWrapper<>(this, new RegistryBuilder<>(ResourceKey.createRegistryKey(registryId)));
}
public class EventListener {
@SubscribeEvent
public void handleEvent(RegisterEvent event) {
for (Map.Entry<ResourceKey<? extends Registry<?>>, Data<?>> typeDataEntry : RegistryProviderImpl.this.registry.entrySet()) {
if (typeDataEntry.getKey().equals(event.getRegistryKey())) {
//noinspection rawtypes
registerFor(event, (ResourceKey) typeDataEntry.getKey(), typeDataEntry.getValue());
}
}
}
public <T> void registerFor(RegisterEvent event, ResourceKey<? extends Registry<T>> resourceKey, Data<T> data) {
event.register(resourceKey, registry -> {
data.registered = true;
for (Map.Entry<ResourceLocation, Supplier<? extends T>> entry : data.objects.entrySet()) {
ResourceLocation location = entry.getKey();
T value = entry.getValue().get();
registry.register(location, value);
RegistryEntryId<?> registryEntryId = new RegistryEntryId<>(resourceKey, location);
for (Consumer<?> consumer : LISTENERS.get(registryEntryId)) {
((Consumer<Object>) consumer).accept(value);
}
LISTENERS.removeAll(registryEntryId);
}
data.objects.clear();
Registrar<?> archRegistry = get(event.getRegistry());
for (Map.Entry<ResourceKey<Registry<?>>, Consumer<Registrar<?>>> entry : listeners.entries()) {
if (entry.getKey().location().equals(resourceKey.location())) {
entry.getValue().accept(archRegistry);
}
}
});
}
@SubscribeEvent(priority = EventPriority.LOWEST)
public void handleEventPost(RegisterEvent event) {
Registrar<?> archRegistry = get(event.getRegistry());
List<RegistryEntryId<?>> toRemove = new ArrayList<>();
for (Map.Entry<RegistryEntryId<?>, Collection<Consumer<?>>> entry : LISTENERS.asMap().entrySet()) {
if (entry.getKey().registryKey.equals(event.getRegistryKey())) {
if (archRegistry.contains(entry.getKey().id)) {
Object value = archRegistry.get(entry.getKey().id);
for (Consumer<?> consumer : entry.getValue()) {
((Consumer<Object>) consumer).accept(value);
}
toRemove.add(entry.getKey());
} else {
LOGGER.warn("Registry entry listened {} was not realized!", entry.getKey());
}
}
}
for (RegistryEntryId<?> id : toRemove) {
LISTENERS.removeAll(id);
}
}
@SubscribeEvent
public void handleEvent(NewRegistryEvent event) {
if (newRegistries != null) {
for (Registry<?> registry : newRegistries) {
event.register(registry);
}
newRegistries = null;
}
}
}
}
public static class RegistryBuilderWrapper<T> implements RegistrarBuilder<T> {
private final RegistryProviderImpl provider;
private final RegistryBuilder<T> builder;
private boolean syncToClients = false;
public RegistryBuilderWrapper(RegistryProviderImpl provider, RegistryBuilder<T> builder) {
this.provider = provider;
this.builder = builder;
}
@Override
public Registrar<T> build() {
builder.sync(syncToClients);
if (provider.newRegistries == null) {
throw new IllegalStateException("Cannot create registries when registries are already aggregated!");
}
var registry = builder.create();
var registrar = provider.get(registry);
provider.newRegistries.add(registry);
//noinspection rawtypes
RegistryProviderImpl.CUSTOM_REGS.put((ResourceKey) registrar.key(), registrar);
return registrar;
}
@Override
public RegistrarBuilder<T> option(RegistrarOption option) {
if (option == StandardRegistrarOption.SYNC_TO_CLIENTS) {
this.syncToClients = true;
}
return this;
}
}
public static class RegistrarImpl<T> implements Registrar<T> {
private final String modId;
private final Registry<T> delegate;
private final Map<ResourceKey<? extends Registry<?>>, Data<?>> registry;
public RegistrarImpl(String modId, Map<ResourceKey<? extends Registry<?>>, Data<?>> registry, Registry<T> delegate) {
this.modId = modId;
this.registry = registry;
this.delegate = delegate;
}
@Override
public RegistrySupplier<T> delegate(ResourceLocation id) {
Supplier<T> value = Suppliers.memoize(() -> get(id));
return asSupplier(id, this, () -> contains(id), value);
}
@Override
public <E extends T> RegistrySupplier<E> register(ResourceLocation id, Supplier<E> supplier) {
Data<T> data = (Data<T>) registry.computeIfAbsent(key(), type -> new Data<>());
Mutable<T> object = new MutableObject<>();
data.register(delegate, id, object, supplier);
return asSupplier(id, (Registrar<E>) this, () -> object.getValue() != null, object::getValue);
}
private <E extends T> RegistrySupplier<E> asSupplier(ResourceLocation id, Registrar<E> registrar, BooleanSupplier isPresent, Supplier<T> object) {
return new RegistrySupplierImpl<E>() {
@Nullable
Holder<E> holder = null;
@Nullable
@Override
public Holder<E> getHolder() {
if (holder != null) return holder;
return holder = registrar.getHolder(getId());
}
@Override
public RegistrarManager getRegistrarManager() {
return RegistrarManager.get(modId);
}
@Override
public Registrar<E> getRegistrar() {
return registrar;
}
@Override
public ResourceLocation getRegistryId() {
return delegate.key().location();
}
@Override
public ResourceLocation getId() {
return id;
}
@Override
public boolean isPresent() {
return isPresent.getAsBoolean();
}
@Override
public E get() {
E value = (E) object.get();
if (value == null) {
throw new NullPointerException("Value missing: " + this.getId() + "@" + getRegistryId());
}
return value;
}
@Override
public int hashCode() {
return Objects.hashCode(getRegistryId(), getId());
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof RegistrySupplier<?> other)) return false;
return other.getRegistryId().equals(getRegistryId()) && other.getId().equals(getId());
}
@Override
public String toString() {
return getRegistryId() + "@" + id.toString();
}
};
}
@Override
@Nullable
public ResourceLocation getId(T obj) {
return delegate.getKey(obj);
}
@Override
public int getRawId(T obj) {
return delegate.getId(obj);
}
@Override
public Optional<ResourceKey<T>> getKey(T t) {
return delegate.getResourceKey(t);
}
@Override
@Nullable
public T get(ResourceLocation id) {
return delegate.get(id);
}
@Override
public T byRawId(int rawId) {
return delegate.byId(rawId);
}
@Override
public boolean contains(ResourceLocation resourceLocation) {
return delegate.keySet().contains(resourceLocation);
}
@Override
public boolean containsValue(T t) {
return delegate.getResourceKey(t).isPresent();
}
@Override
public Set<ResourceLocation> getIds() {
return delegate.keySet();
}
@Override
public Set<Map.Entry<ResourceKey<T>, T>> entrySet() {
return delegate.entrySet();
}
@Override
public ResourceKey<? extends Registry<T>> key() {
return delegate.key();
}
@Override
@Nullable
public Holder<T> getHolder(ResourceKey<T> key) {
return delegate.getHolder(key).orElse(null);
}
@Override
public Iterator<T> iterator() {
return delegate.iterator();
}
@Override
public void listen(ResourceLocation id, Consumer<T> callback) {
if (contains(id)) {
callback.accept(get(id));
} else {
RegistrarManagerImpl.listen(key(), id, callback);
}
}
}
}

View File

@@ -24,7 +24,7 @@ side = "BOTH"
[[dependencies.architectury]]
modId = "neoforge"
mandatory = true
versionRange = "[20.2,)"
versionRange = "[20.2.58,)"
ordering = "NONE"
side = "BOTH"