Remove SurfaceBuilder related APIs.

Remove PersistentDynamicRegistryHandler as the bug (MC-202036) it fixed was fixed a few weeks ago.
This commit is contained in:
modmuss50 2021-10-13 18:55:15 +01:00
parent b43623a4c6
commit bb09662468
15 changed files with 12 additions and 407 deletions
build.gradle
fabric-biome-api-v1
fabric-registry-sync-v0

View file

@ -9,7 +9,7 @@ plugins {
id "eclipse"
id "idea"
id "maven-publish"
id "fabric-loom" version "0.10.23" apply false
id "fabric-loom" version "0.10.31" apply false
id "org.cadixdev.licenser" version "0.6.1"
id "org.ajoberstar.grgit" version "3.1.0"
id "com.matthewprenger.cursegradle" version "1.4.0"
@ -19,8 +19,8 @@ plugins {
def ENV = System.getenv()
class Globals {
static def baseVersion = "0.40.8"
static def mcVersion = "21w40a"
static def baseVersion = "0.40.9"
static def mcVersion = "21w41a"
static def yarnVersion = "+build.1"
static def loaderVersion = "0.11.7"
static def preRelease = true
@ -264,6 +264,7 @@ subprojects {
afterEvaluate {
genSources.enabled = false
genSourcesWithCfr.enabled = false
unpickJar.enabled = false
}
}

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-biome-api-v1"
version = getSubprojectVersion(project, "4.0.3")
version = getSubprojectVersion(project, "5.0.0")
loom {
accessWidenerPath = file("src/main/resources/fabric-biome-api-v1.accesswidener")

View file

@ -38,8 +38,6 @@ import net.minecraft.world.gen.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.feature.StructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders;
import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys;
@ -288,23 +286,6 @@ public interface BiomeModificationContext {
}
interface GenerationSettingsContext {
/**
* Sets the biomes surface builder to a surface builder registered in {@link BuiltinRegistries#CONFIGURED_SURFACE_BUILDER}.
*
* <p>This method is intended for use with the surface builders found in {@link ConfiguredSurfaceBuilders}.
*
* <p><b>NOTE:</b> In case the configured surface builder is overridden in a datapack, the datapacks version
* will be used.
*/
default void setBuiltInSurfaceBuilder(ConfiguredSurfaceBuilder<?> configuredSurfaceBuilder) {
setSurfaceBuilder(BuiltInRegistryKeys.get(configuredSurfaceBuilder));
}
/**
* Sets the biomes surface builder to the surface builder identified by the given key.
*/
void setSurfaceBuilder(RegistryKey<ConfiguredSurfaceBuilder<?>> surfaceBuilderKey);
/**
* Removes a feature from one of this biomes generation steps, and returns if any features were removed.
*/

View file

@ -24,8 +24,6 @@ import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders;
import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys;
@ -43,30 +41,6 @@ public interface BiomeSelectionContext {
*/
Biome getBiome();
/**
* Returns true if this biome uses the given built-in surface builder, which must be registered
* in the {@link net.minecraft.util.registry.BuiltinRegistries}.
*
* <p>This method is intended for use with the Vanilla surface builders found in {@link ConfiguredSurfaceBuilders}.
*/
default boolean hasBuiltInSurfaceBuilder(ConfiguredSurfaceBuilder<?> surfaceBuilder) {
RegistryKey<ConfiguredSurfaceBuilder<?>> key = BuiltInRegistryKeys.get(surfaceBuilder);
return hasSurfaceBuilder(key);
}
/**
* Returns true if this biome uses a surface builder that has the given key.
*/
default boolean hasSurfaceBuilder(RegistryKey<ConfiguredSurfaceBuilder<?>> key) {
return getSurfaceBuilderKey().orElse(null) == key;
}
/**
* Tries to retrieve the registry key for this biomes current surface builder, which may be empty, if the
* surface builder is not registered.
*/
Optional<RegistryKey<ConfiguredSurfaceBuilder<?>>> getSurfaceBuilderKey();
/**
* Returns true if this biome has the given configured feature, which must be registered
* in the {@link net.minecraft.util.registry.BuiltinRegistries}.

View file

@ -52,7 +52,6 @@ import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.StructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext;
import net.fabricmc.fabric.mixin.biome.modification.BiomeAccessor;
@ -220,7 +219,6 @@ public class BiomeModificationContextImpl implements BiomeModificationContext {
private final Registry<ConfiguredCarver<?>> carvers = registries.get(Registry.CONFIGURED_CARVER_KEY);
private final Registry<ConfiguredFeature<?, ?>> features = registries.get(Registry.CONFIGURED_FEATURE_KEY);
private final Registry<ConfiguredStructureFeature<?, ?>> structures = registries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
private final Registry<ConfiguredSurfaceBuilder<?>> surfaceBuilders = registries.get(Registry.CONFIGURED_SURFACE_BUILDER_KEY);
private final GenerationSettings generationSettings = biome.getGenerationSettings();
private final GenerationSettingsAccessor accessor = (GenerationSettingsAccessor) generationSettings;
@ -301,13 +299,6 @@ public class BiomeModificationContextImpl implements BiomeModificationContext {
accessor.fabric_setFlowerFeatures(ImmutableList.copyOf(accessor.fabric_getFlowerFeatures()));
}
@Override
public void setSurfaceBuilder(RegistryKey<ConfiguredSurfaceBuilder<?>> surfaceBuilderKey) {
// We do not need to delay evaluation of this since the registries are already fully built
ConfiguredSurfaceBuilder<?> surfaceBuilder = surfaceBuilders.getOrThrow(surfaceBuilderKey);
accessor.fabric_setSurfaceBuilder(() -> surfaceBuilder);
}
@Override
public boolean removeFeature(GenerationStep.Feature step, RegistryKey<ConfiguredFeature<?, ?>> configuredFeatureKey) {
ConfiguredFeature<?, ?> configuredFeature = features.getOrThrow(configuredFeatureKey);

View file

@ -29,7 +29,6 @@ import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
import net.minecraft.world.gen.chunk.StructuresConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
@ -55,12 +54,6 @@ public class BiomeSelectionContextImpl implements BiomeSelectionContext {
return biome;
}
@Override
public Optional<RegistryKey<ConfiguredSurfaceBuilder<?>>> getSurfaceBuilderKey() {
Registry<ConfiguredSurfaceBuilder<?>> registry = dynamicRegistries.get(Registry.CONFIGURED_SURFACE_BUILDER_KEY);
return registry.getKey(biome.getGenerationSettings().getSurfaceBuilder().get());
}
@Override
public Optional<RegistryKey<ConfiguredFeature<?, ?>>> getFeatureKey(ConfiguredFeature<?, ?> configuredFeature) {
Registry<ConfiguredFeature<?, ?>> registry = dynamicRegistries.get(Registry.CONFIGURED_FEATURE_KEY);

View file

@ -23,7 +23,6 @@ import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.gen.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.ConfiguredStructureFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
/**
* Utility class for getting the registry keys of built-in worldgen objects and throwing proper exceptions if they
@ -34,11 +33,6 @@ public final class BuiltInRegistryKeys {
private BuiltInRegistryKeys() {
}
public static RegistryKey<ConfiguredSurfaceBuilder<?>> get(ConfiguredSurfaceBuilder<?> configuredSurfaceBuilder) {
return BuiltinRegistries.CONFIGURED_SURFACE_BUILDER.getKey(configuredSurfaceBuilder)
.orElseThrow(() -> new IllegalArgumentException("Given surface builder is not built-in: " + configuredSurfaceBuilder));
}
public static RegistryKey<ConfiguredStructureFeature<?, ?>> get(ConfiguredStructureFeature<?, ?> configuredStructure) {
return BuiltinRegistries.CONFIGURED_STRUCTURE_FEATURE.getKey(configuredStructure)
.orElseThrow(() -> new IllegalArgumentException("Given configured structure is not built-in: " + configuredStructure));

View file

@ -28,13 +28,9 @@ import net.minecraft.world.biome.GenerationSettings;
import net.minecraft.world.gen.GenerationStep;
import net.minecraft.world.gen.carver.ConfiguredCarver;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
@Mixin(GenerationSettings.class)
public interface GenerationSettingsAccessor {
@Accessor("surfaceBuilder")
Supplier<ConfiguredSurfaceBuilder<?>> fabric_getSurfaceBuilder();
@Accessor("carvers")
Map<GenerationStep.Carver, List<Supplier<ConfiguredCarver<?>>>> fabric_getCarvers();
@ -44,10 +40,6 @@ public interface GenerationSettingsAccessor {
@Accessor("flowerFeatures")
List<ConfiguredFeature<?, ?>> fabric_getFlowerFeatures();
@Accessor("surfaceBuilder")
@Mutable
void fabric_setSurfaceBuilder(Supplier<ConfiguredSurfaceBuilder<?>> value);
@Accessor("carvers")
@Mutable
void fabric_setCarvers(Map<GenerationStep.Carver, List<Supplier<ConfiguredCarver<?>>>> value);

View file

@ -16,8 +16,7 @@
package net.fabricmc.fabric.test.biome;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.class_6727;
import net.minecraft.sound.BiomeMoodSound;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.BuiltinRegistries;
@ -36,11 +35,6 @@ import net.minecraft.world.gen.feature.ConfiguredFeatures;
import net.minecraft.world.gen.feature.DefaultBiomeFeatures;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.FeatureConfig;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.ConfiguredSurfaceBuilders;
import net.minecraft.world.gen.surfacebuilder.SurfaceBuilder;
import net.minecraft.world.gen.surfacebuilder.SurfaceConfig;
import net.minecraft.world.gen.surfacebuilder.TernarySurfaceConfig;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.biome.v1.BiomeModifications;
@ -70,17 +64,14 @@ public class FabricBiomeTest implements ModInitializer {
private static final RegistryKey<Biome> TEST_END_MIDLANDS = RegistryKey.of(Registry.BIOME_KEY, new Identifier(MOD_ID, "test_end_midlands"));
private static final RegistryKey<Biome> TEST_END_BARRRENS = RegistryKey.of(Registry.BIOME_KEY, new Identifier(MOD_ID, "test_end_barrens"));
private static BlockState STONE = Blocks.STONE.getDefaultState();
private static ConfiguredSurfaceBuilder<TernarySurfaceConfig> TEST_END_SURFACE_BUILDER = registerTestSurfaceBuilder(new Identifier(MOD_ID, "end"), SurfaceBuilder.DEFAULT.withConfig(new TernarySurfaceConfig(STONE, STONE, STONE)));
@Override
public void onInitialize() {
Registry.register(BuiltinRegistries.BIOME, TEST_CRIMSON_FOREST.getValue(), DefaultBiomeCreator.createCrimsonForest());
Registry.register(BuiltinRegistries.BIOME, TEST_CRIMSON_FOREST.getValue(), class_6727.method_39149());
NetherBiomes.addNetherBiome(BiomeKeys.THE_END, MultiNoiseUtil.createNoiseValuePoint(0.0F, 0.5F, 0.0F, 0.0F, 0.0f, 0.1F));
NetherBiomes.addNetherBiome(TEST_CRIMSON_FOREST, MultiNoiseUtil.createNoiseValuePoint(0.0F, 0.5F, 0.0F, 0.0F, 0.0f, 0.275F));
Registry.register(BuiltinRegistries.BIOME, CUSTOM_PLAINS.getValue(), DefaultBiomeCreator.createPlains(false));
Registry.register(BuiltinRegistries.BIOME, CUSTOM_PLAINS.getValue(), DefaultBiomeCreator.createPlains(false, false, false));
Registry.register(BuiltinRegistries.BIOME, TEST_END_HIGHLANDS.getValue(), createEndHighlands());
Registry.register(BuiltinRegistries.BIOME, TEST_END_MIDLANDS.getValue(), createEndMidlands());
@ -107,13 +98,6 @@ public class FabricBiomeTest implements ModInitializer {
.add(ModificationPhase.ADDITIONS,
BiomeSelectors.foundInOverworld(),
modification -> modification.getWeather().setDownfall(100))
.add(ModificationPhase.ADDITIONS,
BiomeSelectors.foundInOverworld().and(BiomeSelectors.excludeByKey(BiomeKeys.PLAINS)).and(
context -> context.hasBuiltInSurfaceBuilder(ConfiguredSurfaceBuilders.GRASS)
),
context -> {
context.getGenerationSettings().setBuiltInSurfaceBuilder(ConfiguredSurfaceBuilders.CRIMSON_FOREST);
})
.add(ModificationPhase.ADDITIONS,
BiomeSelectors.categories(Biome.Category.DESERT),
context -> {
@ -128,20 +112,19 @@ public class FabricBiomeTest implements ModInitializer {
// These are used for testing the spacing of custom end biomes.
private static Biome createEndHighlands() {
GenerationSettings.Builder builder = (new GenerationSettings.Builder()).surfaceBuilder(TEST_END_SURFACE_BUILDER)
GenerationSettings.Builder builder = (new GenerationSettings.Builder())
.feature(GenerationStep.Feature.SURFACE_STRUCTURES, ConfiguredFeatures.END_GATEWAY)
.feature(GenerationStep.Feature.VEGETAL_DECORATION, ConfiguredFeatures.CHORUS_PLANT);
return composeEndSpawnSettings(builder);
}
public static Biome createEndMidlands() {
GenerationSettings.Builder builder = (new GenerationSettings.Builder())
.surfaceBuilder(TEST_END_SURFACE_BUILDER);
GenerationSettings.Builder builder = (new GenerationSettings.Builder());
return composeEndSpawnSettings(builder);
}
public static Biome createEndBarrens() {
GenerationSettings.Builder builder = (new GenerationSettings.Builder()).surfaceBuilder(TEST_END_SURFACE_BUILDER);
GenerationSettings.Builder builder = (new GenerationSettings.Builder());
return composeEndSpawnSettings(builder);
}
@ -150,8 +133,4 @@ public class FabricBiomeTest implements ModInitializer {
DefaultBiomeFeatures.addEndMobs(builder2);
return (new Biome.Builder()).precipitation(Biome.Precipitation.NONE).category(Biome.Category.THEEND).temperature(0.5F).downfall(0.5F).effects((new BiomeEffects.Builder()).waterColor(4159204).waterFogColor(329011).fogColor(10518688).skyColor(0).moodSound(BiomeMoodSound.CAVE).build()).spawnSettings(builder2.build()).generationSettings(builder.build()).build();
}
private static <SC extends SurfaceConfig> ConfiguredSurfaceBuilder<SC> registerTestSurfaceBuilder(Identifier id, ConfiguredSurfaceBuilder<SC> configuredSurfaceBuilder) {
return BuiltinRegistries.add(BuiltinRegistries.CONFIGURED_SURFACE_BUILDER, id, configuredSurfaceBuilder);
}
}

View file

@ -1,5 +1,5 @@
archivesBaseName = "fabric-registry-sync-v0"
version = getSubprojectVersion(project, "0.7.13")
version = getSubprojectVersion(project, "0.8.0")
moduleDependencies(project, [
'fabric-api-base',

View file

@ -60,9 +60,6 @@ public class FabricRegistryInit implements ModInitializer {
// Doesnt seem to be accessed apart from registering?
RegistryAttributeHolder.get(Registry.CARVER);
// Doesnt seem to be accessed apart from registering?
RegistryAttributeHolder.get(Registry.SURFACE_BUILDER);
// Serialised by string, doesnt seem to be synced
RegistryAttributeHolder.get(Registry.FEATURE);

View file

@ -1,216 +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.impl.registry.sync;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtIo;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.util.registry.MutableRegistry;
import net.minecraft.util.registry.Registry;
/**
* This solves a bug in vanilla where datapack added biome IDs are not saved to disk. Thus adding or changing a biome
* from a datapack/mod causes the ids to shift. This remaps the IDs in the {@link DynamicRegistryManager} in a similar
* manner to the normal registry sync.
*
* <p>See: https://bugs.mojang.com/browse/MC-202036
*
* <p>This may cause issues when vanilla adds biomes in the future, this should be fixable by also remapping the static ID
* map vanilla keeps.
*/
public class PersistentDynamicRegistryHandler {
private static final Logger LOGGER = LogManager.getLogger();
public static void remapDynamicRegistries(DynamicRegistryManager.Impl dynamicRegistryManager, Path saveDir) {
LOGGER.debug("Starting registry remap");
NbtCompound registryData;
try {
registryData = remapDynamicRegistries(dynamicRegistryManager, readCompoundTag(getDataPath(saveDir)));
} catch (RemapException | IOException e) {
throw new RuntimeException("Failed to read dynamic registry data", e);
}
writeCompoundTag(registryData, getDataPath(saveDir));
}
@NotNull
private static NbtCompound remapDynamicRegistries(DynamicRegistryManager.Impl dynamicRegistryManager, @Nullable NbtCompound existingTag) throws RemapException {
NbtCompound registries = new NbtCompound();
// For now we only care about biomes, but lets keep our options open
NbtCompound biomeRegistryData = null;
if (existingTag != null) {
biomeRegistryData = existingTag.getCompound(Registry.BIOME_KEY.getValue().toString());
}
MutableRegistry<?> registry = (MutableRegistry<?>) dynamicRegistryManager.get(Registry.BIOME_KEY);
NbtCompound biomeIdMap = remapRegistry(Registry.BIOME_KEY.getValue(), registry, biomeRegistryData);
registries.put(Registry.BIOME_KEY.getValue().toString(), biomeIdMap);
return registries;
}
/**
* Remaps a registry if existing data is passed in.
* Then writes out the ids in the registry (remapped or a new world).
* Keeps hold of the orphaned registry entries as to not overwrite them.
*/
private static <T> NbtCompound remapRegistry(Identifier registryId, MutableRegistry<T> registry, @Nullable NbtCompound existingTag) throws RemapException {
if (!(registry instanceof RemappableRegistry)) {
throw new UnsupportedOperationException("Cannot remap un re-mappable registry: " + registryId.toString());
}
// This includes biomes added via datapacks via the vanilla method, along with mod provided biomes.
boolean isModified = registry.getIds().stream().anyMatch(id -> !id.getNamespace().equals("minecraft"));
// The current registry might not be modified, but we might have previous changed vanilla ids that we should try and remap
if (existingTag != null && !isModified) {
isModified = existingTag.getKeys().stream()
.map(existingTag::getString)
.map(Identifier::new)
.anyMatch(id -> !id.getNamespace().equals("minecraft"));
}
if (LOGGER.isDebugEnabled()) {
if (existingTag == null) {
LOGGER.debug("No existing data found, assuming new registry with {} entries. modded = {}", registry.getIds().size(), isModified);
} else {
LOGGER.debug("Existing registry data found. modded = {}", isModified);
for (T entry : registry) {
//noinspection unchecked
Identifier id = registry.getId(entry);
int rawId = registry.getRawId(entry);
if (id == null || rawId < 0) continue;
if (existingTag.getKeys().contains(id.toString())) {
int existingRawId = existingTag.getInt(id.toString());
if (rawId != existingRawId) {
LOGGER.debug("Remapping {} {} -> {}", id.toString(), rawId, existingRawId);
} else {
LOGGER.debug("Using existing id for {} {}", id.toString(), rawId);
}
} else {
LOGGER.debug("Found new registry entry {}", id.toString());
}
}
}
}
// If we have some existing ids and the registry contains modded/datapack entries we remap the registry with those
if (existingTag != null && isModified) {
LOGGER.debug("Remapping {} with {} entries", registryId, registry.getIds().size());
Object2IntMap<Identifier> idMap = new Object2IntOpenHashMap<>();
for (String key : existingTag.getKeys()) {
idMap.put(new Identifier(key), existingTag.getInt(key));
}
((RemappableRegistry) registry).remap(registryId.toString(), idMap, RemappableRegistry.RemapMode.AUTHORITATIVE);
} else {
LOGGER.debug("Skipping remap of {}", registryId);
}
// Now start to build up what we are going to save out
NbtCompound registryTag = new NbtCompound();
// Save all ids as they appear in the remapped, or new registry to disk even if not modded.
for (T entry : registry) {
//noinspection unchecked
Identifier id = registry.getId(entry);
if (id == null) {
continue;
}
int rawId = registry.getRawId(entry);
registryTag.putInt(id.toString(), rawId);
}
/*
* Look for existing registry key/values that are not in the current registries.
* This can happen when registry entries are removed, preventing that ID from being re-used by something else.
*/
if (existingTag != null) {
for (String key : existingTag.getKeys()) {
if (!registryTag.contains(key)) {
LOGGER.debug("Saving orphaned registry entry: " + key);
registryTag.putInt(key, existingTag.getInt(key));
}
}
}
return registryTag;
}
private static Path getDataPath(Path saveDir) {
return saveDir.resolve("data").resolve("fabricDynamicRegistry.dat");
}
@Nullable
private static NbtCompound readCompoundTag(Path path) throws IOException {
if (!Files.exists(path)) {
return null;
}
try (InputStream inputStream = Files.newInputStream(path)) {
NbtCompound compoundTag = NbtIo.readCompressed(inputStream);
if (!compoundTag.contains("version") || !compoundTag.contains("registries") || compoundTag.getInt("version") != 1) {
throw new UnsupportedOperationException("Unsupported dynamic registry data format. Try updating?");
}
return compoundTag.getCompound("registries");
}
}
private static void writeCompoundTag(NbtCompound compoundTag, Path path) {
try {
Files.createDirectories(path.getParent());
try (OutputStream outputStream = Files.newOutputStream(path, StandardOpenOption.CREATE)) {
NbtCompound outputTag = new NbtCompound();
outputTag.putInt("version", 1);
outputTag.put("registries", compoundTag);
NbtIo.writeCompressed(outputTag, outputStream);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -1,55 +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 java.io.IOException;
import java.nio.file.Path;
import com.mojang.serialization.DynamicOps;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import net.minecraft.server.Main;
import net.minecraft.util.dynamic.RegistryOps;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.world.level.storage.LevelStorage;
import net.minecraft.nbt.NbtElement;
import net.minecraft.resource.ResourceManager;
import net.fabricmc.fabric.impl.registry.sync.PersistentDynamicRegistryHandler;
@Mixin(Main.class)
public class MixinMain {
@Unique
private static Path fabric_saveDir;
@Redirect(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelStorage;createSession(Ljava/lang/String;)Lnet/minecraft/world/level/storage/LevelStorage$Session;"))
private static LevelStorage.Session levelStorageCreateSession(LevelStorage levelStorage, String levelName) throws IOException {
LevelStorage.Session session = levelStorage.createSession(levelName);
fabric_saveDir = ((AccessorLevelStorageSession) session).getDirectory();
return session;
}
@Redirect(method = "main", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/dynamic/RegistryOps;ofLoaded(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/registry/DynamicRegistryManager;)Lnet/minecraft/util/dynamic/RegistryOps;"))
private static RegistryOps<NbtElement> ofRegistryOps(DynamicOps<NbtElement> delegate, ResourceManager resourceManager, DynamicRegistryManager impl) {
RegistryOps<NbtElement> registryOps = RegistryOps.ofLoaded(delegate, resourceManager, impl);
PersistentDynamicRegistryHandler.remapDynamicRegistries((DynamicRegistryManager.Impl) impl, fabric_saveDir);
return registryOps;
}
}

View file

@ -16,8 +16,6 @@
package net.fabricmc.fabric.mixin.registry.sync.client;
import java.nio.file.Path;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
@ -25,20 +23,10 @@ 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.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import net.minecraft.resource.DataPackSettings;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.registry.DynamicRegistryManager;
import net.minecraft.world.SaveProperties;
import net.minecraft.world.gen.GeneratorOptions;
import net.minecraft.world.level.LevelInfo;
import net.minecraft.world.level.storage.LevelStorage;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import net.fabricmc.fabric.impl.registry.sync.PersistentDynamicRegistryHandler;
import net.fabricmc.fabric.mixin.registry.sync.AccessorLevelStorageSession;
import net.fabricmc.fabric.impl.registry.sync.RegistrySyncManager;
import net.fabricmc.fabric.impl.registry.sync.RemapException;
@ -56,17 +44,4 @@ public class MixinMinecraftClient {
FABRIC_LOGGER.warn("Failed to unmap Fabric registries!", e);
}
}
@Inject(method = "createSaveProperties", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/dynamic/RegistryOps;ofLoaded(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/registry/DynamicRegistryManager;)Lnet/minecraft/util/dynamic/RegistryOps;"))
private static void createSaveProperties(LevelStorage.Session session, DynamicRegistryManager.Impl impl, ResourceManager resourceManager, DataPackSettings dataPackSettings, CallbackInfoReturnable<SaveProperties> cir) {
Path saveDir = ((AccessorLevelStorageSession) session).getDirectory();
PersistentDynamicRegistryHandler.remapDynamicRegistries(impl, saveDir);
}
// synthetic in method_29607 just after RegistryOps.of
@Inject(method = "method_31125", at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/util/dynamic/RegistryOps;ofLoaded(Lcom/mojang/serialization/DynamicOps;Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/util/registry/DynamicRegistryManager;)Lnet/minecraft/util/dynamic/RegistryOps;"))
private static void method_31125(DynamicRegistryManager.Impl impl, GeneratorOptions generatorOptions, LevelInfo levelInfo, LevelStorage.Session session, DynamicRegistryManager.Impl impl2, ResourceManager resourceManager, DataPackSettings dataPackSettings, CallbackInfoReturnable<SaveProperties> cir) {
Path saveDir = ((AccessorLevelStorageSession) session).getDirectory();
PersistentDynamicRegistryHandler.remapDynamicRegistries(impl, saveDir);
}
}

View file

@ -9,7 +9,6 @@
"MixinDynamicRegistryManager",
"MixinIdList",
"MixinIdRegistry",
"MixinMain",
"MixinPlayerManager",
"MixinLevelStorageSession",
"MixinRegistry",