mirror of
https://github.com/FabricMC/fabric.git
synced 2025-04-11 22:45:38 -04:00
Move biome modification into the MinecraftServer constructor (#1966)
* Move biome modification into the MinecraftServer constructor to have access to the actual level generation settings for the level. * Move biome modification into the MinecraftServer constructor to have access to the actual level generation settings for the level. * Move biome modification into the MinecraftServer constructor to have access to the actual level generation settings for the level. * Ensure the feature ordering in BiomeSource is updated after modifying biomes. * Don't use var * Use the opportunity to check the real chunk generators for the specified structure.
This commit is contained in:
parent
e66b59e98c
commit
b02b2d58e3
11 changed files with 126 additions and 166 deletions
fabric-biome-api-v1/src/main
java/net/fabricmc/fabric
resources
|
@ -20,6 +20,7 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
import net.minecraft.world.gen.feature.PlacedFeature;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
@ -30,8 +31,6 @@ import net.fabricmc.fabric.impl.biome.modification.BuiltInRegistryKeys;
|
|||
|
||||
/**
|
||||
* Context given to a biome selector for deciding whether it applies to a biome or not.
|
||||
*
|
||||
* <p><b>Experimental feature</b>, may be removed or changed without further notice.
|
||||
*/
|
||||
public interface BiomeSelectionContext {
|
||||
RegistryKey<Biome> getBiomeKey();
|
||||
|
@ -114,7 +113,7 @@ public interface BiomeSelectionContext {
|
|||
|
||||
/**
|
||||
* Returns true if the given built-in configured structure from {@link net.minecraft.util.registry.BuiltinRegistries}
|
||||
* can start in this biome.
|
||||
* can start in this biome in any of the chunk generators used by the current world-save.
|
||||
*
|
||||
* <p>This method is intended for use with the Vanilla configured structures found in {@link net.minecraft.world.gen.feature.ConfiguredStructureFeatures}.
|
||||
*/
|
||||
|
@ -124,8 +123,8 @@ public interface BiomeSelectionContext {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns true if the configured structure with the given key can start in this biome in any configured
|
||||
* chunk generator.
|
||||
* Returns true if the configured structure with the given key can start in this biome in any chunk generator
|
||||
* used by the current world-save.
|
||||
*/
|
||||
boolean hasStructure(RegistryKey<ConfiguredStructureFeature<?, ?>> key);
|
||||
|
||||
|
@ -135,4 +134,12 @@ public interface BiomeSelectionContext {
|
|||
* from this biomes feature list.
|
||||
*/
|
||||
Optional<RegistryKey<ConfiguredStructureFeature<?, ?>>> getStructureKey(ConfiguredStructureFeature<?, ?> configuredStructure);
|
||||
|
||||
/**
|
||||
* Tries to determine whether this biome generates in a specific dimension, based on the {@link net.minecraft.world.gen.GeneratorOptions}
|
||||
* used by the current world-save.
|
||||
*
|
||||
* <p>If no dimension options exist for the given dimension key, <code>false</code> is returned.
|
||||
*/
|
||||
boolean canGenerateIn(RegistryKey<DimensionOptions> dimensionKey);
|
||||
}
|
||||
|
|
|
@ -31,8 +31,7 @@ import net.minecraft.util.registry.BuiltinRegistries;
|
|||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.SpawnSettings;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.OverworldBiomeData;
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
|
||||
/**
|
||||
* Provides several convenient biome selectors that can be used with {@link BiomeModifications}.
|
||||
|
@ -73,7 +72,7 @@ public final class BiomeSelectors {
|
|||
* assuming Vanilla's default biome source is used.
|
||||
*/
|
||||
public static Predicate<BiomeSelectionContext> foundInOverworld() {
|
||||
return context -> OverworldBiomeData.canGenerateInOverworld(context.getBiomeKey());
|
||||
return context -> context.canGenerateIn(DimensionOptions.OVERWORLD);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +82,7 @@ public final class BiomeSelectors {
|
|||
* <p>This selector will also match modded biomes that have been added to the nether using {@link NetherBiomes}.
|
||||
*/
|
||||
public static Predicate<BiomeSelectionContext> foundInTheNether() {
|
||||
return context -> NetherBiomes.canGenerateInNether(context.getBiomeKey());
|
||||
return context -> context.canGenerateIn(DimensionOptions.NETHER);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -91,7 +90,7 @@ public final class BiomeSelectors {
|
|||
* assuming Vanilla's default End biome source is used.
|
||||
*/
|
||||
public static Predicate<BiomeSelectionContext> foundInTheEnd() {
|
||||
return context -> TheEndBiomes.canGenerateInTheEnd(context.getBiomeKey());
|
||||
return context -> context.canGenerateIn(DimensionOptions.END);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,54 +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.biome;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.util.registry.BuiltinRegistries;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.source.MultiNoiseBiomeSource;
|
||||
|
||||
/**
|
||||
* Internal data for modding Vanilla's {@link MultiNoiseBiomeSource.Preset#OVERWORLD}.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public final class OverworldBiomeData {
|
||||
private static final Set<RegistryKey<Biome>> OVERWORLD_BIOMES = new HashSet<>();
|
||||
|
||||
private OverworldBiomeData() {
|
||||
}
|
||||
|
||||
public static boolean canGenerateInOverworld(RegistryKey<Biome> biome) {
|
||||
if (OVERWORLD_BIOMES.isEmpty()) {
|
||||
MultiNoiseBiomeSource source = MultiNoiseBiomeSource.Preset.OVERWORLD.getBiomeSource(BuiltinRegistries.BIOME);
|
||||
|
||||
for (Biome netherBiome : source.getBiomes()) {
|
||||
BuiltinRegistries.BIOME.getKey(netherBiome).ifPresent(OVERWORLD_BIOMES::add);
|
||||
}
|
||||
}
|
||||
|
||||
return OVERWORLD_BIOMES.contains(biome);
|
||||
}
|
||||
|
||||
public static void clearOverworldCache() {
|
||||
OVERWORLD_BIOMES.clear();
|
||||
}
|
||||
}
|
|
@ -21,11 +21,9 @@ import java.util.Comparator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.google.common.base.Stopwatch;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
@ -38,6 +36,9 @@ import net.minecraft.util.registry.DynamicRegistryManager;
|
|||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.source.BiomeSource;
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeModificationContext;
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
|
||||
|
@ -104,14 +105,14 @@ public class BiomeModificationImpl {
|
|||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void modifyBiomes(DynamicRegistryManager.Impl impl) {
|
||||
public void finalizeWorldGen(DynamicRegistryManager.Impl impl, LevelProperties levelProperties) {
|
||||
Stopwatch sw = Stopwatch.createStarted();
|
||||
|
||||
// Vanilla will sometimes call RegistryOps.of twice for the same dynamic registry manager,
|
||||
// which usually will not result in a reload of objects, since it reuses existing objects
|
||||
// from the manager when they are being referenced.
|
||||
BiomeModificationTracker modificationTracker = (BiomeModificationTracker) (Object) impl;
|
||||
Set<Biome> modifiedBiomes = modificationTracker.fabric_getModifiedBiomes();
|
||||
// Now that we apply biome modifications inside the MinecraftServer constructor, we should only ever do
|
||||
// this once for a dynamic registry manager. Marking the dynamic registry manager as modified ensures a crash
|
||||
// if the precondition is violated.
|
||||
BiomeModificationMarker modificationTracker = (BiomeModificationMarker) (Object) impl;
|
||||
modificationTracker.fabric_markModified();
|
||||
|
||||
Registry<Biome> biomes = impl.get(Registry.BIOME_KEY);
|
||||
|
||||
|
@ -120,7 +121,7 @@ public class BiomeModificationImpl {
|
|||
List<RegistryKey<Biome>> keys = biomes.getEntries().stream()
|
||||
.map(Map.Entry::getKey)
|
||||
.sorted(Comparator.comparingInt(key -> biomes.getRawId(biomes.getOrThrow(key))))
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
|
||||
List<ModifierRecord> sortedModifiers = getSortedModifiers();
|
||||
|
||||
|
@ -131,15 +132,11 @@ public class BiomeModificationImpl {
|
|||
for (RegistryKey<Biome> key : keys) {
|
||||
Biome biome = biomes.getOrThrow(key);
|
||||
|
||||
if (!modifiedBiomes.add(biome)) {
|
||||
continue; // Do not modify the same biome twice
|
||||
}
|
||||
|
||||
biomesProcessed++;
|
||||
|
||||
// Make a copy of the biome to allow selection contexts to see it unmodified,
|
||||
// But do so only once it's known anything wants to modify the biome at all
|
||||
BiomeSelectionContext context = new BiomeSelectionContextImpl(impl, key, biome);
|
||||
BiomeSelectionContext context = new BiomeSelectionContextImpl(impl, levelProperties, key, biome);
|
||||
BiomeModificationContextImpl modificationContext = null;
|
||||
|
||||
for (ModifierRecord modifier : sortedModifiers) {
|
||||
|
@ -164,6 +161,14 @@ public class BiomeModificationImpl {
|
|||
}
|
||||
|
||||
if (biomesProcessed > 0) {
|
||||
// Rebuild caches within biome sources after modifying feature lists
|
||||
for (DimensionOptions dimension : levelProperties.getGeneratorOptions().getDimensions()) {
|
||||
// The Biome source has a total ordering of feature generation that might have changed
|
||||
// by us adding or removing features from biomes.
|
||||
BiomeSource biomeSource = dimension.getChunkGenerator().getBiomeSource();
|
||||
biomeSource.field_34469 = biomeSource.method_39525(new ArrayList<>(biomeSource.getBiomes()), true);
|
||||
}
|
||||
|
||||
LOGGER.info("Applied {} biome modifications to {} of {} new biomes in {}", modifiersApplied, biomesChanged,
|
||||
biomesProcessed, sw);
|
||||
}
|
||||
|
|
|
@ -16,17 +16,13 @@
|
|||
|
||||
package net.fabricmc.fabric.impl.biome.modification;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
/**
|
||||
* Prevents double-modification of biomes in the same dynamic registry manager from occuring and fails-fast
|
||||
* Prevents double-modification of biomes in the same dynamic registry manager from occurring and fails-fast
|
||||
* if it does occur.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public interface BiomeModificationTracker {
|
||||
Set<Biome> fabric_getModifiedBiomes();
|
||||
public interface BiomeModificationMarker {
|
||||
void fabric_markModified();
|
||||
}
|
|
@ -16,33 +16,35 @@
|
|||
|
||||
package net.fabricmc.fabric.impl.biome.modification;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import net.minecraft.world.gen.feature.PlacedFeature;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryKey;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
|
||||
import net.minecraft.world.dimension.DimensionOptions;
|
||||
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.feature.PlacedFeature;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
|
||||
import net.fabricmc.fabric.api.biome.v1.BiomeSelectionContext;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class BiomeSelectionContextImpl implements BiomeSelectionContext {
|
||||
private final DynamicRegistryManager dynamicRegistries;
|
||||
private final LevelProperties levelProperties;
|
||||
private final RegistryKey<Biome> key;
|
||||
private final Biome biome;
|
||||
private final DynamicRegistryManager dynamicRegistries;
|
||||
|
||||
public BiomeSelectionContextImpl(DynamicRegistryManager dynamicRegistries, RegistryKey<Biome> key, Biome biome) {
|
||||
public BiomeSelectionContextImpl(DynamicRegistryManager dynamicRegistries, LevelProperties levelProperties, RegistryKey<Biome> key, Biome biome) {
|
||||
this.dynamicRegistries = dynamicRegistries;
|
||||
this.levelProperties = levelProperties;
|
||||
this.key = key;
|
||||
this.biome = biome;
|
||||
this.dynamicRegistries = dynamicRegistries;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -75,13 +77,10 @@ public class BiomeSelectionContextImpl implements BiomeSelectionContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Since the biome->structure mapping is now stored in the chunk generator configurations, it's no longer
|
||||
// trivial to detect if a given biome _could_ spawn a structure. To still support the API, we now do this on a
|
||||
// per-chunk-generator level.
|
||||
Registry<ChunkGeneratorSettings> chunkGeneratorSettings = dynamicRegistries.get(Registry.CHUNK_GENERATOR_SETTINGS_KEY);
|
||||
|
||||
for (Map.Entry<RegistryKey<ChunkGeneratorSettings>, ChunkGeneratorSettings> entry : chunkGeneratorSettings.getEntries()) {
|
||||
StructuresConfig structuresConfig = entry.getValue().getStructuresConfig();
|
||||
// Since the biome->structure mapping is now stored in the chunk generator configuration, we check every
|
||||
// chunk generator used by the current world-save.
|
||||
for (DimensionOptions dimension : levelProperties.getGeneratorOptions().getDimensions()) {
|
||||
StructuresConfig structuresConfig = dimension.getChunkGenerator().getStructuresConfig();
|
||||
|
||||
if (structuresConfig.getConfiguredStructureFeature(instance.feature).get(instance).contains(getBiomeKey())) {
|
||||
return true;
|
||||
|
@ -96,4 +95,15 @@ public class BiomeSelectionContextImpl implements BiomeSelectionContext {
|
|||
Registry<ConfiguredStructureFeature<?, ?>> registry = dynamicRegistries.get(Registry.CONFIGURED_STRUCTURE_FEATURE_KEY);
|
||||
return registry.getKey(configuredStructure);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canGenerateIn(RegistryKey<DimensionOptions> dimensionKey) {
|
||||
DimensionOptions dimension = levelProperties.getGeneratorOptions().getDimensions().get(dimensionKey);
|
||||
|
||||
if (dimension == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return dimension.getChunkGenerator().getBiomeSource().getBiomes().contains(biome);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,28 +16,28 @@
|
|||
|
||||
package net.fabricmc.fabric.mixin.biome.modification;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.modification.BiomeModificationTracker;
|
||||
import net.fabricmc.fabric.impl.biome.modification.BiomeModificationMarker;
|
||||
|
||||
/**
|
||||
* This Mixin allows us to track which biomes already ran through {@link net.fabricmc.fabric.impl.biome.modification.BiomeModificationImpl}
|
||||
* on a per-DynamicRegistryManager basis.
|
||||
* This Mixin allows us to keep backup copies of biomes for
|
||||
* {@link net.fabricmc.fabric.impl.biome.modification.BiomeModificationImpl} on a per-DynamicRegistryManager basis.
|
||||
*/
|
||||
@Mixin(DynamicRegistryManager.Impl.class)
|
||||
public class DynamicRegistryManagerImplMixin implements BiomeModificationTracker {
|
||||
public class DynamicRegistryManagerImplMixin implements BiomeModificationMarker {
|
||||
@Unique
|
||||
private final Set<Biome> modifiedBiomes = new HashSet<>();
|
||||
private boolean modified;
|
||||
|
||||
@Override
|
||||
public Set<Biome> fabric_getModifiedBiomes() {
|
||||
return this.modifiedBiomes;
|
||||
public void fabric_markModified() {
|
||||
if (modified) {
|
||||
throw new IllegalStateException("This dynamic registries instance has already been modified");
|
||||
}
|
||||
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.biome.modification;
|
||||
|
||||
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 net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
import net.minecraft.world.SaveProperties;
|
||||
import net.minecraft.world.level.LevelProperties;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.modification.BiomeModificationImpl;
|
||||
|
||||
@Mixin(MinecraftServer.class)
|
||||
public class MinecraftServerMixin {
|
||||
@Shadow
|
||||
private DynamicRegistryManager.Impl registryManager;
|
||||
|
||||
@Shadow
|
||||
private SaveProperties saveProperties;
|
||||
|
||||
@Inject(method = "<init>", at = @At(value = "RETURN"))
|
||||
private void finalizeWorldGen(CallbackInfo ci) {
|
||||
if (!(saveProperties instanceof LevelProperties levelProperties)) {
|
||||
throw new RuntimeException("Incompatible SaveProperties passed to MinecraftServer: " + saveProperties);
|
||||
}
|
||||
|
||||
BiomeModificationImpl.INSTANCE.finalizeWorldGen(registryManager, levelProperties);
|
||||
}
|
||||
}
|
|
@ -1,56 +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.biome.modification;
|
||||
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
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 net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.dynamic.RegistryOps;
|
||||
import net.minecraft.util.registry.DynamicRegistryManager;
|
||||
|
||||
import net.fabricmc.fabric.impl.biome.modification.BiomeModificationImpl;
|
||||
|
||||
/**
|
||||
* This Mixin hooks int the creation of RegistryOps, which will currently load data pack contents into
|
||||
* the supplied dynamic registry manager, making it the point at which we should apply biome modifications.
|
||||
*
|
||||
* <p>There is generally the following order:
|
||||
* <ol>
|
||||
* <li>{@link DynamicRegistryManager#create()} is used to create a dynamic registry manager with just
|
||||
* entries from {@link net.minecraft.util.registry.BuiltinRegistries}</li>
|
||||
* <li>Sometimes, Vanilla Minecraft will stop here, and use the {@link DynamicRegistryManager} as-is (examples: server.properties parsing, world creation screen).</li>
|
||||
* <li>{@link RegistryOps#ofLoaded(DynamicOps, ResourceManager, DynamicRegistryManager)} gets called with the manager, and a
|
||||
* resource manager that contains the loaded data packs. This will pull in all worldgen objects from datapacks into the
|
||||
* dynamic registry manager.</li>
|
||||
* <li>After the worldgen objects are pulled in from the datapacks, this mixin will call the biome modification callback.</li>
|
||||
* <li>In most cases, Vanilla will stop here and now use the dynamic registy manager to instantiate a server.</li>
|
||||
* <li>Sometimes, i.e. when using the "re-create world feature", and a datapack throws an error, Vanilla will sometimes
|
||||
* repeat the {@link RegistryOps#ofLoaded(DynamicOps, ResourceManager, DynamicRegistryManager)} call on the same
|
||||
* dynamic registry manager. We guard against this using {@link net.fabricmc.fabric.impl.biome.modification.BiomeModificationTracker}.</li>
|
||||
* </ol>
|
||||
*/
|
||||
@Mixin(RegistryOps.class)
|
||||
public class RegistryOpsMixin {
|
||||
@Inject(method = "ofLoaded", at = @At("RETURN"))
|
||||
private static <T> void afterCreation(DynamicOps<T> dynamicOps, ResourceManager resourceManager, DynamicRegistryManager impl, CallbackInfoReturnable<RegistryOps<T>> cir) {
|
||||
BiomeModificationImpl.INSTANCE.modifyBiomes((DynamicRegistryManager.Impl) impl);
|
||||
}
|
||||
}
|
|
@ -3,6 +3,11 @@ accessible class net/minecraft/world/biome/Biome$Weather
|
|||
accessible field net/minecraft/world/gen/chunk/StructuresConfig configuredStructures Lcom/google/common/collect/ImmutableMap;
|
||||
mutable field net/minecraft/world/gen/chunk/StructuresConfig configuredStructures Lcom/google/common/collect/ImmutableMap;
|
||||
|
||||
# Rebuilding biome source feature lists
|
||||
accessible method net/minecraft/world/biome/source/BiomeSource method_39525 (Ljava/util/List;Z)Ljava/util/List;
|
||||
accessible field net/minecraft/world/biome/source/BiomeSource field_34469 Ljava/util/List;
|
||||
mutable field net/minecraft/world/biome/source/BiomeSource field_34469 Ljava/util/List;
|
||||
|
||||
# Top-Level Biome Fields Access
|
||||
accessible field net/minecraft/world/biome/Biome weather Lnet/minecraft/world/biome/Biome$Weather;
|
||||
accessible field net/minecraft/world/biome/Biome generationSettings Lnet/minecraft/world/biome/GenerationSettings;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"compatibilityLevel": "JAVA_16",
|
||||
"mixins": [
|
||||
"modification.DynamicRegistryManagerImplMixin",
|
||||
"modification.RegistryOpsMixin",
|
||||
"modification.MinecraftServerMixin",
|
||||
"MixinMultiNoiseBiomeSource",
|
||||
"MixinTheEndBiomeSource"
|
||||
],
|
||||
|
|
Loading…
Add table
Reference in a new issue