22w42a RegSync changes ()

* Fix DynamicRegistrySetupCallback, add EndDynamicRegistrySetupCallback

`DynamicRegistrySetupCallback` did not work as intended because the injection
was too late. This moves the injection point to `RegistryLoader`, just before it
is loaded.

`EndDynamicRegistrySetupCallback` is a new event triggered when the loading is
finished. This has access to the combined DRM, allowing context-aware modification.

This also replaces `System.out.println` use in testmod.

* Remove useless force-init of BiomeKeys

* Remove now-unnecessary DynamicRegistryManagerMixin

* Fix crash in testmod

This caveat needs proper documentation.

* Add note to javadoc

* Mark impl as internal

* Remove EndDynamicRegistrySetupCallback

* Fix testmod checkstyle issues

* Add automated event call check

* Fix test

* Update javadoc

* Add `@see`

* Re-run actions
This commit is contained in:
apple502j 2022-10-29 02:24:56 +09:00 committed by GitHub
parent 11ba9c3b22
commit 33c37e23ce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 132 additions and 61 deletions
fabric-registry-sync-v0

View file

@ -9,3 +9,7 @@ moduleDependencies(project, [
'fabric-api-base',
'fabric-networking-api-v1'
])
testDependencies(project, [
':fabric-lifecycle-events-v1'
])

View file

