From df0a626420468e332df9e058837d8ff32f106334 Mon Sep 17 00:00:00 2001 From: paulevsGitch Date: Wed, 5 May 2021 04:30:15 +0300 Subject: [PATCH] Better cave biome distribution --- .../mixin/client/ArmorStandRendererMixin.java | 9 +- .../client/HumanoidMobRendererMixin.java | 9 +- .../mixin/common/ServerLevelMixin.java | 2 + .../java/ru/betterend/registry/EndBiomes.java | 14 ++- .../terrain/caves/EndCaveFeature.java | 2 +- .../terrain/caves/TunelCaveFeature.java | 110 +++++++++--------- .../betterend/world/generator/BiomeMap.java | 6 + .../world/generator/GeneratorOptions.java | 6 + 8 files changed, 91 insertions(+), 67 deletions(-) diff --git a/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java b/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java index 7a8b9aca..d3e11b1a 100644 --- a/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java +++ b/src/main/java/ru/betterend/mixin/client/ArmorStandRendererMixin.java @@ -1,14 +1,15 @@ 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.renderer.entity.ArmorStandRenderer; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.LivingEntityRenderer; 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; @Mixin(ArmorStandRenderer.class) diff --git a/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java b/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java index eab82fea..cc034cd5 100644 --- a/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java +++ b/src/main/java/ru/betterend/mixin/client/HumanoidMobRendererMixin.java @@ -1,14 +1,15 @@ 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.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.entity.HumanoidMobRenderer; import net.minecraft.client.renderer.entity.MobRenderer; 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; @Mixin(HumanoidMobRenderer.class) diff --git a/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java b/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java index ee5c0d69..03a9f624 100644 --- a/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java +++ b/src/main/java/ru/betterend/mixin/common/ServerLevelMixin.java @@ -27,6 +27,7 @@ import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.storage.LevelStorageSource; import net.minecraft.world.level.storage.ServerLevelData; import ru.betterend.BetterEnd; +import ru.betterend.registry.EndBiomes; import ru.betterend.util.DataFixerUtil; import ru.betterend.util.WorldDataUtil; import ru.betterend.world.generator.GeneratorOptions; @@ -46,6 +47,7 @@ public class ServerLevelMixin { lastWorld = session.getLevelId(); ServerLevel world = ServerLevel.class.cast(this); + EndBiomes.onWorldLoad(world.getSeed()); File dir = session.getDimensionPath(world.dimension()); if (!new File(dir, "level.dat").exists()) { dir = dir.getParentFile(); diff --git a/src/main/java/ru/betterend/registry/EndBiomes.java b/src/main/java/ru/betterend/registry/EndBiomes.java index cf48844a..db917709 100644 --- a/src/main/java/ru/betterend/registry/EndBiomes.java +++ b/src/main/java/ru/betterend/registry/EndBiomes.java @@ -5,7 +5,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Random; import java.util.Set; 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.SulphurSpringsBiome; import ru.betterend.world.biome.land.UmbrellaJungleBiome; +import ru.betterend.world.generator.BiomeMap; import ru.betterend.world.generator.BiomePicker; import ru.betterend.world.generator.BiomeType; +import ru.betterend.world.generator.GeneratorOptions; public class EndBiomes { private static final HashMap ID_MAP = Maps.newHashMap(); @@ -74,6 +75,7 @@ public class EndBiomes { private static final JsonObject EMPTY_JSON = new JsonObject(); private static Registry biomeRegistry; + private static BiomeMap caveBiomeMap; // Vanilla Land public static final EndBiome END = registerBiome(Biomes.THE_END, BiomeType.LAND, 1F); @@ -118,6 +120,12 @@ public class EndBiomes { 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 biomeRegistry) { EndBiomes.biomeRegistry = biomeRegistry; @@ -439,8 +447,8 @@ public class EndBiomes { return biome; } - public static EndCaveBiome getCaveBiome(Random random) { - return (EndCaveBiome) CAVE_BIOMES.getBiome(random); + public static EndCaveBiome getCaveBiome(int x, int z) { + return (EndCaveBiome) caveBiomeMap.getBiome(x, z); } public static boolean hasBiome(ResourceLocation biomeID) { diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java index 9af35a84..e1155966 100644 --- a/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java +++ b/src/main/java/ru/betterend/world/features/terrain/caves/EndCaveFeature.java @@ -51,7 +51,7 @@ public abstract class EndCaveFeature extends DefaultFeature { return false; } - EndCaveBiome biome = EndBiomes.getCaveBiome(random); + EndCaveBiome biome = EndBiomes.getCaveBiome(pos.getX(), pos.getZ()); Set caveBlocks = generate(world, center, radius, random); if (!caveBlocks.isEmpty()) { if (biome != null) { diff --git a/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java b/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java index df3dfdd2..b3fb083f 100644 --- a/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java +++ b/src/main/java/ru/betterend/world/features/terrain/caves/TunelCaveFeature.java @@ -1,8 +1,10 @@ package ru.betterend.world.features.terrain.caves; +import java.util.Map; import java.util.Random; import java.util.Set; +import com.google.common.collect.Maps; import com.google.common.collect.Sets; import net.minecraft.core.BlockPos; @@ -21,9 +23,6 @@ import ru.betterend.util.BlocksHelper; import ru.betterend.world.biome.cave.EndCaveBiome; 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 generate(WorldGenLevel world, BlockPos center, Random random) { int cx = center.getX() >> 4; int cz = center.getZ() >> 4; @@ -78,62 +77,63 @@ public class TunelCaveFeature extends EndCaveFeature { if (biomeMissingCaves(world, pos)) { return false; } - - EndCaveBiome biome = EndBiomes.getCaveBiome(random); - Set preCaveBlocks = generate(world, pos, random); - Set caveBlocks = mutateBlocks(preCaveBlocks); - if (!caveBlocks.isEmpty()) { - if (biome != null) { - setBiomes(world, biome, caveBlocks); - Set floorPositions = Sets.newHashSet(); - Set ceilPositions = Sets.newHashSet(); - MutableBlockPos mut = new MutableBlockPos(); - Set remove = Sets.newHashSet(); - caveBlocks.forEach((bpos) -> { - mut.set(bpos); - int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ()); - if (mut.getY() >= height) { - remove.add(bpos); - } - else if (world.getBlockState(mut).getMaterial().isReplaceable()) { - mut.setY(bpos.getY() - 1); - if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { - floorPositions.add(mut.immutable()); - } - mut.setY(bpos.getY() + 1); - if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { - ceilPositions.add(mut.immutable()); - } - } - }); - BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); - placeFloor(world, biome, floorPositions, random, surfaceBlock); - placeCeil(world, biome, ceilPositions, random); - caveBlocks.removeAll(remove); - placeWalls(world, biome, caveBlocks, random); - } - fixBlocks(world, preCaveBlocks); + + Set caveBlocks = generate(world, pos, random); + if (caveBlocks.isEmpty()) { + return false; } - - return true; - } - - private Set mutateBlocks(Set caveBlocks) { - Set result = Sets.newHashSet(); - caveBlocks.forEach(pos -> { - 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); + + Map> floorSets = Maps.newHashMap(); + Map> ceilSets = Maps.newHashMap(); + MutableBlockPos mut = new MutableBlockPos(); + Set remove = Sets.newHashSet(); + caveBlocks.forEach((bpos) -> { + mut.set(bpos); + EndCaveBiome bio = EndBiomes.getCaveBiome(bpos.getX(), bpos.getZ()); + int height = world.getHeight(Types.WORLD_SURFACE, bpos.getX(), bpos.getZ()); + if (mut.getY() >= height) { + remove.add(bpos); + } + else if (world.getBlockState(mut).getMaterial().isReplaceable()) { + mut.setY(bpos.getY() - 1); + if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { + Set floorPositions = floorSets.get(bio); + if (floorPositions == null) { + floorPositions = Sets.newHashSet(); + floorSets.put(bio, floorPositions); + } + floorPositions.add(mut.immutable()); } + mut.setY(bpos.getY() + 1); + if (world.getBlockState(mut).is(EndTags.GEN_TERRAIN)) { + Set ceilPositions = ceilSets.get(bio); + if (ceilPositions == null) { + ceilPositions = Sets.newHashSet(); + ceilSets.put(bio, ceilPositions); + } + ceilPositions.add(mut.immutable()); + } + setBiome(world, bpos, bio); } }); - return result; + caveBlocks.removeAll(remove); + + if (caveBlocks.isEmpty()) { + return true; + } + + floorSets.forEach((biome, floorPositions) -> { + BlockState surfaceBlock = biome.getBiome().getGenerationSettings().getSurfaceBuilderConfig().getTopMaterial(); + placeFloor(world, biome, floorPositions, random, surfaceBlock); + }); + 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 diff --git a/src/main/java/ru/betterend/world/generator/BiomeMap.java b/src/main/java/ru/betterend/world/generator/BiomeMap.java index 1aa8c3c8..6ba91b73 100644 --- a/src/main/java/ru/betterend/world/generator/BiomeMap.java +++ b/src/main/java/ru/betterend/world/generator/BiomeMap.java @@ -20,6 +20,7 @@ public class BiomeMap { private final OpenSimplexNoise noiseX; private final OpenSimplexNoise noiseZ; private final BiomePicker picker; + private final long seed; public BiomeMap(long seed, int size, BiomePicker picker) { maps.clear(); @@ -30,6 +31,11 @@ public class BiomeMap { depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2; this.size = 1 << depth; this.picker = picker; + this.seed = seed; + } + + public long getSeed() { + return seed; } public void clearCache() { diff --git a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java index 3d068461..346dd2a7 100644 --- a/src/main/java/ru/betterend/world/generator/GeneratorOptions.java +++ b/src/main/java/ru/betterend/world/generator/GeneratorOptions.java @@ -7,6 +7,7 @@ import ru.betterend.config.Configs; public class GeneratorOptions { private static int biomeSizeLand; private static int biomeSizeVoid; + private static int biomeSizeCaves; private static boolean hasPortal; private static boolean hasPillars; private static boolean hasDragonFights; @@ -33,6 +34,7 @@ public class GeneratorOptions { public static void init() { biomeSizeLand = Configs.GENERATOR_CONFIG.getInt("biomeMap", "biomeSizeLand", 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); hasPillars = Configs.GENERATOR_CONFIG.getBoolean("spikes", "hasSpikes", true); hasDragonFights = Configs.GENERATOR_CONFIG.getBooleanRoot("hasDragonFights", true); @@ -67,6 +69,10 @@ public class GeneratorOptions { public static int getBiomeSizeVoid() { return Mth.clamp(biomeSizeVoid, 1, 8192); } + + public static int getBiomeSizeCaves() { + return Mth.clamp(biomeSizeCaves, 1, 8192); + } public static boolean hasPortal() { return hasPortal;