Browse Source

Add Registries#forRegistry and delay getting forge mod event bus (#82)

* Add forRegistry

Signed-off-by: shedaniel <daniel@shedaniel.me>

* Update gradle.properties
shedaniel 3 years ago
parent
commit
b0a80e0c73

+ 16 - 0
common/src/main/java/me/shedaniel/architectury/registry/Registries.java

@@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
 
 /**
  * Platform-agnostic wrapper of minecraft registries, should be used to register content.
@@ -56,6 +57,19 @@ public final class Registries {
         return this.provider.get(registry);
     }
     
+    /**
+     * Listen to registry registration, the callback is called when content should be registered.
+     * On forge, this is invoked after {@code RegistryEvent.Register}.
+     * On fabric, this is invoked immediately.
+     *
+     * @param key      the key of the registry
+     * @param callback the callback to be invoked
+     * @param <T>      the type of registry entry
+     */
+    public <T> void forRegistry(ResourceKey<net.minecraft.core.Registry<T>> key, Consumer<Registry<T>> callback) {
+        this.provider.forRegistry(key, callback);
+    }
+    
     @SafeVarargs
     public final <T extends RegistryEntry<T>> RegistryBuilder<T> builder(ResourceLocation registryId, T... typeGetter) {
         if (typeGetter.length != 0) throw new IllegalStateException("array must be empty!");
@@ -109,6 +123,8 @@ public final class Registries {
         @Deprecated
         <T> Registry<T> get(net.minecraft.core.Registry<T> registry);
         
+        <T> void forRegistry(ResourceKey<net.minecraft.core.Registry<T>> key, Consumer<Registry<T>> consumer);
+        
         <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId);
     }
 }

+ 7 - 1
fabric/src/main/java/me/shedaniel/architectury/registry/fabric/RegistriesImpl.java

@@ -40,6 +40,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 public class RegistriesImpl {
@@ -71,7 +72,12 @@ public class RegistriesImpl {
         public <T> Registry<T> get(net.minecraft.core.Registry<T> registry) {
             return new RegistryImpl<>(registry);
         }
-        
+    
+        @Override
+        public <T> void forRegistry(ResourceKey<net.minecraft.core.Registry<T>> key, Consumer<Registry<T>> consumer) {
+            consumer.accept(get(key));
+        }
+    
         @Override
         @NotNull
         public <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId) {

+ 34 - 4
forge/src/main/java/me/shedaniel/architectury/registry/forge/RegistriesImpl.java

@@ -21,6 +21,8 @@ package me.shedaniel.architectury.registry.forge;
 
 import com.google.common.base.Objects;
 import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import com.google.common.collect.Table;
 import me.shedaniel.architectury.core.RegistryEntry;
 import me.shedaniel.architectury.platform.forge.EventBuses;
@@ -49,6 +51,7 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 public class RegistriesImpl {
@@ -70,29 +73,49 @@ public class RegistriesImpl {
     
     public static class RegistryProviderImpl implements Registries.RegistryProvider {
         private final String modId;
-        private final IEventBus eventBus;
+        private final LazyLoadedValue<IEventBus> eventBus;
         private final Table<Type, RegistryObject<?>, Supplier<? extends IForgeRegistryEntry<?>>> registry = HashBasedTable.create();
+        private final Multimap<ResourceKey<net.minecraft.core.Registry<?>>, Consumer<Registry<?>>> listeners = HashMultimap.create();
         
         public RegistryProviderImpl(String modId) {
             this.modId = modId;
-            this.eventBus = EventBuses.getModEventBus(modId).orElseThrow(() -> new IllegalStateException("Can't get event bus for mod '" + modId + "' because it was not registered!"));
-            this.eventBus.register(new EventListener());
+            this.eventBus = new LazyLoadedValue<>(() -> {
+                IEventBus eventBus = EventBuses.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> Registry<T> get(ResourceKey<net.minecraft.core.Registry<T>> registryKey) {
+            updateEventBus();
             return get(RegistryManager.ACTIVE.getRegistry(registryKey.location()));
         }
         
         public <T> Registry<T> get(IForgeRegistry registry) {
+            updateEventBus();
             return new ForgeBackedRegistryImpl<>(this.registry, registry);
         }
         
         @Override
         public <T> Registry<T> get(net.minecraft.core.Registry<T> registry) {
+            updateEventBus();
             return new VanillaBackedRegistryImpl<>(registry);
         }
         
+        @Override
+        public <T> void forRegistry(ResourceKey<net.minecraft.core.Registry<T>> key, Consumer<Registry<T>> consumer) {
+            this.listeners.put((ResourceKey<net.minecraft.core.Registry<?>>) (ResourceKey<? extends net.minecraft.core.Registry<?>>) key,
+                    (Consumer<Registry<?>>) (Consumer<? extends Registry<?>>) consumer);
+        }
+        
         @Override
         public <T extends RegistryEntry<T>> RegistryBuilder<T> builder(Class<T> type, ResourceLocation registryId) {
             return new RegistryBuilderWrapper<>(this, new net.minecraftforge.registries.RegistryBuilder<>()
@@ -104,7 +127,8 @@ public class RegistriesImpl {
             @SubscribeEvent
             public void handleEvent(RegistryEvent.Register event) {
                 IForgeRegistry registry = event.getRegistry();
-                
+                Registry<Object> archRegistry = get(registry);
+    
                 for (Map.Entry<Type, Map<RegistryObject<?>, Supplier<? extends IForgeRegistryEntry<?>>>> row : RegistryProviderImpl.this.registry.rowMap().entrySet()) {
                     if (row.getKey() == event.getGenericType()) {
                         for (Map.Entry<RegistryObject<?>, Supplier<? extends IForgeRegistryEntry<?>>> entry : row.getValue().entrySet()) {
@@ -113,6 +137,12 @@ public class RegistriesImpl {
                         }
                     }
                 }
+                
+                for (Map.Entry<ResourceKey<net.minecraft.core.Registry<?>>, Consumer<Registry<?>>> entry : listeners.entries()) {
+                    if (entry.getKey().location().equals(registry.getRegistryName())) {
+                        entry.getValue().accept(archRegistry);
+                    }
+                }
             }
         }
     }

+ 1 - 1
gradle.properties

@@ -6,7 +6,7 @@ supported_version=1.16.4/5
 
 archives_base_name=architectury
 archives_base_name_snapshot=architectury-snapshot
-base_version=1.24
+base_version=1.25
 maven_group=me.shedaniel
 
 fabric_loader_version=0.11.1