[Feature] Auto Detect End-Datapacks and disable custom Terrain Generation

This commit is contained in:
Frank 2022-06-20 01:06:50 +02:00
parent c93a942eee
commit def4fc3566
8 changed files with 140 additions and 42 deletions

View file

@ -24,7 +24,7 @@ import java.util.Optional;
* <p>
* This class provides the ability for mod to store persistent data inside a world. The Storage for the world is
* currently initialized as part of the {@link org.betterx.bclib.presets.worldgen.WorldBootstrap} in
* {@link org.betterx.bclib.presets.worldgen.WorldBootstrap#initializeWorldDataAPI(File, boolean)}
* org.betterx.bclib.presets.worldgen.WorldBootstrap.Helpers#initializeWorldDataAPI(File, boolean)
*/
public class WorldDataAPI {
private static final Map<String, CompoundTag> TAGS = Maps.newHashMap();

View file

@ -16,7 +16,9 @@ import org.betterx.bclib.presets.worldgen.BCLWorldPresetSettings;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BiomeTags;
@ -25,6 +27,7 @@ import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.levelgen.DensityFunction;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
@ -235,6 +238,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_VOID);
}
public static float getLegacyHeightValue(SimplexNoise simplexNoise, int i, int j) {
int k = i / 2;
int l = j / 2;
@ -298,46 +302,72 @@ public class BCLibEndBiomeSource extends BCLBiomeSource {
}
public Holder<Biome> getNoiseBiomeVanilla(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
int posX = QuartPos.toBlock(biomeX);
int posY = QuartPos.toBlock(biomeY);
int posZ = QuartPos.toBlock(biomeZ);
int sectionX = SectionPos.blockToSectionCoord(posX);
int sectionZ = SectionPos.blockToSectionCoord(posZ);
long farEndBiomes = GeneratorOptions.getFarEndBiomes();
if ((long) sectionX * (long) sectionX + (long) sectionZ * (long) sectionZ <= 4096L) {
return this.centerBiome;
} else {
int x = (SectionPos.blockToSectionCoord(posX) * 2 + 1) * 8;
int z = (SectionPos.blockToSectionCoord(posZ) * 2 + 1) * 8;
double d = sampler.erosion().compute(new DensityFunction.SinglePointContext(x, posY, z));
if (d > 0.25) {
return mapLand.getBiome(posX, biomeY << 2, posZ).biome;
} else if (d >= -0.0625) {
return mapLand.getBiome(posX, biomeY << 2, posZ).biome;
} else {
return d < -0.21875 ? mapVoid.getBiome(posX, biomeY << 2, posZ).biome : this.barrens;
}
}
}
@Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler sampler) {
if (mapLand == null || mapVoid == null)
return this.possibleBiomes().stream().findFirst().get();
long posX = biomeX << 2;
long posZ = biomeZ << 2;
long farEndBiomes = GeneratorOptions.getFarEndBiomes();
long dist = posX * posX + posZ * posZ;
if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
mapLand.clearCache();
mapVoid.clearCache();
}
return getNoiseBiomeVanilla(biomeX, biomeY, biomeZ, sampler);
if (endLandFunction == null) {
if (dist <= farEndBiomes) return centerBiome;
float height = getLegacyHeightValue(
noise,
(biomeX >> 1) + 1,
(biomeZ >> 1) + 1
) + (float) SMALL_NOISE.eval(biomeX, biomeZ) * 5;
if (height > -20F && height < -5F) {
return barrens;
}
if (height < -10F) {
return mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
} else {
return mapLand.getBiome(posX, biomeY << 2, posZ).biome;
}
} else {
pos.setLocation(biomeX, biomeZ);
if (endLandFunction.apply(pos, maxHeight)) {
return dist <= farEndBiomes ? centerBiome : mapLand.getBiome(posX, biomeY << 2, posZ).biome;
} else {
return dist <= farEndBiomes ? barrens : mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
}
}
// long posX = biomeX << 2;
// long posZ = biomeZ << 2;
// long farEndBiomes = GeneratorOptions.getFarEndBiomes();
// long dist = posX * posX + posZ * posZ;
//
// if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
// mapLand.clearCache();
// mapVoid.clearCache();
// }
//
// if (endLandFunction == null) {
// if (dist <= farEndBiomes) return centerBiome;
// float height = getLegacyHeightValue(
// noise,
// (biomeX >> 1) + 1,
// (biomeZ >> 1) + 1
// ) + (float) SMALL_NOISE.eval(biomeX, biomeZ) * 5;
//
// if (height > -20F && height < -5F) {
// return barrens;
// }
//
// if (height < -10F) {
// return mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
// } else {
// return mapLand.getBiome(posX, biomeY << 2, posZ).biome;
// }
// } else {
// pos.setLocation(biomeX, biomeZ);
// if (endLandFunction.apply(pos, maxHeight)) {
// return dist <= farEndBiomes ? centerBiome : mapLand.getBiome(posX, biomeY << 2, posZ).biome;
// } else {
// return dist <= farEndBiomes ? barrens : mapVoid.getBiome(posX, biomeY << 2, posZ).biome;
// }
// }
}
@Override

