[Fix] No Features when Terrablender is present

This commit is contained in:
Frank 2022-06-10 03:22:36 +02:00
parent 31ec9c58f2
commit e49323be93
10 changed files with 134 additions and 5 deletions

View file

@ -8,7 +8,7 @@ minecraft_version=1.19
loader_version=0.14.6 loader_version=0.14.6
fabric_version=0.55.3+1.19 fabric_version=0.55.3+1.19
# Mod Properties # Mod Properties
mod_version=2.0.1 mod_version=2.0.2
maven_group=org.betterx.bclib maven_group=org.betterx.bclib
archives_base_name=bclib archives_base_name=bclib
# Dependencies # Dependencies

View file

@ -1,10 +1,13 @@
package org.betterx.bclib.api.v2.generator; package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib; import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI; import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil; import org.betterx.bclib.api.v2.levelgen.surface.SurfaceRuleUtil;
import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider; import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider;
import org.betterx.bclib.interfaces.SurfaceRuleProvider; import org.betterx.bclib.interfaces.SurfaceRuleProvider;
import org.betterx.bclib.mixin.common.ChunkGeneratorAccessor;
import org.betterx.bclib.util.ModUtil;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
@ -13,7 +16,10 @@ import net.minecraft.core.Registry;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeGenerationSettings;
import net.minecraft.world.level.biome.BiomeSource; import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FeatureSorter;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.dimension.LevelStem; import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator; import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
@ -23,8 +29,11 @@ import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import net.minecraft.world.level.levelgen.synth.NormalNoise; import net.minecraft.world.level.levelgen.synth.NormalNoise;
import com.google.common.base.Suppliers;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
import java.util.function.Predicate; import java.util.function.Predicate;
public class BCLChunkGenerator extends NoiseBasedChunkGenerator { public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
@ -51,7 +60,7 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
.and(builderInstance.group(noiseGetter, biomeSourceCodec, settingsCodec)) .and(builderInstance.group(noiseGetter, biomeSourceCodec, settingsCodec))
.apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new)); .apply(builderInstance, builderInstance.stable(BCLChunkGenerator::new));
}); });
public final BiomeSource initialBiomeSource;
public BCLChunkGenerator( public BCLChunkGenerator(
Registry<StructureSet> registry, Registry<StructureSet> registry,
@ -60,7 +69,35 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
Holder<NoiseGeneratorSettings> holder Holder<NoiseGeneratorSettings> holder
) { ) {
super(registry, registry2, biomeSource, holder); super(registry, registry2, biomeSource, holder);
System.out.println("Chunk Generator: " + this); initialBiomeSource = biomeSource;
if (!"0.0.0".equals(ModUtil.getModVersion("terrablender"))) {
BCLib.LOGGER.info("Make sure features are loaded from terrablender for " + biomeSource);
//terrablender is completley invalidating the feature imitialization
//we redo it at this point, otherwise we will get blank biomes
if (this instanceof ChunkGeneratorAccessor acc) {
Function<Holder<Biome>, BiomeGenerationSettings> function = (Holder<Biome> hh) -> hh.value()
.getGenerationSettings();
acc.bcl_setFeaturesPerStep(Suppliers.memoize(() -> FeatureSorter.buildFeaturesPerStep(
List.copyOf(biomeSource.possibleBiomes()),
(hh) -> function.apply(hh).features(),
true
)));
}
}
System.out.println("Chunk Generator: " + this + " (biomeSource: " + biomeSource + ")");
}
public void restoreInitialBiomeSource() {
if (initialBiomeSource != getBiomeSource()) {
if (this instanceof ChunkGeneratorAccessor acc) {
BiomeSource bs = LevelGenUtil.getWorldSettings()
.fixBiomeSource(initialBiomeSource, getBiomeSource().possibleBiomes());
acc.bcl_setBiomeSource(bs);
}
}
} }
public static void injectNoiseSettings(WorldGenSettings settings) { public static void injectNoiseSettings(WorldGenSettings settings) {
@ -123,6 +160,10 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
return "BCLib - Chunk Generator (" + Integer.toHexString(hashCode()) + ")"; return "BCLib - Chunk Generator (" + Integer.toHexString(hashCode()) + ")";
} }
//Make sure terrablender does not rewrite the feature-set
public void appendFeaturesPerStep() {
}
public static RandomState createRandomState(ServerLevel level, ChunkGenerator generator) { public static RandomState createRandomState(ServerLevel level, ChunkGenerator generator) {
if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) { if (generator instanceof NoiseBasedChunkGenerator noiseBasedChunkGenerator) {
return RandomState.create( return RandomState.create(
@ -134,4 +175,16 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator {
return RandomState.create(level.registryAccess(), NoiseGeneratorSettings.OVERWORLD, level.getSeed()); return RandomState.create(level.registryAccess(), NoiseGeneratorSettings.OVERWORLD, level.getSeed());
} }
} }
public static void restoreInitialBiomeSources(WorldGenSettings settings) {
restoreInitialBiomeSource(settings, LevelStem.NETHER);
restoreInitialBiomeSource(settings, LevelStem.END);
}
public static void restoreInitialBiomeSource(WorldGenSettings settings, ResourceKey<LevelStem> dimension) {
LevelStem loadedStem = settings.dimensions().getOrThrow(dimension);
if (loadedStem.generator() instanceof BCLChunkGenerator cg) {
cg.restoreInitialBiomeSource();
}
}
} }

