mirror of
https://github.com/architectury/architectury-api.git
synced 2026-03-28 03:56:59 -05:00
Update to 20.2.59-beta & Adapt to Registry Changes
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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()) {
|
||||
@@ -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());
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ side = "BOTH"
|
||||
[[dependencies.architectury]]
|
||||
modId = "neoforge"
|
||||
mandatory = true
|
||||
versionRange = "[20.2,)"
|
||||
versionRange = "[20.2.58,)"
|
||||
ordering = "NONE"
|
||||
side = "BOTH"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user