diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/FabricRegistry.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/FabricRegistry.java
new file mode 100644
index 0000000000..1021921e09
--- /dev/null
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/api/event/registry/FabricRegistry.java
@@ -0,0 +1,41 @@
+/*
+ * 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 org.jetbrains.annotations.ApiStatus;
+
+import net.minecraft.registry.Registry;
+import net.minecraft.util.Identifier;
+
+/**
+ * General-purpose Fabric-provided extensions for {@link Registry} objects.
+ *
+ *
Note: This interface is automatically implemented on all registries via Mixin and interface injection.
+ */
+@ApiStatus.NonExtendable
+public interface FabricRegistry {
+ /**
+ * Adds an alias for an entry in this registry. Once added, all queries to this registry that refer to the {@code old}
+ * {@link Identifier} will be redirected towards {@code newId}. This is useful if a mod wants to change an ID without
+ * breaking compatibility with existing worlds.
+ * @param old the {@link Identifier} that will become an alias for {@code newId}
+ * @param newId the {@link Identifier} for which {@code old} will become an alias
+ */
+ default void addAlias(Identifier old, Identifier newId) {
+ throw new UnsupportedOperationException("implemented via mixin");
+ }
+}
diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/RegistryMixin.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/RegistryMixin.java
new file mode 100644
index 0000000000..4aeeb24a70
--- /dev/null
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/RegistryMixin.java
@@ -0,0 +1,27 @@
+/*
+ * 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 net.minecraft.registry.Registry;
+
+import net.fabricmc.fabric.api.event.registry.FabricRegistry;
+
+@Mixin(Registry.class)
+public interface RegistryMixin extends FabricRegistry {
+}
diff --git a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/SimpleRegistryMixin.java b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/SimpleRegistryMixin.java
index 0d59e39b85..13d14fb6e1 100644
--- a/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/SimpleRegistryMixin.java
+++ b/fabric-registry-sync-v0/src/main/java/net/fabricmc/fabric/mixin/registry/sync/SimpleRegistryMixin.java
@@ -18,8 +18,10 @@
import java.util.ArrayList;
import java.util.Comparator;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
@@ -43,6 +45,7 @@
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -56,6 +59,7 @@
import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;
+import net.fabricmc.fabric.api.event.registry.FabricRegistry;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
import net.fabricmc.fabric.api.event.registry.RegistryAttributeHolder;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
@@ -67,7 +71,7 @@
import net.fabricmc.fabric.impl.registry.sync.RemappableRegistry;
@Mixin(SimpleRegistry.class)
-public abstract class SimpleRegistryMixin implements MutableRegistry, RemappableRegistry, ListenableRegistry {
+public abstract class SimpleRegistryMixin implements MutableRegistry, RemappableRegistry, ListenableRegistry, FabricRegistry {
// Namespaces used by the vanilla game. "brigadier" is used by command argument type registry.
// While Realms use "realms" namespace, it is irrelevant for Registry Sync.
@Unique
@@ -111,6 +115,22 @@ public abstract class SimpleRegistryMixin implements MutableRegistry, Rema
private Object2IntMap fabric_prevIndexedEntries;
@Unique
private BiMap> fabric_prevEntries;
+ @Unique
+ // invariant: the sets of keys and values are disjoint (every alias points to a 'deepest' non-alias ID)
+ private Map aliases = new HashMap<>();
+
+ @Shadow
+ public abstract boolean containsId(Identifier id);
+
+ @Shadow
+ public abstract String toString();
+
+ @Shadow
+ @Final
+ private RegistryKey extends Registry> key;
+
+ @Shadow
+ protected abstract void assertNotFrozen();
@Override
public Event> fabric_getAddObjectEvent() {
@@ -131,6 +151,18 @@ private void init(RegistryKey key, Lifecycle lifecycle, boolean intrusive, Callb
}
}
);
+ // aliasing: check that no new entries use the id of an alias
+ fabric_addObjectEvent.register((rawId, id, object) -> {
+ if (aliases.containsKey(id)) {
+ throw new IllegalArgumentException(
+ "Tried registering %s to registry %s, but it is already an alias (for %s)".formatted(
+ id,
+ this.key,
+ aliases.get(id)
+ )
+ );
+ }
+ });
fabric_postRemapEvent = EventFactory.createArrayBacked(RegistryIdRemapCallback.class,
(callbacks) -> (a) -> {
for (RegistryIdRemapCallback callback : callbacks) {
@@ -174,7 +206,7 @@ public void remap(String name, Object2IntMap remoteIndexedEntries, R
List strings = null;
for (Identifier remoteId : remoteIndexedEntries.keySet()) {
- if (!idToEntry.containsKey(remoteId)) {
+ if (!this.containsId(remoteId)) {
if (strings == null) {
strings = new ArrayList<>();
}
@@ -382,4 +414,94 @@ public void unmap(String name) throws RemapException {
fabric_prevEntries = null;
}
}
+
+ @Override
+ public void addAlias(Identifier old, Identifier newId) {
+ Objects.requireNonNull(old, "alias cannot be null");
+ Objects.requireNonNull(newId, "aliased id cannot be null");
+
+ if (aliases.containsKey(old)) {
+ throw new IllegalArgumentException(
+ "Tried adding %s as an alias for %s, but it is already an alias (for %s) in registry %s".formatted(
+ old,
+ newId,
+ aliases.get(old),
+ this.key
+ )
+ );
+ }
+
+ if (this.idToEntry.containsKey(old)) {
+ throw new IllegalArgumentException(
+ "Tried adding %s as an alias, but it is already present in registry %s".formatted(
+ old,
+ this.key
+ )
+ );
+ }
+
+ if (old.equals(aliases.get(newId))) {
+ // since an alias corresponds to at most one identifier, this is the only way to create a cycle
+ // that doesn't already fall under the first condition
+ throw new IllegalArgumentException(
+ "Making %1$s an alias of %2$s would create a cycle, as %2$s is already an alias of %1$s (registry %3$s)".formatted(
+ old,
+ newId,
+ this.key
+ )
+ );
+ }
+
+ if (!this.idToEntry.containsKey(newId)) {
+ FABRIC_LOGGER.warn(
+ "Adding {} as an alias for {}, but the latter doesn't exist in registry {}",
+ old,
+ newId,
+ this.key
+ );
+ }
+
+ assertNotFrozen();
+
+ // recompute alias map to preserve invariant, i.e. make sure all keys point to a non-alias ID
+ Identifier deepest = aliases.getOrDefault(newId, newId);
+
+ for (Map.Entry entry : aliases.entrySet()) {
+ if (old.equals(entry.getValue())) {
+ entry.setValue(deepest);
+ }
+ }
+
+ aliases.put(old, deepest);
+ FABRIC_LOGGER.debug("Adding alias {} for {} in registry {}", old, newId, this.key);
+ }
+
+ @ModifyVariable(
+ method = {
+ "getEntry(Lnet/minecraft/util/Identifier;)Ljava/util/Optional;",
+ "get(Lnet/minecraft/util/Identifier;)Ljava/lang/Object;",
+ "containsId"
+ },
+ at = @At("HEAD"),
+ argsOnly = true
+ )
+ private Identifier aliasIdentifierParameter(Identifier original) {
+ return aliases.getOrDefault(original, original);
+ }
+
+ @ModifyVariable(
+ method = {
+ "get(Lnet/minecraft/registry/RegistryKey;)Ljava/lang/Object;",
+ "getOptional(Lnet/minecraft/registry/RegistryKey;)Ljava/util/Optional;",
+ "getOrCreateEntry",
+ "contains",
+ "getEntryInfo"
+ },
+ at = @At("HEAD"),
+ argsOnly = true
+ )
+ private RegistryKey aliasRegistryKeyParameter(RegistryKey original) {
+ Identifier aliased = aliases.get(original.getValue());
+ return aliased == null ? original : RegistryKey.of(original.getRegistryRef(), aliased);
+ }
}
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 d8d12369ef..c51948bd22 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
@@ -14,6 +14,7 @@
"RegistriesMixin",
"RegistryKeysMixin",
"RegistryLoaderMixin",
+ "RegistryMixin",
"SaveLoadingMixin",
"SerializableRegistriesMixin",
"SimpleRegistryAccessor",
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 f05a08c73b..d12176c365 100644
--- a/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
+++ b/fabric-registry-sync-v0/src/main/resources/fabric.mod.json
@@ -38,6 +38,9 @@
},
"accessWidener": "fabric-registry-sync-v0.accesswidener",
"custom": {
- "fabric-api:module-lifecycle": "stable"
+ "fabric-api:module-lifecycle": "stable",
+ "loom:injected_interfaces": {
+ "net/minecraft/class_2378": ["net/fabricmc/fabric/api/event/registry/FabricRegistry"]
+ }
}
}
diff --git a/fabric-registry-sync-v0/src/test/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java b/fabric-registry-sync-v0/src/test/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java
new file mode 100644
index 0000000000..346c09914f
--- /dev/null
+++ b/fabric-registry-sync-v0/src/test/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java
@@ -0,0 +1,103 @@
+/*
+ * 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.test.registry.sync;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.UUID;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import net.minecraft.Bootstrap;
+import net.minecraft.SharedConstants;
+import net.minecraft.registry.Registry;
+import net.minecraft.registry.RegistryKey;
+import net.minecraft.util.Identifier;
+
+import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
+
+public class RegistryAliasTest {
+ private static final Identifier OBSOLETE_ID = id("obsolete");
+ private static final Identifier NEW_ID = id("new");
+ private static final Identifier OTHER = id("other");
+ private RegistryKey> testRegistryKey;
+ private Registry testRegistry;
+
+ @BeforeAll
+ static void beforeAll() {
+ SharedConstants.createGameVersion();
+ Bootstrap.initialize();
+ }
+
+ private static Identifier id(String s) {
+ return Identifier.of("registry_sync_test_alias_test", s);
+ }
+
+ @BeforeEach
+ void beforeEach() {
+ testRegistryKey = RegistryKey.ofRegistry(id(UUID.randomUUID().toString()));
+ testRegistry = Mockito.spy(FabricRegistryBuilder.createSimple(testRegistryKey).buildAndRegister());
+
+ Registry.register(testRegistry, NEW_ID, "entry");
+ Registry.register(testRegistry, OTHER, "other");
+ testRegistry.addAlias(OBSOLETE_ID, NEW_ID);
+ }
+
+ @Test
+ void testAlias() {
+ RegistryKey obsoleteKey = RegistryKey.of(testRegistryKey, OBSOLETE_ID);
+
+ assertTrue(testRegistry.containsId(OBSOLETE_ID));
+ assertFalse(testRegistry.getIds().contains(OBSOLETE_ID));
+ assertEquals("entry", testRegistry.get(OBSOLETE_ID));
+ assertEquals("entry", testRegistry.get(obsoleteKey));
+
+ Identifier moreObsolete = id("more_obsolete");
+ assertFalse(testRegistry.containsId(moreObsolete));
+
+ testRegistry.addAlias(moreObsolete, OBSOLETE_ID);
+
+ assertTrue(testRegistry.containsId(moreObsolete));
+ assertEquals("entry", testRegistry.get(moreObsolete));
+ }
+
+ @Test
+ void forbidAmbiguousAlias() {
+ assertThrows(IllegalArgumentException.class, () -> testRegistry.addAlias(OBSOLETE_ID, OTHER));
+ }
+
+ @Test
+ void forbidCircularAliases() {
+ assertThrows(IllegalArgumentException.class, () -> testRegistry.addAlias(NEW_ID, OBSOLETE_ID));
+ }
+
+ @Test
+ void forbidExistingIdAsAlias() {
+ assertThrows(IllegalArgumentException.class, () -> testRegistry.addAlias(NEW_ID, OTHER));
+ }
+
+ @Test
+ void forbidOverridingAliasWithEntry() {
+ assertThrows(IllegalArgumentException.class, () -> Registry.register(testRegistry, OBSOLETE_ID, "obsolete"));
+ }
+}
diff --git a/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java b/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java
new file mode 100644
index 0000000000..2f35e2da2a
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/java/net/fabricmc/fabric/test/registry/sync/RegistryAliasTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.test.registry.sync;
+
+import com.mojang.logging.LogUtils;
+import org.slf4j.Logger;
+
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.Block;
+import net.minecraft.item.BlockItem;
+import net.minecraft.item.Item;
+import net.minecraft.registry.Registries;
+import net.minecraft.registry.Registry;
+import net.minecraft.registry.RegistryKey;
+import net.minecraft.registry.RegistryKeys;
+import net.minecraft.util.Identifier;
+
+import net.fabricmc.api.ModInitializer;
+
+public class RegistryAliasTest implements ModInitializer {
+ private static final Logger LOGGER = LogUtils.getLogger();
+ public static final boolean USE_OLD_IDS = Boolean.parseBoolean(System.getProperty("fabric.registry.sync.test.alias.use_old_ids", "true"));
+ public static final Identifier OLD_TEST_INGOT = id("test_ingot_old");
+ public static final Identifier TEST_INGOT = id("test_ingot");
+ public static final Identifier OLD_TEST_BLOCK = id("test_block_old");
+ public static final Identifier TEST_BLOCK = id("test_block");
+
+ @Override
+ public void onInitialize() {
+ if (USE_OLD_IDS) {
+ LOGGER.info("Registering old IDs");
+ register(OLD_TEST_BLOCK, OLD_TEST_INGOT);
+ } else {
+ LOGGER.info("Registering new IDs");
+ register(TEST_BLOCK, TEST_INGOT);
+ LOGGER.info("Adding aliases");
+ Registries.BLOCK.addAlias(OLD_TEST_BLOCK, TEST_BLOCK);
+ Registries.ITEM.addAlias(OLD_TEST_BLOCK, TEST_BLOCK);
+ Registries.ITEM.addAlias(OLD_TEST_INGOT, TEST_INGOT);
+ }
+
+ Registries.ITEM.addAlias(Identifier.of("old_stone"), Identifier.of("stone"));
+ }
+
+ private static void register(Identifier blockId, Identifier itemId) {
+ Block block = new Block(AbstractBlock.Settings.create().registryKey(RegistryKey.of(RegistryKeys.BLOCK, blockId)));
+ Registry.register(Registries.BLOCK, blockId, block);
+ BlockItem blockItem = new BlockItem(block, new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, blockId)));
+ Registry.register(Registries.ITEM, blockId, blockItem);
+ Item item = new Item(new Item.Settings().registryKey(RegistryKey.of(RegistryKeys.ITEM, itemId)));
+ Registry.register(Registries.ITEM, itemId, item);
+ }
+
+ private static Identifier id(String path) {
+ return Identifier.of("registry_sync_alias_test", path);
+ }
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block.json
new file mode 100644
index 0000000000..cb3897dc29
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/iron_block"
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block_old.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block_old.json
new file mode 100644
index 0000000000..cb3897dc29
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/block/test_block_old.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/iron_block"
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block.json
new file mode 100644
index 0000000000..cb3897dc29
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/iron_block"
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block_old.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block_old.json
new file mode 100644
index 0000000000..cb3897dc29
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_block_old.json
@@ -0,0 +1,3 @@
+{
+ "parent": "minecraft:block/iron_block"
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot.json
new file mode 100644
index 0000000000..eea043008a
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:item/handheld",
+ "textures": {
+ "layer0": "minecraft:item/copper_ingot"
+ }
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot_old.json b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot_old.json
new file mode 100644
index 0000000000..eea043008a
--- /dev/null
+++ b/fabric-registry-sync-v0/src/testmod/resources/assets/fabric-registry-sync-v0-testmod/models/item/test_ingot_old.json
@@ -0,0 +1,6 @@
+{
+ "parent": "minecraft:item/handheld",
+ "textures": {
+ "layer0": "minecraft:item/copper_ingot"
+ }
+}
diff --git a/fabric-registry-sync-v0/src/testmod/resources/fabric.mod.json b/fabric-registry-sync-v0/src/testmod/resources/fabric.mod.json
index 57745d0628..175286412e 100644
--- a/fabric-registry-sync-v0/src/testmod/resources/fabric.mod.json
+++ b/fabric-registry-sync-v0/src/testmod/resources/fabric.mod.json
@@ -14,7 +14,8 @@
"entrypoints": {
"main": [
"net.fabricmc.fabric.test.registry.sync.CustomDynamicRegistryTest",
- "net.fabricmc.fabric.test.registry.sync.RegistrySyncTest"
+ "net.fabricmc.fabric.test.registry.sync.RegistrySyncTest",
+ "net.fabricmc.fabric.test.registry.sync.RegistryAliasTest"
],
"client": [
"net.fabricmc.fabric.test.registry.sync.client.DynamicRegistryClientTest"