View file

@ -353,6 +353,7 @@ public class LevelGenUtil {
BCLWorldPreset.writeWorldPresetSettings(new BCLWorldPresetSettings(
biomeSourceVersion,
biomeSourceVersion,
true,
true
));
}

View file

@ -41,6 +41,7 @@ public class WorldSetupScreen extends BCLibScreen {
private GridCheckboxCell bclibNether;
GridCheckboxCell endLegacy;
GridCheckboxCell endCustomTerrain;
GridCheckboxCell generateEndVoid;
GridCheckboxCell netherLegacy;
@Override
@ -48,6 +49,7 @@ public class WorldSetupScreen extends BCLibScreen {
final int netherVersion;
final int endVersion;
final boolean customEndGen;
final boolean haveEndVoid;
if (createWorldScreen.worldGenSettingsComponent instanceof WorldGenSettingsComponentAccessor acc
&& acc.bcl_getPreset()
.isPresent() && acc.bcl_getPreset()
@ -57,6 +59,7 @@ public class WorldSetupScreen extends BCLibScreen {
netherVersion = settings.netherVersion;
endVersion = settings.endVersion;
customEndGen = settings.useEndTerrainGenerator;
haveEndVoid = settings.generateEndVoid;
} else {
throw new IllegalStateException("The WorldSetup Screen is only valid for BetterX Presets.");
}
@ -114,7 +117,18 @@ public class WorldSetupScreen extends BCLibScreen {
(state) -> {
}
);
row = colEnd.addRow();
row.addSpacer(20);
generateEndVoid = row.addCheckbox(
Component.translatable("title.screen.bclib.worldgen.end_void"),
haveEndVoid,
1.0,
GridLayout.GridValueType.PERCENTAGE,
(state) -> {
}
);
row = colEnd.addRow();
row.addSpacer(20);
endLegacy = row.addCheckbox(
@ -135,6 +149,7 @@ public class WorldSetupScreen extends BCLibScreen {
(state) -> {
endLegacy.setEnabled(state);
endCustomTerrain.setEnabled(state);
generateEndVoid.setEnabled(state);
}
);
@ -174,7 +189,8 @@ public class WorldSetupScreen extends BCLibScreen {
acc.bcl_setPreset(Optional.of(Holder.direct(worldPreset.withSettings(new BCLWorldPresetSettings(
netherVersion,
endVersion,
endCustomTerrain.isChecked()
endCustomTerrain.isChecked(),
generateEndVoid.isChecked()
)))));
}

View file

@ -43,22 +43,33 @@ public class BCLWorldPresetSettings extends WorldPresetSettings {
Codec.BOOL
.fieldOf("custom_end_terrain")
.orElse(true)
.forGetter(o -> o.useEndTerrainGenerator)
.forGetter(o -> o.useEndTerrainGenerator),
Codec.BOOL
.fieldOf("generate_end_void")
.orElse(true)
.forGetter(o -> o.generateEndVoid)
)
.apply(builderInstance, builderInstance.stable(BCLWorldPresetSettings::new));
});
public final int netherVersion;
public final int endVersion;
public final boolean useEndTerrainGenerator;
public final boolean generateEndVoid;
public BCLWorldPresetSettings(int version) {
this(version, version, true);
this(version, version, true, true);
}
public BCLWorldPresetSettings(int netherVersion, int endVersion, boolean useEndTerrainGenerator) {
public BCLWorldPresetSettings(
int netherVersion,
int endVersion,
boolean useEndTerrainGenerator,
boolean generateEndVoid
) {
this.netherVersion = netherVersion;
this.endVersion = endVersion;
this.useEndTerrainGenerator = endVersion != BCLibEndBiomeSource.BIOME_SOURCE_VERSION_VANILLA && useEndTerrainGenerator;
this.generateEndVoid = generateEndVoid;
}

View file

@ -5,6 +5,7 @@ import org.betterx.bclib.api.v2.LifeCycleAPI;
import org.betterx.bclib.api.v2.WorldDataAPI;
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
import org.betterx.bclib.api.v2.datafixer.DataFixerAPI;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.levelgen.LevelGenUtil;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import org.betterx.bclib.interfaces.WorldGenSettingsComponentAccessor;
@ -14,6 +15,8 @@ import net.minecraft.client.gui.screens.worldselection.WorldGenSettingsComponent
import net.minecraft.core.Holder;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.dimension.LevelStem;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.presets.WorldPreset;
import net.minecraft.world.level.storage.LevelResource;
@ -92,7 +95,7 @@ public class WorldBootstrap {
Helpers.initializeWorldDataAPI(levelStorageAccess.get(), true);
if (worldGenSettingsComponent instanceof WorldGenSettingsComponentAccessor acc) {
BCLWorldPreset.writeWorldPresetSettings(acc.bcl_getPreset());
BCLWorldPreset.writeWorldPresetSettings(adaptPresetForDatapacks(acc, worldGenSettingsComponent));
}
DataFixerAPI.initializePatchData();
@ -138,6 +141,41 @@ public class WorldBootstrap {
}
}
private static Optional<Holder<WorldPreset>> adaptPresetForDatapacks(
WorldGenSettingsComponentAccessor accessor,
WorldGenSettingsComponent component
) {
LevelStem endStem = component.settings().worldGenSettings().dimensions().get(LevelStem.END);
Optional<Holder<WorldPreset>> currentPreset = accessor.bcl_getPreset();
//We probably loaded a Datapack for the End
if (!(endStem.generator().getBiomeSource() instanceof BCLibEndBiomeSource)) {
BCLib.LOGGER.info("Detected Datapack for END.");
if (currentPreset.isPresent()) {
if (currentPreset.get().value() instanceof BCLWorldPreset worldPreset) {
ResourceKey key = currentPreset.get().unwrapKey().orElse(null);
//user did not configure the Preset!
if (BCLWorldPresets.BCL_WORLD.equals(key) || BCLWorldPresets.BCL_WORLD_17.equals(key)) {
if (worldPreset.settings instanceof BCLWorldPresetSettings settings) {
BCLib.LOGGER.info("Changing Default WorldPreset Settings for Datapack use.");
worldPreset = worldPreset.withSettings(new BCLWorldPresetSettings(
settings.netherVersion,
settings.endVersion,
false,
false
));
currentPreset = Optional.of(Holder.direct(worldPreset));
accessor.bcl_setPreset(currentPreset);
}
}
}
}
}
return currentPreset;
}
public static WorldGenSettings enforceInNewWorld(WorldGenSettings worldGenSettings) {
worldGenSettings = LevelGenUtil
.getWorldSettings()

View file

@ -56,5 +56,6 @@
"title.bclib.the_end": "Das Ende",
"title.screen.bclib.worldgen.custom_biome_source": "Benutzerdefinierte Biomquelle verwenden",
"title.screen.bclib.worldgen.legacy_square": "Legacy-Verteilung (1.17)",
"title.screen.bclib.worldgen.custom_end_terrain": "Angepasster End-Terrain-Generator"
"title.screen.bclib.worldgen.custom_end_terrain": "Angepasster End-Terrain-Generator",
"title.screen.bclib.worldgen.end_void": "Kleine End-Inseln erzeugen"
}

View file

@ -57,5 +57,6 @@
"title.bclib.the_end": "The End",
"title.screen.bclib.worldgen.custom_biome_source": "Use Custom Biome Source",
"title.screen.bclib.worldgen.legacy_square": "Use Legacy Map (1.17)",
"title.screen.bclib.worldgen.custom_end_terrain": "Custom End Terrain Generator"
"title.screen.bclib.worldgen.custom_end_terrain": "Custom End Terrain Generator",
"title.screen.bclib.worldgen.end_void": "Generate small Islands"
}