View file

@ -608,6 +608,7 @@ public class BiomeAPI {
public static void sortBiomeFeatures(Holder<Biome> biome) { public static void sortBiomeFeatures(Holder<Biome> biome) {
sortBiomeFeatures(biome.value()); sortBiomeFeatures(biome.value());
} }
static void sortBiomeFeatures(Biome biome) { static void sortBiomeFeatures(Biome biome) {
BiomeGenerationSettings settings = biome.getGenerationSettings(); BiomeGenerationSettings settings = biome.getGenerationSettings();
BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) settings; BiomeGenerationSettingsAccessor accessor = (BiomeGenerationSettingsAccessor) settings;

View file

@ -1,6 +1,7 @@
package org.betterx.bclib.interfaces; package org.betterx.bclib.interfaces;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
public interface ChunkGeneratorAccessor { public interface ChunkGeneratorAccessor {

View file

@ -0,0 +1,23 @@
package org.betterx.bclib.mixin.common;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.FeatureSorter;
import net.minecraft.world.level.chunk.ChunkGenerator;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.List;
import java.util.function.Supplier;
@Mixin(ChunkGenerator.class)
public interface ChunkGeneratorAccessor {
@Accessor("biomeSource")
@Mutable
void bcl_setBiomeSource(BiomeSource biomeSource);
@Accessor("featuresPerStep")
@Mutable
void bcl_setFeaturesPerStep(Supplier<List<FeatureSorter.StepFeatureData>> supplier);
}

View file

@ -5,13 +5,16 @@ import org.betterx.bclib.interfaces.ChunkGeneratorAccessor;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.StructureManager; import net.minecraft.world.level.StructureManager;
import net.minecraft.world.level.WorldGenLevel; import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.levelgen.structure.StructureSet; import net.minecraft.world.level.levelgen.structure.StructureSet;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.ModifyArg;
@ -24,6 +27,7 @@ public class ChunkGeneratorMixin implements ChunkGeneratorAccessor {
protected Registry<StructureSet> structureSets; protected Registry<StructureSet> structureSets;
private int bclib_featureIteratorSeed; private int bclib_featureIteratorSeed;
@ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V")) @ModifyArg(method = "applyBiomeDecoration", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/levelgen/WorldgenRandom;setFeatureSeed(JII)V"))
private long bclib_updateFeatureSeed(long seed) { private long bclib_updateFeatureSeed(long seed) {
return Long.rotateRight(seed, bclib_featureIteratorSeed++); return Long.rotateRight(seed, bclib_featureIteratorSeed++);

View file

@ -12,6 +12,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory; import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess; import net.minecraft.world.level.storage.LevelStorageSource.LevelStorageAccess;
import net.minecraft.world.level.storage.WorldData; import net.minecraft.world.level.storage.WorldData;
@ -28,7 +29,7 @@ import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@Mixin(MinecraftServer.class) @Mixin(value=MinecraftServer.class)
public class MinecraftServerMixin { public class MinecraftServerMixin {
@Shadow @Shadow
private MinecraftServer.ReloadableResources resources; private MinecraftServer.ReloadableResources resources;
@ -41,7 +42,7 @@ public class MinecraftServerMixin {
@Shadow @Shadow
protected WorldData worldData; protected WorldData worldData;
@Inject(method = "<init>*", at = @At("TAIL")) @Inject(method = "<init>*", at = @At("TAIL"))
private void bclib_onServerInit( private void bclib_onServerInit(
Thread thread, Thread thread,
LevelStorageAccess levelStorageAccess, LevelStorageAccess levelStorageAccess,

View file

@ -0,0 +1,39 @@
package org.betterx.bclib.mixin.common;
import org.betterx.bclib.api.v2.generator.BCLChunkGenerator;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import com.mojang.datafixers.DataFixer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.Services;
import net.minecraft.server.WorldStem;
import net.minecraft.server.level.progress.ChunkProgressListenerFactory;
import net.minecraft.server.packs.repository.PackRepository;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.storage.LevelStorageSource;
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.CallbackInfo;
import java.net.Proxy;
@Mixin(value= MinecraftServer.class, priority = 2000)
public class MinecraftServerMixinLate {
@Inject(at = @At("RETURN"), method = "<init>")
private void appendGlobalFeatures(
Thread thread,
LevelStorageSource.LevelStorageAccess levelStorageAccess,
PackRepository packRepository,
WorldStem worldStem,
Proxy proxy,
DataFixer dataFixer,
Services services,
ChunkProgressListenerFactory chunkProgressListenerFactory,
CallbackInfo ci
) {
BCLChunkGenerator.restoreInitialBiomeSources(worldStem.worldData().worldGenSettings());
}
}

View file

@ -4,13 +4,17 @@ import org.betterx.bclib.BCLib;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.Lifecycle; import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder;
import net.minecraft.core.MappedRegistry; import net.minecraft.core.MappedRegistry;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess; import net.minecraft.core.RegistryAccess;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.WorldGenSettings; import net.minecraft.world.level.levelgen.WorldGenSettings;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
public abstract class WorldPresetSettings { public abstract class WorldPresetSettings {
@ -47,4 +51,5 @@ public abstract class WorldPresetSettings {
public abstract Codec<? extends WorldPresetSettings> codec(); public abstract Codec<? extends WorldPresetSettings> codec();
public abstract WorldGenSettings repairSettingsOnLoad(RegistryAccess registryAccess, WorldGenSettings settings); public abstract WorldGenSettings repairSettingsOnLoad(RegistryAccess registryAccess, WorldGenSettings settings);
public abstract BiomeSource fixBiomeSource(BiomeSource biomeSource, Set<Holder<Biome>> datapackBiomes);
} }

View file

@ -11,6 +11,7 @@
"BiomeSourceMixin", "BiomeSourceMixin",
"BlockStateBaseMixin", "BlockStateBaseMixin",
"BoneMealItemMixin", "BoneMealItemMixin",
"ChunkGeneratorAccessor",
"ChunkGeneratorMixin", "ChunkGeneratorMixin",
"ChunkGeneratorsMixin", "ChunkGeneratorsMixin",
"ComposterBlockAccessor", "ComposterBlockAccessor",
@ -24,6 +25,7 @@
"LootPoolMixin", "LootPoolMixin",
"MainMixin", "MainMixin",
"MinecraftServerMixin", "MinecraftServerMixin",
"MinecraftServerMixinLate",
"MobSpawnSettingsAccessor", "MobSpawnSettingsAccessor",
"NoiseBasedChunkGeneratorMixin", "NoiseBasedChunkGeneratorMixin",
"NoiseGeneratorSettingsMixin", "NoiseGeneratorSettingsMixin",