Better cave biome distribution

This commit is contained in:
paulevsGitch 2021-05-05 04:30:15 +03:00
parent 609381dee8
commit df0a626420
8 changed files with 91 additions and 67 deletions

View file

@ -1,14 +1,15 @@
package ru.betterend.mixin.client; package ru.betterend.mixin.client;
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 net.minecraft.client.model.ArmorStandArmorModel; import net.minecraft.client.model.ArmorStandArmorModel;
import net.minecraft.client.renderer.entity.ArmorStandRenderer; import net.minecraft.client.renderer.entity.ArmorStandRenderer;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.LivingEntityRenderer; import net.minecraft.client.renderer.entity.LivingEntityRenderer;
import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.decoration.ArmorStand;
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 ru.betterend.client.render.ArmoredElytraLayer; import ru.betterend.client.render.ArmoredElytraLayer;
@Mixin(ArmorStandRenderer.class) @Mixin(ArmorStandRenderer.class)

View file

@ -1,14 +1,15 @@
package ru.betterend.mixin.client; package ru.betterend.mixin.client;
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 net.minecraft.client.model.HumanoidModel; import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.client.renderer.entity.HumanoidMobRenderer; import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
import net.minecraft.client.renderer.entity.MobRenderer; import net.minecraft.client.renderer.entity.MobRenderer;
import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.Mob;
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 ru.betterend.client.render.ArmoredElytraLayer; import ru.betterend.client.render.ArmoredElytraLayer;
@Mixin(HumanoidMobRenderer.class) @Mixin(HumanoidMobRenderer.class)

View file

