[Fix] Empty Biomes in world generation and mob spawn could crash the game (quiqueck/BCLib#105)

This commit is contained in:
Frank 2023-06-23 08:14:31 +02:00
parent 3055ab1efa
commit 54f92ff686
12 changed files with 73 additions and 43 deletions

View file

@ -1,5 +1,7 @@
package org.betterx.betterend.entity;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.betterend.registry.EndBiomes;
import org.betterx.betterend.registry.EndItems;
@ -51,7 +53,8 @@ public class CubozoaEntity extends AbstractSchoolingFish {
) {
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
if (BiomeAPI.getBiome(world.getBiome(blockPosition())).is(EndBiomes.SULPHUR_SPRINGS)) {
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(blockPosition()));
if (!BCLBiomeRegistry.isEmptyBiome(biome) && biome.is(EndBiomes.SULPHUR_SPRINGS)) {
this.entityData.set(VARIANT, (byte) 1);
}

View file

@ -1,5 +1,7 @@
package org.betterx.betterend.entity;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.betterend.registry.EndBiomes;
import org.betterx.betterend.registry.EndItems;
@ -59,7 +61,8 @@ public class EndFishEntity extends AbstractSchoolingFish {
) {
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
if (BiomeAPI.getBiome(world.getBiome(blockPosition())).equals(EndBiomes.SULPHUR_SPRINGS)) {
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(blockPosition()));
if (!BCLBiomeRegistry.isEmptyBiome(biome) && biome.equals(EndBiomes.SULPHUR_SPRINGS)) {
this.entityData.set(VARIANT, (byte) (random.nextInt(VARIANTS_SULPHUR) + VARIANTS_NORMAL));
}

View file

@ -1,6 +1,7 @@
package org.betterx.betterend.entity;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.bclib.util.MHelper;
@ -95,14 +96,16 @@ public class EndSlimeEntity extends Slime {
) {
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(blockPosition()));
if (biome.equals(EndBiomes.FOGGY_MUSHROOMLAND)) {
this.setMossy();
} else if (biome.equals(EndBiomes.MEGALAKE) || biome.equals(EndBiomes.MEGALAKE_GROVE)) {
this.setLake();
} else if (biome.equals(EndBiomes.AMBER_LAND)) {
this.setAmber();
if (!BCLBiomeRegistry.isEmptyBiome(biome)) {
if (biome.equals(EndBiomes.FOGGY_MUSHROOMLAND)) {
this.setMossy();
} else if (biome.equals(EndBiomes.MEGALAKE) || biome.equals(EndBiomes.MEGALAKE_GROVE)) {
this.setLake();
} else if (biome.equals(EndBiomes.AMBER_LAND)) {
this.setAmber();
}
this.refreshDimensions();
}
this.refreshDimensions();
return data;
}
@ -233,11 +236,13 @@ public class EndSlimeEntity extends Slime {
return false;
}
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(pos));
if (biome.equals(EndBiomes.CHORUS_FOREST) || biome.equals(EndBiomes.MEGALAKE)) {
return true;
}
if (biome.equals(EndBiomes.MEGALAKE_GROVE) && random.nextBoolean()) {
return true;
if (!BCLBiomeRegistry.isEmptyBiome(biome)) {
if (biome.equals(EndBiomes.CHORUS_FOREST) || biome.equals(EndBiomes.MEGALAKE)) {
return true;
}
if (biome.equals(EndBiomes.MEGALAKE_GROVE) && random.nextBoolean()) {
return true;
}
}
return random.nextInt(4) == 0 && isWaterNear(world, pos);
}

View file

@ -72,9 +72,9 @@ public class EndBiomes {
.map(biome -> registry.getHolderOrThrow(registry.getResourceKey(biome).get()))
.map(biome -> biome.unwrapKey().orElseThrow().location())
.filter(id -> BiomeAPI.wasRegisteredAs(id, END_CAVE))
.map(id -> BiomeAPI.getBiome(id))
.filter(bcl -> bcl != null)
.forEach(bcl -> CAVE_BIOMES.addBiome(bcl));
.map(BiomeAPI::getBiome)
.filter(bcl -> !BCLBiomeRegistry.isEmptyBiome(bcl))
.forEach(CAVE_BIOMES::addBiome);
CAVE_BIOMES.rebuild();
caveBiomeMap = null;
@ -106,7 +106,7 @@ public class EndBiomes {
public static void addSubBiomeIntegration(EndBiome biome, ResourceLocation parent) {
if (Configs.BIOME_CONFIG.getBoolean(biome.getID(), "enabled", true)) {
BCLBiome parentBiome = BiomeAPI.getBiome(parent);
if (parentBiome != null && biome.getParentBiome().getID().equals(biome.getID())) {
if (!BCLBiomeRegistry.isEmptyBiome(parentBiome) && biome.getParentBiome().getID().equals(biome.getID())) {
parentBiome.addSubBiome(biome);
}
}

View file

@ -3,6 +3,7 @@ package org.betterx.betterend.registry;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeBuilder;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v3.levelgen.features.BCLConfigureFeature;
import org.betterx.bclib.api.v3.levelgen.features.BCLFeature;
@ -1360,9 +1361,11 @@ public class EndFeatures {
BiomeAPI.addBiomeFeature(biome, CRASHED_SHIP);
BCLBiome bclbiome = BiomeAPI.getBiome(id);
BCLFeature feature = getBiomeStructures(bclbiome);
if (feature != null) {
BiomeAPI.addBiomeFeature(biome, feature);
if (!BCLBiomeRegistry.isEmptyBiome(bclbiome)) {
BCLFeature<BuildingListFeature, BuildingListFeatureConfig> feature = getBiomeStructures(bclbiome.getID());
if (feature != null) {
BiomeAPI.addBiomeFeature(biome, feature);
}
}
@ -1380,10 +1383,6 @@ public class EndFeatures {
}
}
private static BCLFeature<BuildingListFeature, BuildingListFeatureConfig> getBiomeStructures(BCLBiome biome) {
return getBiomeStructures(biome.getID());
}
private static BCLFeature<BuildingListFeature, BuildingListFeatureConfig> getBiomeStructures(ResourceLocation loc) {
String ns = loc.getNamespace();
String nm = loc.getPath();

View file

@ -114,16 +114,18 @@ public class LootTableUtil {
public static ResourceLocation getTable(Holder<Biome> biome) {
BCLBiome bclBiome = BiomeAPI.getBiome(biome.value());
if (bclBiome.equals(EndBiomes.FOGGY_MUSHROOMLAND)) {
return FOGGY_MUSHROOMLAND;
} else if (bclBiome.equals(EndBiomes.CHORUS_FOREST)) {
return CHORUS_FOREST;
} else if (bclBiome.equals(EndBiomes.SHADOW_FOREST)) {
return SHADOW_FOREST;
} else if (bclBiome.equals(EndBiomes.LANTERN_WOODS)) {
return LANTERN_WOODS;
} else if (bclBiome.equals(EndBiomes.UMBRELLA_JUNGLE)) {
return UMBRELLA_JUNGLE;
if (bclBiome != null) {
if (bclBiome.equals(EndBiomes.FOGGY_MUSHROOMLAND)) {
return FOGGY_MUSHROOMLAND;
} else if (bclBiome.equals(EndBiomes.CHORUS_FOREST)) {
return CHORUS_FOREST;
} else if (bclBiome.equals(EndBiomes.SHADOW_FOREST)) {
return SHADOW_FOREST;
} else if (bclBiome.equals(EndBiomes.LANTERN_WOODS)) {
return LANTERN_WOODS;
} else if (bclBiome.equals(EndBiomes.UMBRELLA_JUNGLE)) {
return UMBRELLA_JUNGLE;
}
}
return COMMON;
}

View file

@ -1,5 +1,7 @@
package org.betterx.betterend.world.features.terrain;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.sdf.SDF;
import org.betterx.bclib.sdf.operator.SDFDisplacement;
@ -86,7 +88,8 @@ public class FloatingSpireFeature extends SpireFeature {
sdf.fillRecursive(world, center);
support.forEach((bpos) -> {
if (BiomeAPI.getBiome(world.getBiome(bpos)).is(EndBiomes.BLOSSOMING_SPIRES)) {
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(bpos));
if (!BCLBiomeRegistry.isEmptyBiome(biome) && biome.is(EndBiomes.BLOSSOMING_SPIRES)) {
EndFeatures.TENANEA_BUSH.getFeature()
.place(new FeaturePlaceContext<NoneFeatureConfiguration>(
Optional.empty(),

View file

@ -1,5 +1,7 @@
package org.betterx.betterend.world.features.terrain;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
import org.betterx.bclib.sdf.SDF;
@ -87,7 +89,8 @@ public class SpireFeature extends DefaultFeature {
}).fillRecursive(world, center);
support.forEach((bpos) -> {
if (BiomeAPI.getBiome(world.getBiome(bpos)).equals(EndBiomes.BLOSSOMING_SPIRES)) {
BCLBiome biome = BiomeAPI.getBiome(world.getBiome(bpos));
if (!BCLBiomeRegistry.isEmptyBiome(biome) && biome.equals(EndBiomes.BLOSSOMING_SPIRES)) {
EndFeatures.TENANEA_BUSH.getFeature()
.place(new FeaturePlaceContext<NoneFeatureConfiguration>(
Optional.empty(),

View file

@ -1,5 +1,6 @@
package org.betterx.betterend.world.features.terrain.caves;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.util.BlocksHelper;
import org.betterx.betterend.util.BlockFixer;
import org.betterx.betterend.world.biome.cave.EndCaveBiome;
@ -42,6 +43,9 @@ public class CaveChunkPopulatorFeature extends Feature<CaveChunkPopulatorFeature
MutableBlockPos max = new MutableBlockPos().set(pos);
fillSets(sx, sz, world.getChunk(pos), floorPositions, ceilPositions, min, max);
EndCaveBiome biome = cfg.getCaveBiome();
if (BCLBiomeRegistry.isEmptyBiome(biome)) {
return false;
}
BlockState surfaceBlock = Blocks.END_STONE.defaultBlockState(); //biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
placeFloor(world, chunkGenerator, biome, floorPositions, random, surfaceBlock);
placeCeil(world, chunkGenerator, biome, ceilPositions, random);

View file

@ -8,12 +8,14 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.feature.configurations.FeatureConfiguration;
import org.jetbrains.annotations.Nullable;
public record CaveChunkPopulatorFeatureConfig(ResourceLocation biomeID) implements FeatureConfiguration {
public static final Codec<CaveChunkPopulatorFeatureConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(ResourceLocation.CODEC.fieldOf("biome").forGetter(o -> o.biomeID))
.apply(instance, CaveChunkPopulatorFeatureConfig::new));
public EndCaveBiome getCaveBiome() {
public @Nullable EndCaveBiome getCaveBiome() {
return (EndCaveBiome) BiomeAPI.getBiome(biomeID);
}
}

View file

@ -2,6 +2,7 @@ package org.betterx.betterend.world.features.terrain.caves;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.api.v2.levelgen.features.features.DefaultFeature;
import org.betterx.bclib.util.BlocksHelper;
@ -69,7 +70,7 @@ public abstract class EndCaveFeature extends DefaultFeature {
Set<BlockPos> floorPositions = Sets.newConcurrentHashSet();
Set<BlockPos> ceilPositions = Sets.newConcurrentHashSet();
caveBlocks.parallelStream().forEach((bpos) -> {
if (world.getBlockState(bpos).canBeReplaced()){
if (world.getBlockState(bpos).canBeReplaced()) {
BlockPos side = bpos.below();
if (world.getBlockState(side).is(CommonBlockTags.GEN_END_STONES)) {
floorPositions.add(side);
@ -258,7 +259,9 @@ public abstract class EndCaveFeature extends DefaultFeature {
if (bclBiome instanceof EndBiome endBiome)
hasCaves = endBiome.hasCaves();
if (!hasCaves && BiomeAPI.wasRegisteredAsEndLandBiome(bclBiome.getID())) {
if (!hasCaves
&& !BCLBiomeRegistry.isEmptyBiome(bclBiome)
&& BiomeAPI.wasRegisteredAsEndLandBiome(bclBiome.getID())) {
return true;
}
}

View file

@ -32,6 +32,7 @@ import java.awt.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
import org.jetbrains.annotations.Nullable;
public class TerrainGenerator {
private static final Map<Point, TerrainBoolCache> TERRAIN_BOOL_CACHE_MAP = Maps.newHashMap();
@ -114,19 +115,21 @@ public class TerrainGenerator {
if (biomeSource == null) {
return 0;
}
if (getBiome(biomeSource, x, z).settings.getTerrainHeight() < 0.1F) {
BCLBiome biome = getBiome(biomeSource, x, z);
if (biome != null && biome.settings.getTerrainHeight() < 0.1F) {
return 0F;
}
float depth = 0F;
for (int i = 0; i < OFFS.length; i++) {
int px = x + OFFS[i].x;
int pz = z + OFFS[i].y;
depth += getBiome(biomeSource, px, pz).settings.getTerrainHeight() * COEF[i];
biome = getBiome(biomeSource, px, pz);
depth += biome == null ? 0 : (biome.settings.getTerrainHeight() * COEF[i]);
}
return depth;
}
private static BCLBiome getBiome(BiomeSource biomeSource, int x, int z) {
private static @Nullable BCLBiome getBiome(BiomeSource biomeSource, int x, int z) {
return BiomeAPI.getBiome(biomeSource.getNoiseBiome(x, 0, z, sampler));
}