diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/DynamicRegistrySetupCallback.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/DynamicRegistrySetupCallback.java
new file mode 100644
index 000000000..d16aea52e
--- /dev/null
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/DynamicRegistrySetupCallback.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.api.event.registry;
+
+import net.minecraft.util.registry.DynamicRegistryManager;
+
+import net.fabricmc.fabric.api.event.Event;
+import net.fabricmc.fabric.api.event.EventFactory;
+
+/**
+ * This event gets triggered when a new {@link DynamicRegistryManager} gets created, but before it gets filled.
+ * Therefore, this is the ideal place to register callbacks to dynamic registries.
+ * For example, the following code is used to register a callback that gets triggered for any registered Biome, both JSON and code defined.
+ *
+ *
+ * {@code
+ * DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
+ * Registry biomes = registryManager.get(Registry.BIOME_KEY);
+ * RegistryEntryAddedCallback.event(biomes).register((rawId, id, object) -> {
+ * // Do something
+ * });
+ * });
+ * }
+ *
+ */
+@FunctionalInterface
+public interface DynamicRegistrySetupCallback {
+ void onRegistrySetup(DynamicRegistryManager registryManager);
+
+ Event EVENT = EventFactory.createArrayBacked(
+ DynamicRegistrySetupCallback.class,
+ callbacks -> registryManager -> {
+ for (DynamicRegistrySetupCallback callback : callbacks) {
+ callback.onRegistrySetup(registryManager);
+ }
+ }
+ );
+}
diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/DynamicRegistryManagerMixin.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/DynamicRegistryManagerMixin.java
new file mode 100644
index 000000000..58df768d5
--- /dev/null
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/DynamicRegistryManagerMixin.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, 2017, 2018, 2019 FabricMC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.fabricmc.fabric.mixin.registry.sync;
+
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
+import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
+
+import net.minecraft.util.registry.DynamicRegistryManager;
+
+import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
+
+@Mixin(DynamicRegistryManager.class)
+public class DynamicRegistryManagerMixin {
+ @Inject(method = "create", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/dynamic/RegistryOps$class_5506$class_5507;()V"), locals = LocalCapture.CAPTURE_FAILHARD)
+ private static void onCreateImpl(CallbackInfoReturnable cir, DynamicRegistryManager.Impl registryManager) {
+ DynamicRegistrySetupCallback.EVENT.invoker().onRegistrySetup(registryManager);
+ }
+}
diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/MixinIdRegistry.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/MixinIdRegistry.java
index 441504b32..a39365139 100644
--- a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/MixinIdRegistry.java
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/MixinIdRegistry.java
@@ -45,8 +45,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
-import net.minecraft.util.registry.SimpleRegistry;
import net.minecraft.util.registry.RegistryKey;
+import net.minecraft.util.registry.SimpleRegistry;
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
@@ -132,8 +132,8 @@ public abstract class MixinIdRegistry extends Registry implements Remappab
@Unique
private boolean fabric_isObjectNew = false;
- @Inject(method = "set", at = @At("HEAD"))
- public void setPre(int id, RegistryKey registryId, T object, Lifecycle lifecycle, CallbackInfoReturnable info) {
+ @Inject(method = "set(ILnet/minecraft/util/registry/RegistryKey;Ljava/lang/Object;Lcom/mojang/serialization/Lifecycle;Z)Ljava/lang/Object;", at = @At("HEAD"))
+ public void setPre(int id, RegistryKey registryId, T object, Lifecycle lifecycle, boolean checkDuplicateKeys, CallbackInfoReturnable info) {
int indexedEntriesId = entryToRawId.getInt(object);
if (indexedEntriesId >= 0) {
@@ -148,7 +148,7 @@ public abstract class MixinIdRegistry extends Registry implements Remappab
if (oldObject != null && oldObject != object) {
int oldId = entryToRawId.getInt(oldObject);
- if (oldId != id) {
+ if (oldId != id && checkDuplicateKeys) {
throw new RuntimeException("Attempted to register ID " + registryId + " at different raw IDs (" + oldId + ", " + id + ")! If you're trying to override an item, use .set(), not .register()!");
}
@@ -160,8 +160,8 @@ public abstract class MixinIdRegistry extends Registry implements Remappab
}
}
- @Inject(method = "set", at = @At("RETURN"))
- public void setPost(int id, RegistryKey registryId, T object, Lifecycle lifecycle, CallbackInfoReturnable info) {
+ @Inject(method = "set(ILnet/minecraft/util/registry/RegistryKey;Ljava/lang/Object;Lcom/mojang/serialization/Lifecycle;Z)Ljava/lang/Object;", at = @At("RETURN"))
+ public void setPost(int id, RegistryKey registryId, T object, Lifecycle lifecycle, boolean checkDuplicateKeys, CallbackInfoReturnable info) {
if (fabric_isObjectNew) {
fabric_addObjectEvent.invoker().onEntryAdded(id, registryId.getValue(), object);
}
diff --git a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
index 435ba89ee..ce24616b0 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric-registry-sync-v0.mixins.json
@@ -11,7 +11,8 @@
"MixinPlayerManager",
"MixinLevelStorageSession",
"MixinRegistry",
- "MixinSimpleRegistry"
+ "MixinSimpleRegistry",
+ "DynamicRegistryManagerMixin"
],
"client": [
"client.MixinBlockColorMap",
diff --git a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
index 6fa2597a5..cb03233b2 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
@@ -16,7 +16,7 @@
"FabricMC"
],
"depends": {
- "fabricloader": ">=0.4.0",
+ "fabricloader": ">=0.9.2",
"fabric-api-base": "*",
"fabric-networking-v0": "*"
},
diff --git a/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistrySyncTest.java b/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistrySyncTest.java
index 6a687784c..b85bc1731 100644
--- a/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistrySyncTest.java
+++ b/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistrySyncTest.java
@@ -34,9 +34,11 @@ import net.minecraft.world.gen.feature.DefaultFeatureConfig;
import net.minecraft.world.gen.feature.Feature;
import net.fabricmc.api.ModInitializer;
+import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
import net.fabricmc.fabric.api.event.registry.RegistryAttributeHolder;
+import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
public class RegistrySyncTest implements ModInitializer {
/**
@@ -73,9 +75,17 @@ public class RegistrySyncTest implements ModInitializer {
Registry.register(fabricRegistry, new Identifier("registry_sync", "test"), "test");
+ Validate.isTrue(Registry.REGISTRIES.getIds().contains(new Identifier("registry_sync", "fabric_registry")));
+
Validate.isTrue(RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.MODDED));
Validate.isTrue(RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.SYNCED));
Validate.isTrue(!RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.PERSISTED));
+
+ DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
+ RegistryEntryAddedCallback.event(registryManager.get(Registry.BIOME_KEY)).register((rawId, id, object) -> {
+ System.out.println(id);
+ });
+ });
}
/**