@ -29,13 +29,21 @@ import net.fabricmc.fabric.api.event.EventFactory;
* <pre>
* {@code
* DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
* Registry<Biome> biomes = registryManager.get(Registry.BIOME_KEY);
* RegistryEntryAddedCallback.event(biomes).register((rawId, id, object) -> {
* // Do something
* registryManager.getOptional(Registry.BIOME_KEY).ifPresent(biomes -> {
* RegistryEntryAddedCallback.event(biomes).register((rawId, id, object) -> {
* // Do something
* });
* });
* });
* }
* </pre>
*
* <p><strong>Important Note</strong>: The passed dynamic registry manager might not
* contain the registry, as this event is invoked for each layer of
* the combined registry manager, and each layer holds different registries.
* Use {@link DynamicRegistryManager#getOptional} to prevent crashes.
*
* @see net.minecraft.util.registry.ServerDynamicRegistryType
*/
@FunctionalInterface
public interface DynamicRegistrySetupCallback {

View file

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* Contains the Registry Sync implementation.
*/
@ApiStatus.Internal
package net.fabricmc.fabric.impl.registry.sync;
import org.jetbrains.annotations.ApiStatus;

View file

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* Contains packet handlers used by Registry Sync.
*/
@ApiStatus.Internal
package net.fabricmc.fabric.impl.registry.sync.packet;
import org.jetbrains.annotations.ApiStatus;

View file

@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* Contains remap state trackers.
*/
@ApiStatus.Internal
package net.fabricmc.fabric.impl.registry.sync.trackers;
import org.jetbrains.annotations.ApiStatus;

View file

@ -18,6 +18,8 @@ package net.fabricmc.fabric.impl.registry.sync.trackers.vanilla;
import java.util.List;
import org.jetbrains.annotations.ApiStatus;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
@ -27,6 +29,7 @@ import net.minecraft.util.registry.Registry;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
import net.fabricmc.fabric.mixin.registry.sync.DebugChunkGeneratorAccessor;
@ApiStatus.Internal
public final class BlockInitTracker implements RegistryEntryAddedCallback<Block> {
private final Registry<Block> registry;

View file

@ -16,6 +16,8 @@
package net.fabricmc.fabric.impl.registry.sync.trackers.vanilla;
import org.jetbrains.annotations.ApiStatus;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.util.Identifier;
@ -23,6 +25,7 @@ import net.minecraft.util.registry.Registry;
import net.fabricmc.fabric.api.event.registry.RegistryEntryAddedCallback;
@ApiStatus.Internal
public final class BlockItemTracker implements RegistryEntryAddedCallback<Item> {
private BlockItemTracker() { }

View file

@ -29,7 +29,6 @@ import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.Fluids;
import net.minecraft.item.Items;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.BiomeKeys;
import net.fabricmc.fabric.impl.registry.sync.RegistrySyncManager;
import net.fabricmc.fabric.impl.registry.sync.trackers.StateIdTracker;
@ -44,7 +43,6 @@ public class BootstrapMixin {
// static initializer is called, to register vanilla-provided blocks
// and items from the respective classes - otherwise, they would
// duplicate our calls from below.
Object oBiome = BiomeKeys.THE_END;
Object oBlock = Blocks.AIR;
Object oFluid = Fluids.EMPTY;
Object oItem = Items.AIR;

View file

@ -1,35 +0,0 @@
/*
* 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.util.registry.DynamicRegistryManager;
@Mixin(DynamicRegistryManager.class)
public interface DynamicRegistryManagerMixin {
/**
* Ensures that any registrations made into {@link net.minecraft.util.registry.BuiltinRegistries} after
* {@link DynamicRegistryManager} has been class-loaded are still propagated.
*/
/* TODO 22w42a not needed?
@Inject(method = "method_40327", at = @At(value = "RETURN"))
private static void setupBuiltInSync(CallbackInfoReturnable<DynamicRegistryManager.Immutable> cir) {
DynamicRegistrySync.setupSync(cir.getReturnValue());
}
*/
}

View file

@ -17,27 +17,32 @@
package net.fabricmc.fabric.mixin.registry.sync;
import java.util.List;
import java.util.Map;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.util.registry.CombinedDynamicRegistries;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.RegistryLoader;
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
@Mixin(CombinedDynamicRegistries.class)
public class CombinedDynamicRegistriesMixin {
@Shadow
@Final
private DynamicRegistryManager.Immutable combinedRegistryManager;
@Inject(method = "<init>(Ljava/util/List;Ljava/util/List;)V", at = @At("RETURN"))
private void init(List list, List list2, CallbackInfo ci) {
DynamicRegistrySetupCallback.EVENT.invoker().onRegistrySetup(this.combinedRegistryManager);
@Mixin(RegistryLoader.class)
public class RegistryLoaderMixin {
@Inject(
method = "load(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/registry/DynamicRegistryManager;Ljava/util/List;)Lnet/minecraft/util/registry/DynamicRegistryManager$Immutable;",
at = @At(
value = "INVOKE",
target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V",
ordinal = 0
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private static void beforeLoad(ResourceManager resourceManager, DynamicRegistryManager baseRegistryManager, List<RegistryLoader.Entry<?>> entries, CallbackInfoReturnable<DynamicRegistryManager.Immutable> cir, Map a, List b, DynamicRegistryManager registryManager) {
DynamicRegistrySetupCallback.EVENT.invoker().onRegistrySetup(registryManager);
}
}

View file

@ -3,17 +3,16 @@
"package": "net.fabricmc.fabric.mixin.registry.sync",
"compatibilityLevel": "JAVA_16",
"mixins": [
"DebugChunkGeneratorAccessor",
"RegistryAccessor",
"BootstrapMixin",
"BuiltinRegistriesMixin",
"ChunkSerializerMixin",
"DynamicRegistryManagerMixin",
"DebugChunkGeneratorAccessor",
"IdListMixin",
"SimpleRegistryMixin",
"LevelStorageSessionMixin",
"RegistryMixin",
"MinecraftServerMixin",
"RegistryAccessor",
"RegistryLoaderMixin",
"RegistryMixin",
"SimpleRegistryMixin",
"StructuresToConfiguredStructuresFixMixin"
],

View file

@ -17,9 +17,12 @@
package net.fabricmc.fabric.test.registry.sync;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
@ -36,6 +39,7 @@ 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.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
import net.fabricmc.fabric.api.event.registry.FabricRegistryBuilder;
import net.fabricmc.fabric.api.event.registry.RegistryAttribute;
@ -49,6 +53,8 @@ import net.fabricmc.fabric.impl.registry.sync.packet.NbtRegistryPacketHandler;
import net.fabricmc.fabric.impl.registry.sync.packet.RegistryPacketHandler;
public class RegistrySyncTest implements ModInitializer {
private static final Logger LOGGER = LogUtils.getLogger();
/**
* These are system property's as it allows for easier testing with different run configurations.
*/
@ -109,12 +115,23 @@ public class RegistrySyncTest implements ModInitializer {
Validate.isTrue(RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.SYNCED));
Validate.isTrue(!RegistryAttributeHolder.get(fabricRegistry).hasAttribute(RegistryAttribute.PERSISTED));
final AtomicBoolean setupCalled = new AtomicBoolean(false);
DynamicRegistrySetupCallback.EVENT.register(registryManager -> {
RegistryEntryAddedCallback.event(registryManager.get(Registry.BIOME_KEY)).register((rawId, id, object) -> {
System.out.println(id);
setupCalled.set(true);
registryManager.getOptional(Registry.BIOME_KEY).ifPresent(registry -> {
RegistryEntryAddedCallback.event(registry).register((rawId, id, object) -> {
LOGGER.info("Biome added: {}", id);
});
});
});
ServerLifecycleEvents.SERVER_STARTING.register(server -> {
if (!setupCalled.get()) {
throw new IllegalStateException("DRM setup was not called before startup!");
}
});
// Vanilla status effects don't have an entry for the int id 0, test we can handle this.
RegistryAttributeHolder.get(Registry.STATUS_EFFECT).addAttribute(RegistryAttribute.MODDED);
}
@ -136,7 +153,7 @@ public class RegistrySyncTest implements ModInitializer {
* class-loaded.
*/
private void testBuiltInRegistrySync() {
System.out.println("Checking built-in registry sync...");
LOGGER.info("Checking built-in registry sync...");
// Register a configured feature before force-loading the dynamic registry manager
ConfiguredFeature<DefaultFeatureConfig, ?> cf1 = new ConfiguredFeature<>(Feature.BASALT_PILLAR, DefaultFeatureConfig.INSTANCE);