diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersChunkGenerator.java b/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersChunkGenerator.java index 6777f8f..f91a567 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersChunkGenerator.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersChunkGenerator.java @@ -32,10 +32,10 @@ public final class BeaconBreakersChunkGenerator extends GameChunkGenerator { private final ChunkGenerator chunkGenerator; public BeaconBreakersChunkGenerator(MinecraftServer server, BeaconBreakersMapConfig mapConfig) { - super(mapConfig.getDimensionOptions().chunkGenerator().getBiomeSource()); + super(mapConfig.getChunkGenerator().getBiomeSource()); this.mapConfig = mapConfig; - this.chunkGenerator = mapConfig.getDimensionOptions().chunkGenerator(); + this.chunkGenerator = mapConfig.getChunkGenerator(); } public ChunkGeneratorSettings getSettings() { diff --git a/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersMapConfig.java b/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersMapConfig.java index ea5b831..e0d0045 100644 --- a/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersMapConfig.java +++ b/src/main/java/io/github/haykam821/beaconbreakers/game/map/BeaconBreakersMapConfig.java @@ -1,21 +1,34 @@ package io.github.haykam821.beaconbreakers.game.map; +import java.util.List; +import java.util.Optional; + +import com.mojang.datafixers.util.Pair; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.registry.RegistryCodecs; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.registry.entry.RegistryEntryList; import net.minecraft.registry.entry.RegistryFixedCodec; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.source.MultiNoiseBiomeSource; +import net.minecraft.world.biome.source.util.MultiNoiseUtil; +import net.minecraft.world.biome.source.util.MultiNoiseUtil.NoiseHypercube; import net.minecraft.world.dimension.DimensionOptions; import net.minecraft.world.dimension.DimensionOptionsRegistryHolder; import net.minecraft.world.gen.WorldPreset; +import net.minecraft.world.gen.chunk.ChunkGenerator; +import net.minecraft.world.gen.chunk.NoiseChunkGenerator; public class BeaconBreakersMapConfig { public static final Codec CODEC = RecordCodecBuilder.create(instance -> { return instance.group( RegistryFixedCodec.of(RegistryKeys.WORLD_PRESET).fieldOf("preset").forGetter(mapConfig -> mapConfig.worldPreset), RegistryKey.createCodec(RegistryKeys.DIMENSION).optionalFieldOf("dimension_options", DimensionOptions.OVERWORLD).forGetter(mapConfig -> mapConfig.dimensionOptions), + RegistryCodecs.entryList(RegistryKeys.BIOME).optionalFieldOf("excluded_biomes").forGetter(mapConfig -> mapConfig.excludedBiomes), Codec.INT.optionalFieldOf("x", 16).forGetter(BeaconBreakersMapConfig::getX), Codec.INT.optionalFieldOf("z", 16).forGetter(BeaconBreakersMapConfig::getZ) ).apply(instance, BeaconBreakersMapConfig::new); @@ -23,12 +36,18 @@ public class BeaconBreakersMapConfig { private final RegistryEntry worldPreset; private final RegistryKey dimensionOptions; + private final Optional> excludedBiomes; + private final int x; private final int z; - public BeaconBreakersMapConfig(RegistryEntry worldPreset, RegistryKey dimensionOptions, int x, int z) { + private ChunkGenerator chunkGenerator; + + public BeaconBreakersMapConfig(RegistryEntry worldPreset, RegistryKey dimensionOptions, Optional> excludedBiomes, int x, int z) { this.worldPreset = worldPreset; this.dimensionOptions = dimensionOptions; + this.excludedBiomes = excludedBiomes; + this.x = x; this.z = z; } @@ -45,4 +64,42 @@ public int getX() { public int getZ() { return this.z; } + + public ChunkGenerator getChunkGenerator() { + if (this.chunkGenerator == null) { + this.chunkGenerator = this.createChunkGenerator(); + } + + return this.chunkGenerator; + } + + private boolean isIncludedBiome(Pair> pair) { + return this.excludedBiomes.isEmpty() || !this.excludedBiomes.get().contains(pair.getSecond()); + } + + private ChunkGenerator createChunkGenerator() { + DimensionOptions dimensionOptions = this.getDimensionOptions(); + + if (this.excludedBiomes.isPresent()) { + if (dimensionOptions.chunkGenerator() instanceof NoiseChunkGenerator noiseChunkGenerator) { + if (noiseChunkGenerator.getBiomeSource() instanceof MultiNoiseBiomeSource biomeSource) { + List>> entries = biomeSource.getBiomeEntries() + .getEntries() + .stream() + .filter(this::isIncludedBiome) + .toList(); + + MultiNoiseBiomeSource newBiomeSource = MultiNoiseBiomeSource.create(new MultiNoiseUtil.Entries<>(entries)); + + return new NoiseChunkGenerator(newBiomeSource, noiseChunkGenerator.getSettings()); + } + + throw new IllegalArgumentException("Cannot exclude biomes from unsupported biome source"); + } + + throw new IllegalArgumentException("Cannot exclude biomes from unsupported chunk generator"); + } + + return dimensionOptions.chunkGenerator(); + } } diff --git a/src/main/resources/beaconbreakers.accesswidener b/src/main/resources/beaconbreakers.accesswidener index 4e89a61..4e16fdd 100644 --- a/src/main/resources/beaconbreakers.accesswidener +++ b/src/main/resources/beaconbreakers.accesswidener @@ -2,4 +2,5 @@ accessWidener v1 named accessible method net/minecraft/entity/LivingEntity dropXp ()V accessible method net/minecraft/entity/player/PlayerEntity vanishCursedItems ()V accessible method net/minecraft/entity/player/PlayerEntity dropShoulderEntities ()V -accessible field net/minecraft/world/explosion/Explosion world Lnet/minecraft/world/World; \ No newline at end of file +accessible field net/minecraft/world/explosion/Explosion world Lnet/minecraft/world/World; +accessible method net/minecraft/world/biome/source/MultiNoiseBiomeSource getBiomeEntries ()Lnet/minecraft/world/biome/source/util/MultiNoiseUtil$Entries; \ No newline at end of file diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers.json index 00bd4cd..80554d4 100644 --- a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers.json +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers.json @@ -2,7 +2,8 @@ "type": "beaconbreakers:beacon_breakers", "map": { "dimension_options": "minecraft:overworld", - "preset": "minecraft:amplified" + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" }, "players": { "min": 1, diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory.json index 755adda..bed3101 100644 --- a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory.json +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_keep_inventory.json @@ -2,7 +2,8 @@ "type": "beaconbreakers:beacon_breakers", "map": { "dimension_options": "minecraft:overworld", - "preset": "minecraft:amplified" + "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean" }, "players": { "min": 1, diff --git a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny.json b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny.json index 817b404..2ff44ae 100644 --- a/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny.json +++ b/src/main/resources/data/beaconbreakers/games/amplified_beacon_breakers_tiny.json @@ -3,6 +3,7 @@ "map": { "dimension_options": "minecraft:overworld", "preset": "minecraft:amplified", + "excluded_biomes": "#minecraft:is_ocean", "x": 5, "z": 5 }, diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers.json index aacd77d..0b5fae9 100644 --- a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers.json +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers.json @@ -2,7 +2,8 @@ "type": "beaconbreakers:beacon_breakers", "map": { "dimension_options": "minecraft:overworld", - "preset": "minecraft:normal" + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" }, "players": { "min": 1, diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory.json index 6939fb2..42e5231 100644 --- a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory.json +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_keep_inventory.json @@ -2,7 +2,8 @@ "type": "beaconbreakers:beacon_breakers", "map": { "dimension_options": "minecraft:overworld", - "preset": "minecraft:normal" + "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean" }, "players": { "min": 1, diff --git a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny.json b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny.json index 722671c..329334c 100644 --- a/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny.json +++ b/src/main/resources/data/beaconbreakers/games/standard_beacon_breakers_tiny.json @@ -3,6 +3,7 @@ "map": { "dimension_options": "minecraft:overworld", "preset": "minecraft:normal", + "excluded_biomes": "#minecraft:is_ocean", "x": 5, "z": 5 },