@ -27,6 +27,7 @@ import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData; import net.minecraft.world.level.storage.ServerLevelData;
import ru.betterend.BetterEnd; import ru.betterend.BetterEnd;
import ru.betterend.registry.EndBiomes;
import ru.betterend.util.DataFixerUtil; import ru.betterend.util.DataFixerUtil;
import ru.betterend.util.WorldDataUtil; import ru.betterend.util.WorldDataUtil;
import ru.betterend.world.generator.GeneratorOptions; import ru.betterend.world.generator.GeneratorOptions;
@ -46,6 +47,7 @@ public class ServerLevelMixin {
lastWorld = session.getLevelId(); lastWorld = session.getLevelId();
ServerLevel world = ServerLevel.class.cast(this); ServerLevel world = ServerLevel.class.cast(this);
EndBiomes.onWorldLoad(world.getSeed());
File dir = session.getDimensionPath(world.dimension()); File dir = session.getDimensionPath(world.dimension());
if (!new File(dir, "level.dat").exists()) { if (!new File(dir, "level.dat").exists()) {
dir = dir.getParentFile(); dir = dir.getParentFile();

View file

@ -5,7 +5,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random;
import java.util.Set; import java.util.Set;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
@ -58,8 +57,10 @@ import ru.betterend.world.biome.land.PaintedMountainsBiome;
import ru.betterend.world.biome.land.ShadowForestBiome; import ru.betterend.world.biome.land.ShadowForestBiome;
import ru.betterend.world.biome.land.SulphurSpringsBiome; import ru.betterend.world.biome.land.SulphurSpringsBiome;
import ru.betterend.world.biome.land.UmbrellaJungleBiome; import ru.betterend.world.biome.land.UmbrellaJungleBiome;
import ru.betterend.world.generator.BiomeMap;
import ru.betterend.world.generator.BiomePicker; import ru.betterend.world.generator.BiomePicker;
import ru.betterend.world.generator.BiomeType; import ru.betterend.world.generator.BiomeType;
import ru.betterend.world.generator.GeneratorOptions;
public class EndBiomes { public class EndBiomes {
private static final HashMap<ResourceLocation, EndBiome> ID_MAP = Maps.newHashMap(); private static final HashMap<ResourceLocation, EndBiome> ID_MAP = Maps.newHashMap();
@ -74,6 +75,7 @@ public class EndBiomes {
private static final JsonObject EMPTY_JSON = new JsonObject(); private static final JsonObject EMPTY_JSON = new JsonObject();
private static Registry<Biome> biomeRegistry; private static Registry<Biome> biomeRegistry;
private static BiomeMap caveBiomeMap;
// Vanilla Land // Vanilla Land
public static final EndBiome END = registerBiome(Biomes.THE_END, BiomeType.LAND, 1F); public static final EndBiome END = registerBiome(Biomes.THE_END, BiomeType.LAND, 1F);
@ -118,6 +120,12 @@ public class EndBiomes {
CAVE_BIOMES.rebuild(); CAVE_BIOMES.rebuild();
} }
public static void onWorldLoad(long seed) {
if (caveBiomeMap == null || caveBiomeMap.getSeed() != seed) {
caveBiomeMap = new BiomeMap(seed, GeneratorOptions.getBiomeSizeCaves(), CAVE_BIOMES);
}
}
public static void mutateRegistry(Registry<Biome> biomeRegistry) { public static void mutateRegistry(Registry<Biome> biomeRegistry) {
EndBiomes.biomeRegistry = biomeRegistry; EndBiomes.biomeRegistry = biomeRegistry;
@ -439,8 +447,8 @@ public class EndBiomes {
return biome; return biome;
} }
public static EndCaveBiome getCaveBiome(Random random) { public static EndCaveBiome getCaveBiome(int x, int z) {
return (EndCaveBiome) CAVE_BIOMES.getBiome(random); return (EndCaveBiome) caveBiomeMap.getBiome(x, z);
} }
public static boolean hasBiome(ResourceLocation biomeID) { public static boolean hasBiome(ResourceLocation biomeID) {

View file

@ -51,7 +51,7 @@ public abstract class EndCaveFeature extends DefaultFeature {
return false; return false;
} }
EndCaveBiome biome = EndBiomes.getCaveBiome(random); EndCaveBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ());
Set<BlockPos> caveBlocks = generate(world, center, radius, random); Set<BlockPos> caveBlocks = generate(world, center, radius, random);
if (!caveBlocks.isEmpty()) { if (!caveBlocks.isEmpty()) {
if (biome != null) { if (biome != null) {

View file

@ -1,8 +1,10 @@
package ru.betterend.world.features.terrain.caves; package ru.betterend.world.features.terrain.caves;
import java.util.Map;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
@ -21,9 +23,6 @@ import ru.betterend.util.BlocksHelper;
import ru.betterend.world.biome.cave.EndCaveBiome; import ru.betterend.world.biome.cave.EndCaveBiome;
public class TunelCaveFeature extends EndCaveFeature { public class TunelCaveFeature extends EndCaveFeature {
private static final OpenSimplexNoise BIOME_NOISE_X = new OpenSimplexNoise("biome_noise_x".hashCode());
private static final OpenSimplexNoise BIOME_NOISE_Z = new OpenSimplexNoise("biome_noise_z".hashCode());
private Set<BlockPos> generate(WorldGenLevel world, BlockPos center, Random random) { private Set<BlockPos> generate(WorldGenLevel world, BlockPos center, Random random) {
int cx = center.getX() >> 4; int cx = center.getX() >> 4;
int cz = center.getZ() >> 4; int cz = center.getZ() >> 4;
@ -79,18 +78,18 @@ public class TunelCaveFeature extends EndCaveFeature {
return false; return false;
} }
EndCaveBiome biome = EndBiomes.getCaveBiome(random); Set<BlockPos> caveBlocks = generate(world, pos, random);
Set<BlockPos> preCaveBlocks = generate(world, pos, random); if (caveBlocks.isEmpty()) {
Set<BlockPos> caveBlocks = mutateBlocks(preCaveBlocks); return false;
if (!caveBlocks.isEmpty()) { }
if (biome != null) {
setBiomes(world, biome, caveBlocks); Map<EndCaveBiome, Set<BlockPos>> floorSets = Maps.newHashMap();
Set<BlockPos> floorPositions = Sets.newHashSet(); Map<EndCaveBiome, Set<BlockPos>> ceilSets = Maps.newHashMap();
Set<BlockPos> ceilPositions = Sets.newHashSet();
MutableBlockPos mut = new MutableBlockPos(); MutableBlockPos mut = new MutableBlockPos();
Set<BlockPos> remove = Sets.newHashSet(); Set<BlockPos> remove = Sets.newHashSet();
caveBlocks.forEach((bpos) -> { caveBlocks.forEach((bpos) -> {
mut.set(bpos); mut.set(bpos);
EndCaveBiome bio = EndBiomes.getCaveBiome(bpos.getX(), bpos.getZ());
int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ()); int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ());
if (mut.getY() >= height) { if (mut.getY() >= height) {
remove.add(bpos); remove.add(bpos);
@ -98,42 +97,43 @@ public class TunelCaveFeature extends EndCaveFeature {
else if (world.getBlockState(mut).getMaterial().isReplaceable()) { else if (world.getBlockState(mut).getMaterial().isReplaceable()) {
mut.setY(bpos.getY() - 1); mut.setY(bpos.getY() - 1);
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
Set<BlockPos> floorPositions = floorSets.get(bio);
if (floorPositions == null) {
floorPositions = Sets.newHashSet();
floorSets.put(bio, floorPositions);
}
floorPositions.add(mut.immutable()); floorPositions.add(mut.immutable());
} }
mut.setY(bpos.getY() + 1); mut.setY(bpos.getY() + 1);
if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) {
Set<BlockPos> ceilPositions = ceilSets.get(bio);
if (ceilPositions == null) {
ceilPositions = Sets.newHashSet();
ceilSets.put(bio, ceilPositions);
}
ceilPositions.add(mut.immutable()); ceilPositions.add(mut.immutable());
} }
setBiome(world, bpos, bio);
} }
}); });
BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
placeFloor(world, biome, floorPositions, random, surfaceBlock);
placeCeil(world, biome, ceilPositions, random);
caveBlocks.removeAll(remove); caveBlocks.removeAll(remove);
placeWalls(world, biome, caveBlocks, random);
}
fixBlocks(world, preCaveBlocks);
}
if (caveBlocks.isEmpty()) {
return true; return true;
} }
private Set<BlockPos> mutateBlocks(Set<BlockPos> caveBlocks) { floorSets.forEach((biome, floorPositions) -> {
Set<BlockPos> result = Sets.newHashSet(); BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial();
caveBlocks.forEach(pos -> { placeFloor(world, biome, floorPositions, random, surfaceBlock);
int dx = pos.getX() + Mth.floor(BIOME_NOISE_X.eval(pos.getX() * 0.1, pos.getZ() * 0.1) * 3);
int dz = pos.getZ() + Mth.floor(BIOME_NOISE_Z.eval(pos.getX() * 0.1, pos.getZ() * 0.1) * 3);
if (dx >> 4 == pos.getX() >> 4 && dz >> 4 == pos.getZ() >> 4) {
int cx = ((pos.getX() >> 4) << 4) | 8;
int cz = ((pos.getZ() >> 4) << 4) | 8;
dx = pos.getX() - cx;
dz = pos.getZ() - cz;
if (dx * dx + dz * dz < 64) {
result.add(pos);
}
}
}); });
return result; ceilSets.forEach((biome, ceilPositions) -> {
placeCeil(world, biome, ceilPositions, random);
});
EndCaveBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ());
placeWalls(world, biome, caveBlocks, random);
fixBlocks(world, caveBlocks);
return true;
} }
@Override @Override

View file

@ -20,6 +20,7 @@ public class BiomeMap {
private final OpenSimplexNoise noiseX; private final OpenSimplexNoise noiseX;
private final OpenSimplexNoise noiseZ; private final OpenSimplexNoise noiseZ;
private final BiomePicker picker; private final BiomePicker picker;
private final long seed;
public BiomeMap(long seed, int size, BiomePicker picker) { public BiomeMap(long seed, int size, BiomePicker picker) {
maps.clear(); maps.clear();
@ -30,6 +31,11 @@ public class BiomeMap {
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2; depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
this.size = 1 << depth; this.size = 1 << depth;
this.picker = picker; this.picker = picker;
this.seed = seed;
}
public long getSeed() {
return seed;
} }
public void clearCache() { public void clearCache() {

View file

@ -7,6 +7,7 @@ import ru.betterend.config.Configs;
public class GeneratorOptions { public class GeneratorOptions {
private static int biomeSizeLand; private static int biomeSizeLand;
private static int biomeSizeVoid; private static int biomeSizeVoid;
private static int biomeSizeCaves;
private static boolean hasPortal; private static boolean hasPortal;
private static boolean hasPillars; private static boolean hasPillars;
private static boolean hasDragonFights; private static boolean hasDragonFights;
@ -33,6 +34,7 @@ public class GeneratorOptions {
public static void init() { public static void init() {
biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 256); biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 256);
biomeSizeVoid = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeVoid", 256); biomeSizeVoid = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeVoid", 256);
biomeSizeCaves = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeCaves", 32);
hasPortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "hasPortal", true); hasPortal = Configs.GENERATOR_CONFIG.getBoolean("portal", "hasPortal", true);
hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true); hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true);
hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true); hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true);
@ -68,6 +70,10 @@ public class GeneratorOptions {
return Mth.clamp(biomeSizeVoid, 1, 8192); return Mth.clamp(biomeSizeVoid, 1, 8192);
} }
public static int getBiomeSizeCaves() {
return Mth.clamp(biomeSizeCaves, 1, 8192);
}
public static boolean hasPortal() { public static boolean hasPortal() {
return hasPortal; return hasPortal;
} }