From 32e7ffec693cd066fb97b0e89d9f0042f37d9ec9 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 7 Jul 2022 18:53:08 +0200 Subject: [PATCH] [Change] BCLBiome Data is managed in a Datapack-Aware registry now --- gradle.properties | 2 +- src/main/java/org/betterx/bclib/BCLib.java | 2 + .../api/v2/generator/BCLChunkGenerator.java | 3 + .../api/v2/generator/BCLibEndBiomeSource.java | 48 +-- .../v2/generator/BCLibNetherBiomeSource.java | 25 +- .../bclib/api/v2/generator/BiomePicker.java | 15 +- .../api/v2/levelgen/biomes/BCLBiome.java | 180 ++++++++++- .../v2/levelgen/biomes/BCLBiomeBuilder.java | 61 ++++ .../v2/levelgen/biomes/BCLBiomeRegistry.java | 145 +++++++++ .../v2/levelgen/biomes/BCLBiomeSettings.java | 16 + .../api/v2/levelgen/biomes/BiomeAPI.java | 280 +++++++++++++----- .../api/v2/levelgen/biomes/BiomeData.java | 15 + .../v2/levelgen/biomes/InternalBiomeAPI.java | 23 +- .../client/render/CustomFogRenderer.java | 3 +- .../betterx/bclib/commands/DumpDatapack.java | 30 +- .../mixin/common/BuiltinRegistriesMixin.java | 40 +++ .../mixin/common/RegistryAccessMixin.java | 48 +++ .../java/org/betterx/bclib/util/Pair.java | 12 + .../org/betterx/bclib/util/WeightedList.java | 54 ++++ .../biomesource/ReloadableBiomeSource.java | 5 + .../chunkgenerator/RestorableBiomeSource.java | 2 +- .../together/levelgen/WorldGenUtil.java | 9 + .../mixin/common/WorldLoaderMixin.java | 22 ++ .../surfaceRules/SurfaceRuleRegistry.java | 2 +- .../together/world/event/WorldBootstrap.java | 4 + src/main/resources/bclib.accesswidener | 4 +- src/main/resources/bclib.mixins.common.json | 2 + src/main/resources/fabric.mod.json | 2 +- .../resources/together.mixins.common.json | 1 + 29 files changed, 910 insertions(+), 145 deletions(-) create mode 100644 src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeRegistry.java create mode 100644 src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeData.java create mode 100644 src/main/java/org/betterx/bclib/mixin/common/BuiltinRegistriesMixin.java create mode 100644 src/main/java/org/betterx/bclib/mixin/common/RegistryAccessMixin.java create mode 100644 src/main/java/org/betterx/worlds/together/biomesource/ReloadableBiomeSource.java create mode 100644 src/main/java/org/betterx/worlds/together/mixin/common/WorldLoaderMixin.java diff --git a/gradle.properties b/gradle.properties index 774e809a..bb807776 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ minecraft_version=1.19 loader_version=0.14.8 fabric_version=0.57.0+1.19 # Mod Properties -mod_version=2.0.10 +mod_version=2.0.11 maven_group=org.betterx.bclib archives_base_name=bclib # Dependencies diff --git a/src/main/java/org/betterx/bclib/BCLib.java b/src/main/java/org/betterx/bclib/BCLib.java index 602da7e2..e839214c 100644 --- a/src/main/java/org/betterx/bclib/BCLib.java +++ b/src/main/java/org/betterx/bclib/BCLib.java @@ -8,6 +8,7 @@ import org.betterx.bclib.api.v2.generator.GeneratorOptions; import org.betterx.bclib.api.v2.levelgen.LevelGenEvents; 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.v2.levelgen.structures.TemplatePiece; import org.betterx.bclib.api.v2.levelgen.surface.rules.Conditions; @@ -42,6 +43,7 @@ public class BCLib implements ModInitializer { public void onInitialize() { LevelGenEvents.register(); BlockPredicates.ensureStaticInitialization(); + BCLBiomeRegistry.ensureStaticallyLoaded(); BaseRegistry.register(); GeneratorOptions.init(); BaseBlockEntities.register(); diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BCLChunkGenerator.java b/src/main/java/org/betterx/bclib/api/v2/generator/BCLChunkGenerator.java index 160614ba..cbbd853f 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BCLChunkGenerator.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BCLChunkGenerator.java @@ -6,6 +6,7 @@ import org.betterx.bclib.interfaces.NoiseGeneratorSettingsProvider; import org.betterx.bclib.mixin.common.ChunkGeneratorAccessor; import org.betterx.worlds.together.WorldsTogether; import org.betterx.worlds.together.biomesource.MergeableBiomeSource; +import org.betterx.worlds.together.biomesource.ReloadableBiomeSource; import org.betterx.worlds.together.chunkgenerator.EnforceableChunkGenerator; import org.betterx.worlds.together.chunkgenerator.InjectableSurfaceRules; import org.betterx.worlds.together.chunkgenerator.RestorableBiomeSource; @@ -110,6 +111,8 @@ public class BCLChunkGenerator extends NoiseBasedChunkGenerator implements Resto if (this instanceof ChunkGeneratorAccessor acc) { if (initialBiomeSource instanceof MergeableBiomeSource bs) { acc.bcl_setBiomeSource(bs.mergeWithBiomeSource(getBiomeSource())); + } else if (initialBiomeSource instanceof ReloadableBiomeSource bs) { + bs.reloadBiomes(); } rebuildFeaturesPerStep(getBiomeSource()); diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibEndBiomeSource.java b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibEndBiomeSource.java index ccc94786..bd4ef2e1 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibEndBiomeSource.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibEndBiomeSource.java @@ -3,10 +3,12 @@ package org.betterx.bclib.api.v2.generator; import org.betterx.bclib.BCLib; import org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig; 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.config.Configs; import org.betterx.bclib.interfaces.BiomeMap; import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig; +import org.betterx.worlds.together.biomesource.ReloadableBiomeSource; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -32,7 +34,7 @@ import java.util.Set; import java.util.function.BiFunction; import org.jetbrains.annotations.NotNull; -public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig { +public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig, ReloadableBiomeSource { public static Codec CODEC = RecordCodecBuilder.create((instance) -> instance.group( RegistryOps @@ -61,7 +63,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi private BiomeMap mapCenter; private BiomeMap mapBarrens; - private final BiomePicker endLandBiomePicker; + private BiomePicker endLandBiomePicker; private BiomePicker endVoidBiomePicker; private BiomePicker endCenterBiomePicker; private BiomePicker endBarrensBiomePicker; @@ -94,13 +96,25 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi ) { super(biomeRegistry, list, seed); this.config = config; + rebuildBiomePickers(); + + this.endLandFunction = GeneratorOptions.getEndLandFunction(); + this.pos = new Point(); + + if (initMaps) { + initMap(seed); + } + } + + @NotNull + private void rebuildBiomePickers() { var includeMap = Configs.BIOMES_CONFIG.getBiomeIncludeMap(); var excludeList = Configs.BIOMES_CONFIG.getExcludeMatching(BiomeAPI.BiomeType.END); - endLandBiomePicker = new BiomePicker(biomeRegistry); - endVoidBiomePicker = new BiomePicker(biomeRegistry); - endCenterBiomePicker = new BiomePicker(biomeRegistry); - endBarrensBiomePicker = new BiomePicker(biomeRegistry); + this.endLandBiomePicker = new BiomePicker(biomeRegistry); + this.endVoidBiomePicker = new BiomePicker(biomeRegistry); + this.endCenterBiomePicker = new BiomePicker(biomeRegistry); + this.endBarrensBiomePicker = new BiomePicker(biomeRegistry); Map pickerMap = new HashMap<>(); pickerMap.put(BiomeAPI.BiomeType.END_LAND, endLandBiomePicker); pickerMap.put(BiomeAPI.BiomeType.END_VOID, endVoidBiomePicker); @@ -126,7 +140,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi } - if (bclBiome != null || bclBiome != BiomeAPI.EMPTY_BIOME) { + if (bclBiome != null || bclBiome != BCLBiomeRegistry.EMPTY_BIOME) { if (bclBiome.getParentBiome() == null) { //ignore small islands when void biomes are disabled if (!config.withVoidBiomes) { @@ -168,7 +182,6 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi } } } - }); endLandBiomePicker.rebuild(); @@ -194,20 +207,15 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi endCenterBiomePicker = endLandBiomePicker; } } - - this.endLandFunction = GeneratorOptions.getEndLandFunction(); - this.pos = new Point(); - - if (initMaps) { - initMap(seed); - } } protected BCLBiomeSource cloneForDatapack(Set> datapackBiomes) { datapackBiomes.addAll(getBclBiomes(this.biomeRegistry)); return new BCLibEndBiomeSource( this.biomeRegistry, - datapackBiomes.stream().toList(), + datapackBiomes.stream() + .filter(b -> b.unwrapKey().orElse(null) != BCLBiomeRegistry.EMPTY_BIOME.getBiomeKey()) + .toList(), this.currentSeed, this.config, true @@ -235,7 +243,7 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi private static boolean isValidEndBiome(Holder biome, ResourceLocation location) { if (BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.END_IGNORE)) return false; - + return biome.is(BiomeTags.IS_END) || BiomeAPI.wasRegisteredAsEndBiome(location) || TheEndBiomesHelper.canGenerateInEnd(biome.unwrapKey().orElse(null)); @@ -363,4 +371,10 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi this.config = newConfig; this.initMap(currentSeed); } + + @Override + public void reloadBiomes() { + rebuildBiomePickers(); + this.initMap(currentSeed); + } } diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java index bdf504b4..dc614b86 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BCLibNetherBiomeSource.java @@ -4,11 +4,13 @@ import org.betterx.bclib.BCLib; import org.betterx.bclib.api.v2.generator.config.BCLNetherBiomeSourceConfig; import org.betterx.bclib.api.v2.generator.map.MapStack; 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.config.Configs; import org.betterx.bclib.interfaces.BiomeMap; import org.betterx.bclib.util.TriFunction; import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig; +import org.betterx.worlds.together.biomesource.ReloadableBiomeSource; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; @@ -26,7 +28,7 @@ import net.fabricmc.fabric.api.biome.v1.NetherBiomes; import java.util.List; import java.util.Set; -public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig { +public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig, ReloadableBiomeSource { public static final Codec CODEC = RecordCodecBuilder .create(instance -> instance .group( @@ -49,7 +51,7 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc .apply(instance, instance.stable(BCLibNetherBiomeSource::new)) ); private BiomeMap biomeMap; - private final BiomePicker biomePicker; + private BiomePicker biomePicker; private BCLNetherBiomeSourceConfig config; public BCLibNetherBiomeSource(Registry biomeRegistry, BCLNetherBiomeSourceConfig config) { @@ -78,6 +80,13 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc ) { super(biomeRegistry, list, seed); this.config = config; + rebuildBiomePicker(); + if (initMaps) { + initMap(seed); + } + } + + private void rebuildBiomePicker() { biomePicker = new BiomePicker(biomeRegistry); this.possibleBiomes().forEach(biome -> { @@ -87,12 +96,13 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc return; } if (!BiomeAPI.hasBiome(biomeID)) { + BCLBiome bclBiome = new BCLBiome(biomeID, biome.value()); biomePicker.addBiome(bclBiome); } else { BCLBiome bclBiome = BiomeAPI.getBiome(biomeID); - if (bclBiome != BiomeAPI.EMPTY_BIOME) { + if (bclBiome != BCLBiomeRegistry.EMPTY_BIOME) { if (bclBiome.getParentBiome() == null) { biomePicker.addBiome(bclBiome); } @@ -101,9 +111,6 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc }); biomePicker.rebuild(); - if (initMaps) { - initMap(seed); - } } protected BCLBiomeSource cloneForDatapack(Set> datapackBiomes) { @@ -213,4 +220,10 @@ public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourc this.config = newConfig; initMap(currentSeed); } + + @Override + public void reloadBiomes() { + rebuildBiomePicker(); + initMap(currentSeed); + } } diff --git a/src/main/java/org/betterx/bclib/api/v2/generator/BiomePicker.java b/src/main/java/org/betterx/bclib/api/v2/generator/BiomePicker.java index 6763ce9d..550d467e 100644 --- a/src/main/java/org/betterx/bclib/api/v2/generator/BiomePicker.java +++ b/src/main/java/org/betterx/bclib/api/v2/generator/BiomePicker.java @@ -1,7 +1,7 @@ package org.betterx.bclib.api.v2.generator; import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome; -import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI; +import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry; import org.betterx.bclib.util.WeighTree; import org.betterx.bclib.util.WeightedList; @@ -37,7 +37,7 @@ public class BiomePicker { .map(h -> h.unwrapKey()) .filter(o -> o.isPresent()) .map(o -> o.get().location().toString()).toList() : null; - this.fallbackBiome = create(BiomeAPI.EMPTY_BIOME); + this.fallbackBiome = create(BCLBiomeRegistry.EMPTY_BIOME); } private boolean isAllowed(BCLBiome b) { @@ -83,7 +83,7 @@ public class BiomePicker { //no Biome, make sure we add at least one, otherwise bad things will happen if (list.isEmpty()) { - list.add(create(BiomeAPI.EMPTY_BIOME), 1); + list.add(create(BCLBiomeRegistry.EMPTY_BIOME), 1); } @@ -161,4 +161,13 @@ public class BiomePicker { '}'; } } + + @Override + public String toString() { + return "BiomePicker{" + + "biomes=" + biomes.size() + " (" + all.size() + ")" + + ", biomeRegistry=" + biomeRegistry + + ", type=" + super.toString() + + '}'; + } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiome.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiome.java index 1275e5db..70bdd5f9 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiome.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiome.java @@ -2,39 +2,179 @@ package org.betterx.bclib.api.v2.levelgen.biomes; import org.betterx.bclib.util.WeightedList; +import com.mojang.datafixers.Products; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.Registry; import net.minecraft.data.BuiltinRegistries; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.TagKey; +import net.minecraft.util.KeyDispatchDataCodec; import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.levelgen.WorldgenRandom; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.collect.Sets; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Random; -import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; import org.jetbrains.annotations.Nullable; -public class BCLBiome extends BCLBiomeSettings { - private final Set> biomeTags = Sets.newHashSet(); - private final WeightedList subbiomes = new WeightedList<>(); + +public class BCLBiome extends BCLBiomeSettings implements BiomeData { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> codecWithSettings(instance).apply( + instance, + BCLBiome::new + )); + public static final KeyDispatchDataCodec KEY_CODEC = KeyDispatchDataCodec.of(CODEC); + + public KeyDispatchDataCodec codec() { + return KEY_CODEC; + } + + private static class CodecAttributes { + public RecordCodecBuilder t0 = Codec.FLOAT.fieldOf("terrainHeight") + .orElse(0.1f) + .forGetter((T o1) -> o1.terrainHeight); + + public RecordCodecBuilder t1 = Codec.FLOAT.fieldOf("fogDensity") + .orElse(1.0f) + .forGetter((T o1) -> o1.fogDensity); + public RecordCodecBuilder t2 = Codec.FLOAT.fieldOf("genChance") + .orElse(1.0f) + .forGetter((T o1) -> o1.genChance); + public RecordCodecBuilder t3 = Codec.INT.fieldOf("edgeSize") + .orElse(0) + .forGetter((T o1) -> o1.edgeSize); + public RecordCodecBuilder t4 = Codec.BOOL.fieldOf("vertical") + .orElse(false) + .forGetter((T o1) -> o1.vertical); + public RecordCodecBuilder> t5 = + ResourceLocation.CODEC + .optionalFieldOf("edge") + .orElse(Optional.empty()) + .forGetter((T o1) -> o1.edge == null + ? Optional.empty() + : Optional.of(o1.edge.biomeID)); + public RecordCodecBuilder t6 = + ResourceLocation.CODEC.fieldOf("biome") + .forGetter((T o) -> ((BCLBiome) o).biomeID); + public RecordCodecBuilder>> t7 = + Climate.ParameterPoint.CODEC.listOf() + .optionalFieldOf("parameter_points") + .orElse(Optional.of(List.of())) + .forGetter((T o) -> + o.parameterPoints == null || o.parameterPoints.isEmpty() + ? Optional.empty() + : Optional.of(o.parameterPoints)); + + public RecordCodecBuilder> t8 = + ResourceLocation.CODEC.optionalFieldOf("parent") + .orElse(Optional.empty()) + .forGetter( + (T o1) -> + ((BCLBiome) o1).biomeParent == null + ? Optional.empty() + : Optional.of( + ((BCLBiome) o1).biomeParent.biomeID)); + public RecordCodecBuilder>> t9 = + WeightedList.listCodec( + ResourceLocation.CODEC, + "biomes", + "biome" + ) + .optionalFieldOf("sub_biomes") + .forGetter( + (T o) -> { + if (o.subbiomes == null + || o.subbiomes.isEmpty() + || (o.subbiomes.size() == 1 && o.subbiomes.contains( + o))) { + return Optional.empty(); + } + return Optional.of( + o.subbiomes.map( + b -> b.biomeID)); + }); + public RecordCodecBuilder> t10 = + Codec.STRING.optionalFieldOf("intended_for") + .orElse(Optional.of(BiomeAPI.BiomeType.NONE.getName())) + .forGetter((T o) -> + ((BCLBiome) o).intendedType == null + ? Optional.empty() + : Optional.of(((BCLBiome) o).intendedType.getName())); + } + + public static Products.P12, Float, Float, Float, Integer, Boolean, Optional, ResourceLocation, Optional>, Optional, Optional>, Optional, P12> codecWithSettings( + RecordCodecBuilder.Instance instance, + final RecordCodecBuilder p12 + ) { + CodecAttributes a = new CodecAttributes<>(); + return instance.group(a.t0, a.t1, a.t2, a.t3, a.t4, a.t5, a.t6, a.t7, a.t8, a.t9, a.t10, p12); + } + + public static Products.P13, Float, Float, Float, Integer, Boolean, Optional, ResourceLocation, Optional>, Optional, Optional>, Optional, P12, P13> codecWithSettings( + RecordCodecBuilder.Instance instance, + final RecordCodecBuilder p12, + final RecordCodecBuilder p13 + ) { + CodecAttributes a = new CodecAttributes<>(); + return instance.group(a.t0, a.t1, a.t2, a.t3, a.t4, a.t5, a.t6, a.t7, a.t8, a.t9, a.t10, p12, p13); + } + + public static Products.P11, Float, Float, Float, Integer, Boolean, Optional, ResourceLocation, Optional>, Optional, Optional>, Optional> codecWithSettings( + RecordCodecBuilder.Instance instance + ) { + CodecAttributes a = new CodecAttributes<>(); + return instance.group(a.t0, a.t1, a.t2, a.t3, a.t4, a.t5, a.t6, a.t7, a.t8, a.t9, a.t10); + } + + protected final WeightedList subbiomes = new WeightedList<>(); private final Map customData = Maps.newHashMap(); private final ResourceLocation biomeID; private final ResourceKey biomeKey; final Biome biomeToRegister; - private final List parameterPoints = Lists.newArrayList(); + protected final List parameterPoints = Lists.newArrayList(); private BCLBiome biomeParent; + private BiomeAPI.BiomeType intendedType = BiomeAPI.BiomeType.NONE; + + protected BCLBiome( + float terrainHeight, + float fogDensity, + float genChance, + int edgeSize, + boolean vertical, + Optional edge, + ResourceLocation biomeID, + Optional> parameterPoints, + Optional biomeParent, + Optional> subbiomes, + Optional intendedType + ) { + super(terrainHeight, fogDensity, genChance, edgeSize, vertical, edge.map(BiomeAPI::getBiome).orElse(null)); + biomeToRegister = null; + this.biomeID = biomeID; + this.biomeKey = ResourceKey.create(Registry.BIOME_REGISTRY, biomeID); + if (subbiomes.isEmpty() || subbiomes.get().size() == 0) { + this.subbiomes.add(this, 1); + } else { + this.subbiomes.addAll(subbiomes.get().map(BiomeAPI::getBiome)); + } + this.biomeParent = biomeParent.map(BiomeAPI::getBiome).orElse(null); + if (parameterPoints.isPresent()) this.parameterPoints.addAll(parameterPoints.get()); + this.setIntendedType(intendedType.map(t -> BiomeAPI.BiomeType.create(t)).orElse(BiomeAPI.BiomeType.NONE)); + + + } + /** * Create wrapper for existing biome using its {@link ResourceLocation} identifier. * @@ -81,6 +221,7 @@ public class BCLBiome extends BCLBiomeSettings { * @param biomeID Teh ResoureLocation for this Biome */ @Deprecated(forRemoval = true) + //this constructor should become package private and not get removed public BCLBiome(ResourceLocation biomeID, Biome biomeToRegister) { this(biomeID, biomeToRegister, null); } @@ -124,6 +265,25 @@ public class BCLBiome extends BCLBiomeSettings { } } + /** + * Changes the intended Type for this Biome + * + * @param type the new type + * @return the same instance + */ + protected BCLBiome setIntendedType(BiomeAPI.BiomeType type) { + return _setIntendedType(type); + } + + BCLBiome _setIntendedType(BiomeAPI.BiomeType type) { + this.intendedType = type; + return this; + } + + BiomeAPI.BiomeType getIntendedType() { + return this.intendedType; + } + /** * Get current biome edge. * @@ -250,6 +410,10 @@ public class BCLBiome extends BCLBiomeSettings { return biomeKey; } + public ResourceKey getBCLBiomeKey() { + return ResourceKey.create(BCLBiomeRegistry.BCL_BIOMES_REGISTRY, biomeID); + } + /** * For internal use from BiomeAPI only */ @@ -291,6 +455,7 @@ public class BCLBiome extends BCLBiomeSettings { * @param obj any data to add. * @return same {@link BCLBiome}. */ + @Deprecated(forRemoval = true) public BCLBiome addCustomData(String name, Object obj) { customData.put(name, obj); return this; @@ -302,6 +467,7 @@ public class BCLBiome extends BCLBiomeSettings { * @param data a {@link Map} with custom data. * @return same {@link BCLBiome}. */ + @Deprecated(forRemoval = true) public BCLBiome addCustomData(Map data) { customData.putAll(data); return this; diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeBuilder.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeBuilder.java index bd11dab7..a8bd1faf 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeBuilder.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeBuilder.java @@ -54,6 +54,7 @@ public class BCLBiomeBuilder { public interface BiomeSupplier extends TriFunction { } + private static final BCLBiomeBuilder INSTANCE = new BCLBiomeBuilder(); private static final SurfaceRules.ConditionSource SURFACE_NOISE = SurfaceRules.noiseCondition( Noises.SOUL_SAND_LAYER, @@ -709,6 +710,64 @@ public class BCLBiomeBuilder { return this; } + /** + * Changes the type for the Biome. The intended Type defines in which Dimension a + * Biome is allowed to spawn. Currently each Biome can only spawn in one dimension + * + * @param type The intended type + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder intendedType(BiomeAPI.BiomeType type) { + this.biomeType = type; + return this; + } + + + /** + * Changes the intended type for the Biome to an EndLand Biome + * + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder endLandBiome() { + return intendedType(BiomeAPI.BiomeType.BCL_END_LAND); + } + + /** + * Changes the intended type for the Biome to an EndVoid (aka small islands) Biome + * + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder endVoidBiome() { + return intendedType(BiomeAPI.BiomeType.BCL_END_VOID); + } + + /** + * Changes the intended type for the Biome to an Endbarrens Biome + * + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder endBarrensBiome() { + return intendedType(BiomeAPI.BiomeType.BCL_END_BARRENS); + } + + /** + * Changes the intended type for the Biome to an End Center Island Biome + * + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder endCenterBiome() { + return intendedType(BiomeAPI.BiomeType.BCL_END_CENTER); + } + + /** + * Changes the intended type for the Biome to a Nether Biome + * + * @return same {@link BCLBiomeBuilder} instance. + */ + public BCLBiomeBuilder netherBiome() { + return intendedType(BiomeAPI.BiomeType.BCL_NETHER); + } + public BCLBiomeBuilder tag(TagKey... tag) { for (TagKey t : tag) { tags.add(t); @@ -850,6 +909,8 @@ public class BCLBiomeBuilder { //res.setSurface(surfaceRule); SurfaceRuleRegistry.registerRule(biomeID, surfaceRule, biomeID); res.addClimateParameters(parameters); + if (biomeType != null) + res._setIntendedType(biomeType); //carvers.forEach(cfg -> BiomeAPI.addBiomeCarver(biome, cfg.second, cfg.first)); diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeRegistry.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeRegistry.java new file mode 100644 index 00000000..bf7e9c72 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeRegistry.java @@ -0,0 +1,145 @@ +package org.betterx.bclib.api.v2.levelgen.biomes; + +import org.betterx.bclib.BCLib; +import org.betterx.worlds.together.WorldsTogether; +import org.betterx.worlds.together.world.event.WorldBootstrap; + +import com.mojang.serialization.Codec; +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.Holder; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.KeyDispatchDataCodec; +import net.minecraft.world.level.biome.Biomes; + +import java.util.Optional; +import java.util.stream.Stream; +import org.jetbrains.annotations.ApiStatus; + +public class BCLBiomeRegistry { + public static final ResourceKey> BCL_BIOMES_REGISTRY = + createRegistryKey(WorldsTogether.makeID("worldgen/betterx/biome")); + + public static final ResourceKey>> BCL_BIOME_CODEC_REGISTRY = + createRegistryKey(WorldsTogether.makeID("worldgen/betterx/biome_codec")); + + public static Registry> BIOME_CODECS = Registry.registerSimple( + BCL_BIOME_CODEC_REGISTRY, + BCLBiomeRegistry::bootstrapCodecs + ); + public static Registry BUILTIN_BCL_BIOMES = new MappedRegistry<>( + BCL_BIOMES_REGISTRY, + Lifecycle.stable(), null + ); + + /** + * Empty biome used as default value if requested biome doesn't exist or linked. Shouldn't be registered anywhere to prevent bugs. + * Have {@code Biomes.THE_VOID} as the reference biome. + **/ + public static final BCLBiome EMPTY_BIOME = new BCLBiome(Biomes.THE_VOID.location()); + + public static Codec registerBiomeCodec( + ResourceLocation location, + KeyDispatchDataCodec codec + ) { + Registry.register(BIOME_CODECS, location, codec.codec()); + return codec.codec(); + } + + public static ResourceKey register(BCLBiome biome) { + Registry.register(BUILTIN_BCL_BIOMES, biome.getBCLBiomeKey(), biome); + return biome.getBCLBiomeKey(); + } + + private static ResourceKey> createRegistryKey(ResourceLocation location) { + return ResourceKey.createRegistryKey(location); + } + + private static Codec bootstrapCodecs(Registry> registry) { + return Registry.register(registry, BCLib.makeID("biome"), BCLBiome.KEY_CODEC.codec()); + } + + + @ApiStatus.Internal + public static Holder bootstrap(Registry registry) { + BuiltinRegistries.register(registry, BiomeAPI.SMALL_END_ISLANDS.getBCLBiomeKey(), BiomeAPI.SMALL_END_ISLANDS); + BuiltinRegistries.register(registry, BiomeAPI.END_BARRENS.getBCLBiomeKey(), BiomeAPI.END_BARRENS); + BuiltinRegistries.register(registry, BiomeAPI.END_HIGHLANDS.getBCLBiomeKey(), BiomeAPI.END_HIGHLANDS); + BuiltinRegistries.register(registry, BiomeAPI.END_MIDLANDS.getBCLBiomeKey(), BiomeAPI.END_MIDLANDS); + BuiltinRegistries.register(registry, BiomeAPI.THE_END.getBCLBiomeKey(), BiomeAPI.THE_END); + BuiltinRegistries.register( + registry, + BiomeAPI.BASALT_DELTAS_BIOME.getBCLBiomeKey(), + BiomeAPI.BASALT_DELTAS_BIOME + ); + BuiltinRegistries.register( + registry, + BiomeAPI.SOUL_SAND_VALLEY_BIOME.getBCLBiomeKey(), + BiomeAPI.SOUL_SAND_VALLEY_BIOME + ); + BuiltinRegistries.register( + registry, + BiomeAPI.WARPED_FOREST_BIOME.getBCLBiomeKey(), + BiomeAPI.WARPED_FOREST_BIOME + ); + BuiltinRegistries.register( + registry, + BiomeAPI.CRIMSON_FOREST_BIOME.getBCLBiomeKey(), + BiomeAPI.CRIMSON_FOREST_BIOME + ); + BuiltinRegistries.register( + registry, + BiomeAPI.NETHER_WASTES_BIOME.getBCLBiomeKey(), + BiomeAPI.NETHER_WASTES_BIOME + ); + return BuiltinRegistries.register(registry, EMPTY_BIOME.getBCLBiomeKey(), EMPTY_BIOME); + } + + public static BCLBiome get(ResourceLocation loc) { + return get(WorldBootstrap.getLastRegistryAccessOrElseBuiltin(), loc); + } + + public static BCLBiome get(RegistryAccess access, ResourceLocation loc) { + return getBclBiomesRegistry(access).get(loc); + } + + public static BCLBiome getOrElseEmpty(ResourceLocation loc) { + return getOrElseEmpty(WorldBootstrap.getLastRegistryAccessOrElseBuiltin(), loc); + } + + public static BCLBiome getOrElseEmpty(RegistryAccess access, ResourceLocation loc) { + BCLBiome res = get(access, loc); + if (res == null) return EMPTY_BIOME; + return res; + } + + public static Stream> getAll(BiomeAPI.BiomeType dim) { + return getAll(WorldBootstrap.getLastRegistryAccessOrElseBuiltin(), dim); + } + + public static Stream> getAll(RegistryAccess access, BiomeAPI.BiomeType dim) { + return getBclBiomesRegistry(access) + .entrySet() + .stream() + .filter(e -> e.getValue().getIntendedType().is(BiomeAPI.BiomeType.END)) + .map(e -> e.getKey()); + } + + private static Registry getBclBiomesRegistry(RegistryAccess access) { + if (access != null) { + return ((Optional>) access + .registry(BCLBiomeRegistry.BCL_BIOMES_REGISTRY)) + .orElse(BUILTIN_BCL_BIOMES); + } else { + return BUILTIN_BCL_BIOMES; + } + } + + public static void ensureStaticallyLoaded() { + + } +} diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeSettings.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeSettings.java index 6f2a560b..948702c6 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeSettings.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BCLBiomeSettings.java @@ -103,6 +103,22 @@ public class BCLBiomeSettings { } } + BCLBiomeSettings( + float terrainHeight, + float fogDensity, + float genChance, + int edgeSize, + boolean vertical, + BCLBiome edge + ) { + this.terrainHeight = terrainHeight; + this.fogDensity = fogDensity; + this.genChance = genChance; + this.edgeSize = edgeSize; + this.vertical = vertical; + this.edge = edge; + } + protected BCLBiomeSettings() { this.terrainHeight = 0.1F; this.fogDensity = 1.0F; diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeAPI.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeAPI.java index a7169b94..7353db38 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeAPI.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeAPI.java @@ -8,8 +8,10 @@ import org.betterx.bclib.mixin.common.MobSpawnSettingsAccessor; import org.betterx.bclib.util.CollectionsUtil; import org.betterx.worlds.together.tag.v3.CommonBiomeTags; import org.betterx.worlds.together.tag.v3.TagManager; +import org.betterx.worlds.together.world.event.WorldBootstrap; -import net.minecraft.client.Minecraft; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.core.HolderSet; @@ -38,53 +40,142 @@ import net.minecraft.world.level.levelgen.feature.ConfiguredFeature; import net.minecraft.world.level.levelgen.feature.Feature; import net.minecraft.world.level.levelgen.placement.PlacedFeature; -import net.fabricmc.api.EnvType; -import net.fabricmc.api.Environment; import net.fabricmc.fabric.api.biome.v1.NetherBiomes; import net.fabricmc.fabric.api.biome.v1.TheEndBiomes; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; +import java.util.*; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.Collectors; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class BiomeAPI { public static class BiomeType { + public static final Codec DIRECT_CODEC = RecordCodecBuilder.create(instance -> instance + .group( + Codec.STRING.fieldOf("name") + .orElse("undefined") + .forGetter(o -> o.name) + + ).apply(instance, BiomeType::create)); + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance + .group( + Codec.STRING.fieldOf("name") + .orElse("undefined") + .forGetter(o -> o.name), + Codec.STRING.fieldOf("parent") + .orElse("none") + .forGetter(o -> o.parentOrNull == null ? "none" : o.parentOrNull.name) + + ).apply(instance, BiomeType::create)); + + private static final Map KNOWN_TYPES = new HashMap<>(); + public static final BiomeType NONE = new BiomeType("NONE"); public static final BiomeType OVERWORLD = new BiomeType("OVERWORLD"); public static final BiomeType NETHER = new BiomeType("NETHER"); - public static final BiomeType BCL_NETHER = new BiomeType("BCL_NETHER", NETHER); + public static final BiomeType BCL_NETHER = new BiomeType("BCL_NETHER", NETHER, (biome, ignored) -> { + ResourceKey key = biome.getBiomeKey(); + if (!biome.isEdgeBiome()) { + biome.forEachClimateParameter(p -> NetherBiomes.addNetherBiome(key, p)); + } + }); public static final BiomeType END = new BiomeType("END"); public static final BiomeType END_IGNORE = new BiomeType("END_IGNORE", END); public static final BiomeType END_LAND = new BiomeType("END_LAND", END); public static final BiomeType END_VOID = new BiomeType("END_VOID", END); public static final BiomeType END_CENTER = new BiomeType("END_CENTER", END); public static final BiomeType END_BARRENS = new BiomeType("END_BARRENS", END); - public static final BiomeType BCL_END_LAND = new BiomeType("BCL_END_LAND", END_LAND); - public static final BiomeType BCL_END_VOID = new BiomeType("BCL_END_VOID", END_VOID); - public static final BiomeType BCL_END_CENTER = new BiomeType("BCL_END_CENTER", END_CENTER); - public static final BiomeType BCL_END_BARRENS = new BiomeType("BCL_END_BARRENS", END_BARRENS); + public static final BiomeType BCL_END_LAND = new BiomeType("BCL_END_LAND", END_LAND, (biome, ignored) -> { + float weight = biome.getGenChance(); + ResourceKey key = biome.getBiomeKey(); + + if (biome.isEdgeBiome()) { + ResourceKey parentKey = biome.getParentBiome().getBiomeKey(); + TheEndBiomes.addMidlandsBiome(parentKey, key, weight); + } else { + TheEndBiomes.addHighlandsBiome(key, weight); + } + }); + public static final BiomeType BCL_END_VOID = new BiomeType("BCL_END_VOID", END_VOID, (biome, ignored) -> { + float weight = biome.getGenChance(); + ResourceKey key = biome.getBiomeKey(); + if (!biome.isEdgeBiome()) { + TheEndBiomes.addSmallIslandsBiome(key, weight); + } + }); + public static final BiomeType BCL_END_CENTER = new BiomeType("BCL_END_CENTER", END_CENTER, (biome, ignored) -> { + float weight = biome.getGenChance(); + ResourceKey key = biome.getBiomeKey(); + if (!biome.isEdgeBiome()) { + TheEndBiomes.addMainIslandBiome(key, weight); + } + }); + + public static final BiomeType BCL_END_BARRENS = new BiomeType( + "BCL_END_BARRENS", + END_BARRENS, + (biome, highlandBiome) -> { + float weight = biome.getGenChance(); + ResourceKey key = biome.getBiomeKey(); + if (!biome.isEdgeBiome()) { + ResourceKey parentKey = highlandBiome.getBiomeKey(); + TheEndBiomes.addBarrensBiome(parentKey, key, weight); + } + } + ); - static final Map BIOME_TYPE_MAP = Maps.newHashMap(); public final BiomeType parentOrNull; private final String name; + @FunctionalInterface + interface ExtraRegisterTaks { + void register(@NotNull BCLBiome biome, @Nullable BCLBiome parent); + } + + final ExtraRegisterTaks extraRegisterTask; + + private static BiomeType create(String name, String parentOrNull) { + BiomeType known = KNOWN_TYPES.get(name); + BiomeType parent = parentOrNull == null || "none".equals(parentOrNull) + ? null + : KNOWN_TYPES.get(parentOrNull); + if (known != null) { + if (known.parentOrNull != parent) { + BCLib.LOGGER.warning("BiomeType " + name + " was deserialized with parent " + parent + " but already has " + known.parentOrNull); + } + return known; + } + return new BiomeType(name, parent); + } + + static BiomeType create(String name) { + BiomeType known = KNOWN_TYPES.get(name); + if (known != null) { + return known; + } + return NONE; + } + public BiomeType(String name) { this(name, null); } public BiomeType(String name, BiomeType parentOrNull) { + this(name, parentOrNull, (b, a) -> { + }); + } + + public BiomeType(String name, BiomeType parentOrNull, ExtraRegisterTaks extraRegisterTask) { this.parentOrNull = parentOrNull; this.name = name; + this.extraRegisterTask = extraRegisterTask; + KNOWN_TYPES.put(name, this); } public boolean is(BiomeType d) { @@ -108,10 +199,10 @@ public class BiomeAPI { /** * Empty biome used as default value if requested biome doesn't exist or linked. Shouldn't be registered anywhere to prevent bugs. * Have {@code Biomes.THE_VOID} as the reference biome. + * + * @deprecated use {@link BCLBiomeRegistry#EMPTY_BIOME} instead */ - public static final BCLBiome EMPTY_BIOME = new BCLBiome(Biomes.THE_VOID.location()); - - private static final Map ID_MAP = Maps.newHashMap(); + public static final BCLBiome EMPTY_BIOME = BCLBiomeRegistry.EMPTY_BIOME; public static final BCLBiome NETHER_WASTES_BIOME = InternalBiomeAPI.wrapNativeBiome( Biomes.NETHER_WASTES, @@ -166,6 +257,16 @@ public class BiomeAPI { InternalBiomeAPI.OTHER_END_VOID ); + /** + * Register {@link BCLBiome} instance and its {@link Biome} if necessary. + * + * @param bclbiome {@link BCLBiome} + * @return {@link BCLBiome} + */ + public static BCLBiome registerBiome(BCLBiome bclbiome) { + return registerBiome(bclbiome, BuiltinRegistries.BIOME); + } + /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. * @@ -173,6 +274,7 @@ public class BiomeAPI { * @param dim The Dimension fo rthis Biome * @return {@link BCLBiome} */ + @Deprecated(forRemoval = true) public static BCLBiome registerBiome(BCLBiome bclbiome, BiomeType dim) { return registerBiome(bclbiome, dim, BuiltinRegistries.BIOME); } @@ -184,15 +286,27 @@ public class BiomeAPI { * @param dim The Dimension fo rthis Biome * @return {@link BCLBiome} */ + @Deprecated(forRemoval = true) static BCLBiome registerBiome(BCLBiome bclbiome, BiomeType dim, Registry registryOrNull) { + bclbiome._setIntendedType(dim); + return registerBiome(bclbiome, registryOrNull); + } + + /** + * Register {@link BCLBiome} instance and its {@link Biome} if necessary. + * + * @param bclbiome {@link BCLBiome} + * @return {@link BCLBiome} + */ + static BCLBiome registerBiome(BCLBiome bclbiome, Registry registryOrNull) { + BiomeType dim = bclbiome.getIntendedType(); if (registryOrNull != null && bclbiome.biomeToRegister != null && registryOrNull.get(bclbiome.getID()) == null) { Registry.register(registryOrNull, bclbiome.getBiomeKey(), bclbiome.biomeToRegister); - } - ID_MAP.put(bclbiome.getID(), bclbiome); - BiomeType.BIOME_TYPE_MAP.put(bclbiome.getID(), dim); + BCLBiomeRegistry.register(bclbiome); + } if (dim != null && dim.is(BiomeType.NETHER)) { TagManager.BIOMES.add(BiomeTags.IS_NETHER, bclbiome.getBiomeKey()); @@ -211,7 +325,7 @@ public class BiomeAPI { return registerSubBiome( parent, subBiome, - BiomeType.BIOME_TYPE_MAP.getOrDefault(parent.getID(), BiomeType.NONE) + parent.getIntendedType() ); } @@ -220,7 +334,7 @@ public class BiomeAPI { parent, subBiome, genChance, - BiomeType.BIOME_TYPE_MAP.getOrDefault(parent.getID(), BiomeType.NONE) + parent.getIntendedType() ); } @@ -248,14 +362,14 @@ public class BiomeAPI { float weight = biome.getGenChance(); ResourceKey key = biome.getBiomeKey(); - if (biome.allowFabricRegistration()) { - if (biome.isEdgeBiome()) { - ResourceKey parentKey = biome.getParentBiome().getBiomeKey(); - TheEndBiomes.addMidlandsBiome(parentKey, key, weight); - } else { - TheEndBiomes.addHighlandsBiome(key, weight); - } + + if (biome.isEdgeBiome()) { + ResourceKey parentKey = biome.getParentBiome().getBiomeKey(); + TheEndBiomes.addMidlandsBiome(parentKey, key, weight); + } else { + TheEndBiomes.addHighlandsBiome(key, weight); } + return biome; } @@ -272,7 +386,7 @@ public class BiomeAPI { float weight = biome.getGenChance(); ResourceKey key = biome.getBiomeKey(); - if (biome.allowFabricRegistration()) { + if (!biome.isEdgeBiome()) { TheEndBiomes.addSmallIslandsBiome(key, weight); } return biome; @@ -291,7 +405,7 @@ public class BiomeAPI { float weight = biome.getGenChance(); ResourceKey key = biome.getBiomeKey(); - if (biome.allowFabricRegistration()) { + if (!biome.isEdgeBiome()) { TheEndBiomes.addMainIslandBiome(key, weight); } return biome; @@ -310,7 +424,7 @@ public class BiomeAPI { float weight = biome.getGenChance(); ResourceKey key = biome.getBiomeKey(); - if (biome.allowFabricRegistration()) { + if (!biome.isEdgeBiome()) { ResourceKey parentKey = highlandBiome.getBiomeKey(); TheEndBiomes.addBarrensBiome(parentKey, key, weight); } @@ -318,17 +432,20 @@ public class BiomeAPI { } - public static BCLBiome registerEndBiome(Holder biome) { - BCLBiome bclBiome = new BCLBiome(biome.value(), null); + /** + * Register {@link BCLBiome} instance and its {@link Biome} if necessary. + * After that biome will be added to BCLib Nether Biome Generator and into Fabric Biome API. + * + * @param bclBiome {@link BCLBiome} + * @return {@link BCLBiome} + */ + public static BCLBiome registerNetherBiome(BCLBiome bclBiome) { + registerBiome(bclBiome, BiomeType.BCL_NETHER); - registerBiome(bclBiome, BiomeType.END); - return bclBiome; - } - - public static BCLBiome registerCenterBiome(Holder biome) { - BCLBiome bclBiome = new BCLBiome(biome.value(), null); - - registerBiome(bclBiome, BiomeType.END_CENTER); + ResourceKey key = bclBiome.getBiomeKey(); + if (!bclBiome.isEdgeBiome()) { + bclBiome.forEachClimateParameter(p -> NetherBiomes.addNetherBiome(key, p)); + } return bclBiome; } @@ -342,9 +459,13 @@ public class BiomeAPI { @Deprecated(forRemoval = true) public static BCLBiome getFromBiome(Holder biome) { if (InternalBiomeAPI.biomeRegistry == null) { - return EMPTY_BIOME; + return BCLBiomeRegistry.EMPTY_BIOME; } - return ID_MAP.getOrDefault(biome.unwrapKey().orElseThrow().location(), EMPTY_BIOME); + return BCLBiomeRegistry + .getOrElseEmpty( + InternalBiomeAPI.registryAccess, + biome.unwrapKey().orElseThrow().location() + ); } /** @@ -353,15 +474,15 @@ public class BiomeAPI { * @param biome - {@link Biome} from client world. * @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}. */ - @Environment(EnvType.CLIENT) public static BCLBiome getRenderBiome(Biome biome) { BCLBiome endBiome = InternalBiomeAPI.CLIENT.get(biome); if (endBiome == null) { - Minecraft minecraft = Minecraft.getInstance(); - ResourceLocation id = minecraft.level.registryAccess() - .registryOrThrow(Registry.BIOME_REGISTRY) - .getKey(biome); - endBiome = id == null ? EMPTY_BIOME : ID_MAP.getOrDefault(id, EMPTY_BIOME); + ResourceLocation id = WorldBootstrap.getLastRegistryAccessOrElseBuiltin() + .registryOrThrow(Registry.BIOME_REGISTRY) + .getKey(biome); + endBiome = id == null + ? BCLBiomeRegistry.EMPTY_BIOME + : BCLBiomeRegistry.getOrElseEmpty(id); InternalBiomeAPI.CLIENT.put(biome, endBiome); } return endBiome; @@ -401,7 +522,7 @@ public class BiomeAPI { if (id == null) { BCLib.LOGGER.error("Unable to get ID for " + biome + ". Falling back to empty Biome..."); - id = EMPTY_BIOME.getID(); + id = BCLBiomeRegistry.EMPTY_BIOME.getID(); } return id; @@ -414,11 +535,10 @@ public class BiomeAPI { * @return biome {@link ResourceLocation}. */ public static ResourceLocation getBiomeID(Holder biome) { - var oKey = biome.unwrapKey(); - if (oKey.isPresent()) { - return oKey.get().location(); - } - return null; + return biome + .unwrapKey() + .map(h -> h.location()) + .orElse(null); } public static ResourceKey getBiomeKey(Holder biome) { @@ -462,7 +582,8 @@ public class BiomeAPI { * @return {@link BCLBiome} or {@code BiomeAPI.EMPTY_BIOME}. */ public static BCLBiome getBiome(ResourceLocation biomeID) { - return ID_MAP.getOrDefault(biomeID, EMPTY_BIOME); + if (biomeID == null) return BCLBiomeRegistry.EMPTY_BIOME; + return BCLBiomeRegistry.getOrElseEmpty(biomeID); } /** @@ -492,7 +613,7 @@ public class BiomeAPI { * @return {@code true} if biome exists in API registry and {@code false} if not. */ public static boolean hasBiome(ResourceLocation biomeID) { - return ID_MAP.containsKey(biomeID); + return BCLBiomeRegistry.get(biomeID) != null; } public static Holder getFromRegistry(ResourceLocation biomeID) { @@ -537,12 +658,9 @@ public class BiomeAPI { } public static boolean wasRegisteredAs(ResourceLocation biomeID, BiomeType dim) { - if (BiomeType.BIOME_TYPE_MAP.containsKey(biomeID) && BiomeType.BIOME_TYPE_MAP.get(biomeID).is(dim)) return true; - BCLBiome biome = getBiome(biomeID); - if (biome != null && biome != BiomeAPI.EMPTY_BIOME && biome.getParentBiome() != null) { - return wasRegisteredAs(biome.getParentBiome().getID(), dim); - } - return false; + if (BCLBiomeRegistry.EMPTY_BIOME.getID().equals(biomeID)) + return false; + return BCLBiomeRegistry.getOrElseEmpty(biomeID).getIntendedType().is(dim); } public static boolean wasRegisteredAsNetherBiome(ResourceLocation biomeID) { @@ -883,22 +1001,6 @@ public class BiomeAPI { return features.get(index).stream().collect(Collectors.toList()); } - /** - * Register {@link BCLBiome} instance and its {@link Biome} if necessary. - * After that biome will be added to BCLib Nether Biome Generator and into Fabric Biome API. - * - * @param bclBiome {@link BCLBiome} - * @return {@link BCLBiome} - */ - public static BCLBiome registerNetherBiome(BCLBiome bclBiome) { - registerBiome(bclBiome, BiomeType.BCL_NETHER); - - ResourceKey key = bclBiome.getBiomeKey(); - if (bclBiome.allowFabricRegistration()) { - bclBiome.forEachClimateParameter(p -> NetherBiomes.addNetherBiome(key, p)); - } - return bclBiome; - } /** * Register {@link BCLBiome} instance and its {@link Biome} if necessary. @@ -962,4 +1064,22 @@ public class BiomeAPI { InternalBiomeAPI.OTHER_END_VOID ); } + + + @Deprecated(forRemoval = true) + public static BCLBiome registerEndBiome(Holder biome) { + BCLBiome bclBiome = new BCLBiome(biome.value(), null); + + registerBiome(bclBiome, BiomeType.END); + return bclBiome; + } + + + @Deprecated(forRemoval = true) + public static BCLBiome registerCenterBiome(Holder biome) { + BCLBiome bclBiome = new BCLBiome(biome.value(), null); + + registerBiome(bclBiome, BiomeType.END_CENTER); + return bclBiome; + } } diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeData.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeData.java new file mode 100644 index 00000000..2997ef38 --- /dev/null +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/BiomeData.java @@ -0,0 +1,15 @@ +package org.betterx.bclib.api.v2.levelgen.biomes; + +import com.mojang.serialization.Codec; +import net.minecraft.util.KeyDispatchDataCodec; + +import java.util.function.Function; + +public interface BiomeData { + Codec CODEC = BCLBiomeRegistry + .BIOME_CODECS + .byNameCodec() + .dispatch(b -> b.codec().codec(), Function.identity()); + + KeyDispatchDataCodec codec(); +} diff --git a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java index ba14625f..0b0cce96 100644 --- a/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java +++ b/src/main/java/org/betterx/bclib/api/v2/levelgen/biomes/InternalBiomeAPI.java @@ -165,16 +165,10 @@ public class InternalBiomeAPI { public static void _runBiomeTagAdders() { for (var mod : TAG_ADDERS.entrySet()) { Stream s = null; - if (mod.getKey() == Level.NETHER) s = BiomeAPI.BiomeType.BIOME_TYPE_MAP.entrySet() - .stream() - .filter(e -> e.getValue() - .is(BiomeAPI.BiomeType.NETHER)) - .map(e -> e.getKey()); - else if (mod.getKey() == Level.END) s = BiomeAPI.BiomeType.BIOME_TYPE_MAP.entrySet() - .stream() - .filter(e -> e.getValue().is( - BiomeAPI.BiomeType.END)) - .map(e -> e.getKey()); + if (mod.getKey() == Level.NETHER) + s = BCLBiomeRegistry.getAll(BiomeAPI.BiomeType.NETHER).map(k -> k.location()); + else if (mod.getKey() == Level.END) + s = BCLBiomeRegistry.getAll(BiomeAPI.BiomeType.END).map(k -> k.location()); if (s != null) { s.forEach(id -> { Holder biomeHolder = BiomeAPI.getFromRegistry(id); @@ -326,11 +320,12 @@ public class InternalBiomeAPI { BiomeAPI.BiomeType type ) { BCLBiome bclBiome = BiomeAPI.getBiome(biomeKey.location()); - if (bclBiome == BiomeAPI.EMPTY_BIOME) { + if (bclBiome == BCLBiomeRegistry.EMPTY_BIOME) { bclBiome = new BCLBiome(biomeKey, setings); + bclBiome._setIntendedType(type); } - BiomeAPI.registerBiome(bclBiome, type); + BiomeAPI.registerBiome(bclBiome); return bclBiome; } @@ -345,7 +340,7 @@ public class InternalBiomeAPI { @Deprecated(forRemoval = true) static BCLBiome wrapNativeBiome(Biome biome, float genChance, BiomeAPI.BiomeType type) { BCLBiome bclBiome = BiomeAPI.getBiome(biome); - if (bclBiome == BiomeAPI.EMPTY_BIOME) { + if (bclBiome == BCLBiomeRegistry.EMPTY_BIOME) { bclBiome = new BCLBiome( biome, genChance < 0 ? null : VanillaBiomeSettings.createVanilla().setGenChance(genChance).build() @@ -363,7 +358,7 @@ public class InternalBiomeAPI { .event(oBiomeRegistry.get()) .register((rawId, id, biome) -> { BCLBiome b = BiomeAPI.getBiome(id); - if (!"minecraft".equals(id.getNamespace()) && (b == null || b == BiomeAPI.EMPTY_BIOME)) { + if (!"minecraft".equals(id.getNamespace()) && (b == null || b == BCLBiomeRegistry.EMPTY_BIOME)) { //BCLib.LOGGER.info(" #### " + rawId + ", " + biome + ", " + id); BIOMES_TO_SORT.add(id); } diff --git a/src/main/java/org/betterx/bclib/client/render/CustomFogRenderer.java b/src/main/java/org/betterx/bclib/client/render/CustomFogRenderer.java index c2308d9e..b4f122fd 100644 --- a/src/main/java/org/betterx/bclib/client/render/CustomFogRenderer.java +++ b/src/main/java/org/betterx/bclib/client/render/CustomFogRenderer.java @@ -1,6 +1,7 @@ package org.betterx.bclib.client.render; 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.config.Configs; import org.betterx.bclib.util.BackgroundInfo; @@ -116,7 +117,7 @@ public class CustomFogRenderer { private static boolean shouldIgnore(Level level, int x, int y, int z) { Biome biome = level.getBiome(MUT_POS.set(x, y, z)).value(); - return BiomeAPI.getRenderBiome(biome) == BiomeAPI.EMPTY_BIOME; + return BiomeAPI.getRenderBiome(biome) == BCLBiomeRegistry.EMPTY_BIOME; } private static float getFogDensityI(Level level, int x, int y, int z) { diff --git a/src/main/java/org/betterx/bclib/commands/DumpDatapack.java b/src/main/java/org/betterx/bclib/commands/DumpDatapack.java index bd8187f1..5f3d4003 100644 --- a/src/main/java/org/betterx/bclib/commands/DumpDatapack.java +++ b/src/main/java/org/betterx/bclib/commands/DumpDatapack.java @@ -1,9 +1,10 @@ package org.betterx.bclib.commands; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; +import org.betterx.bclib.BCLib; +import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome; +import org.betterx.bclib.api.v2.levelgen.biomes.BiomeData; +import org.betterx.bclib.blocks.BaseStairsBlock; + import com.mojang.brigadier.Command; import com.mojang.brigadier.context.CommandContext; import com.mojang.serialization.Codec; @@ -27,8 +28,11 @@ import net.minecraft.world.level.levelgen.structure.templatesystem.RuleTestType; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorList; import net.minecraft.world.level.levelgen.structure.templatesystem.StructureProcessorType; import net.minecraft.world.level.material.Fluid; -import org.betterx.bclib.BCLib; -import org.betterx.bclib.blocks.BaseStairsBlock; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; import java.awt.Taskbar.Feature; import java.io.File; @@ -113,13 +117,15 @@ public class DumpDatapack { while (obj instanceof Holder) { obj = ((Holder) obj).value(); } - + if (obj instanceof BiomeSource || obj instanceof Feature) { System.out.print(""); } - + if (obj instanceof Structure s) { codec[0] = s.type().codec(); + } else if (obj instanceof BCLBiome s) { + codec[0] = BiomeData.CODEC; } else if (obj instanceof StructureProcessorList s) { codec[0] = StructureProcessorType.LIST_OBJECT_CODEC; } else if (obj instanceof GameEvent) { @@ -134,9 +140,9 @@ public class DumpDatapack { codec[0] = registry.value().byNameCodec(); } else if (obj instanceof PosRuleTestType) { codec[0] = registry.value().byNameCodec(); - }else if (obj instanceof WorldGenSettings) { + } else if (obj instanceof WorldGenSettings) { codec[0] = registry.value().byNameCodec(); - }else if (obj instanceof LevelStem) { + } else if (obj instanceof LevelStem) { codec[0] = registry.value().byNameCodec(); } @@ -225,8 +231,8 @@ public class DumpDatapack { } } } - - if (codec[0]==null){ + + if (codec[0] == null) { codec[0] = registry.value().byNameCodec(); } diff --git a/src/main/java/org/betterx/bclib/mixin/common/BuiltinRegistriesMixin.java b/src/main/java/org/betterx/bclib/mixin/common/BuiltinRegistriesMixin.java new file mode 100644 index 00000000..b5733252 --- /dev/null +++ b/src/main/java/org/betterx/bclib/mixin/common/BuiltinRegistriesMixin.java @@ -0,0 +1,40 @@ +package org.betterx.bclib.mixin.common; + +import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry; + +import com.mojang.serialization.Lifecycle; +import net.minecraft.core.MappedRegistry; +import net.minecraft.core.Registry; +import net.minecraft.core.WritableRegistry; +import net.minecraft.data.BuiltinRegistries; +import net.minecraft.resources.ResourceKey; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(BuiltinRegistries.class) +public abstract class BuiltinRegistriesMixin { + @Shadow + protected static > R internalRegister( + ResourceKey> resourceKey, + R writableRegistry, + BuiltinRegistries.RegistryBootstrap registryBootstrap, + Lifecycle lifecycle + ) { + throw new RuntimeException("Shadowed Call"); + } + + //this needs to be added BEFORE the WORLD_PRESET-Registry. Otherwise decoding will fail! + @Inject(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/data/BuiltinRegistries;registerSimple(Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/data/BuiltinRegistries$RegistryBootstrap;)Lnet/minecraft/core/Registry;", ordinal = 0)) + private static void bcl_registerBuiltin(CallbackInfo ci) { + BCLBiomeRegistry.BUILTIN_BCL_BIOMES = internalRegister( + BCLBiomeRegistry.BCL_BIOMES_REGISTRY, + (MappedRegistry) BCLBiomeRegistry.BUILTIN_BCL_BIOMES, + BCLBiomeRegistry::bootstrap, + Lifecycle.stable() + ); + } +} diff --git a/src/main/java/org/betterx/bclib/mixin/common/RegistryAccessMixin.java b/src/main/java/org/betterx/bclib/mixin/common/RegistryAccessMixin.java new file mode 100644 index 00000000..79b6478e --- /dev/null +++ b/src/main/java/org/betterx/bclib/mixin/common/RegistryAccessMixin.java @@ -0,0 +1,48 @@ +package org.betterx.bclib.mixin.common; + +import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry; +import org.betterx.bclib.api.v2.levelgen.biomes.BiomeData; + +import com.mojang.serialization.Codec; +import net.minecraft.core.Registry; +import net.minecraft.core.RegistryAccess; +import net.minecraft.resources.ResourceKey; + +import com.google.common.collect.ImmutableMap; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import java.util.Map; +import java.util.function.Supplier; + +@Mixin(RegistryAccess.class) +public interface RegistryAccessMixin { + + @ModifyArg(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/Util;make(Ljava/util/function/Supplier;)Ljava/lang/Object;")) + private static Supplier>, RegistryAccess.RegistryData>> together_addRegistry( + Supplier>, RegistryAccess.RegistryData>> supplier + ) { + return () -> { + ImmutableMap.Builder>, RegistryAccess.RegistryData> builder = ImmutableMap.builder(); + //Make sure this gets added before WORLD_PRESETS + put(builder, BCLBiomeRegistry.BCL_BIOMES_REGISTRY, BiomeData.CODEC); + + Map>, RegistryAccess.RegistryData> res = supplier.get(); + builder.putAll(res); + + return builder.build(); + }; + } + + @Shadow + static void put( + ImmutableMap.Builder>, RegistryAccess.RegistryData> builder, + ResourceKey> resourceKey, + Codec codec + ) { + throw new RuntimeException("Shadowed Call"); + } + +} diff --git a/src/main/java/org/betterx/bclib/util/Pair.java b/src/main/java/org/betterx/bclib/util/Pair.java index 44c9db97..5495c16b 100644 --- a/src/main/java/org/betterx/bclib/util/Pair.java +++ b/src/main/java/org/betterx/bclib/util/Pair.java @@ -1,8 +1,20 @@ package org.betterx.bclib.util; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + import java.util.Objects; public class Pair { + public static Codec> pairCodec(Codec a, Codec b, String first, String second) { + return RecordCodecBuilder.create(instance -> instance + .group( + a.fieldOf(first).forGetter(o -> o.first), + b.fieldOf(second).forGetter(o -> o.second) + ) + .apply(instance, Pair::new)); + } + public final A first; public final B second; diff --git a/src/main/java/org/betterx/bclib/util/WeightedList.java b/src/main/java/org/betterx/bclib/util/WeightedList.java index 70a90f4a..330d48d7 100644 --- a/src/main/java/org/betterx/bclib/util/WeightedList.java +++ b/src/main/java/org/betterx/bclib/util/WeightedList.java @@ -1,17 +1,71 @@ package org.betterx.bclib.util; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.util.RandomSource; import java.util.ArrayList; import java.util.List; import java.util.Random; import java.util.function.Consumer; +import java.util.function.Function; public class WeightedList { + + private final List weights = new ArrayList(); private final List values = new ArrayList(); private float maxWeight; + public static Codec> pairCodec(Codec elementCodec, String fieldName) { + return Pair.pairCodec(Codec.FLOAT, elementCodec, "weight", fieldName); + } + + public static Codec> listCodec(Codec elementCodec, String fieldName, String elementName) { + return RecordCodecBuilder.create(instance -> instance + .group( + pairCodec(elementCodec, elementName).listOf() + .fieldOf(fieldName) + .forGetter(WeightedList::pairs) + ) + .apply(instance, WeightedList::new) + ); + } + + private List> pairs() { + List> pairs = new ArrayList<>(weights.size()); + for (int i = 0; i < weights.size(); i++) { + pairs.add(new Pair<>(weights.get(i), values.get(i))); + } + return pairs; + } + + private WeightedList(List> pairs) { + maxWeight = 0; + for (var pair : pairs) { + maxWeight += pair.first; + weights.add(pair.first); + values.add(pair.second); + } + } + + public WeightedList() { + } + + public WeightedList map(Function map) { + List> pairs = new ArrayList<>(weights.size()); + for (int i = 0; i < weights.size(); i++) { + pairs.add(new Pair<>(weights.get(i), map.apply(values.get(i)))); + } + return new WeightedList<>(pairs); + } + + public void addAll(WeightedList other) { + weights.addAll(other.weights); + values.addAll(other.values); + maxWeight += other.maxWeight; + } + /** * Adds value with specified weight to the list * diff --git a/src/main/java/org/betterx/worlds/together/biomesource/ReloadableBiomeSource.java b/src/main/java/org/betterx/worlds/together/biomesource/ReloadableBiomeSource.java new file mode 100644 index 00000000..377c3110 --- /dev/null +++ b/src/main/java/org/betterx/worlds/together/biomesource/ReloadableBiomeSource.java @@ -0,0 +1,5 @@ +package org.betterx.worlds.together.biomesource; + +public interface ReloadableBiomeSource { + void reloadBiomes(); +} diff --git a/src/main/java/org/betterx/worlds/together/chunkgenerator/RestorableBiomeSource.java b/src/main/java/org/betterx/worlds/together/chunkgenerator/RestorableBiomeSource.java index 90d3e45e..11ca787f 100644 --- a/src/main/java/org/betterx/worlds/together/chunkgenerator/RestorableBiomeSource.java +++ b/src/main/java/org/betterx/worlds/together/chunkgenerator/RestorableBiomeSource.java @@ -4,6 +4,6 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.dimension.LevelStem; -public interface RestorableBiomeSource { +public interface RestorableBiomeSource { void restoreInitialBiomeSource(ResourceKey dimensionKey); } diff --git a/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java b/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java index 4a82f11f..3fe9c066 100644 --- a/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java +++ b/src/main/java/org/betterx/worlds/together/levelgen/WorldGenUtil.java @@ -2,6 +2,7 @@ package org.betterx.worlds.together.levelgen; import org.betterx.worlds.together.WorldsTogether; import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig; +import org.betterx.worlds.together.biomesource.ReloadableBiomeSource; import org.betterx.worlds.together.chunkgenerator.EnforceableChunkGenerator; import org.betterx.worlds.together.world.BiomeSourceWithNoiseRelatedSettings; import org.betterx.worlds.together.world.BiomeSourceWithSeed; @@ -141,6 +142,7 @@ public class WorldGenUtil { ) { var dimensions = TogetherWorldPreset.loadWorldDimensions(); for (var entry : settings.dimensions().entrySet()) { + boolean didRepair = false; ResourceKey key = entry.getKey(); LevelStem loadedStem = entry.getValue(); @@ -156,6 +158,7 @@ public class WorldGenUtil { loadedChunkGenerator, settings ); + didRepair = true; } else if (loadedChunkGenerator.getBiomeSource() instanceof BiomeSourceWithConfig bs) { if (referenceGenerator.getBiomeSource() instanceof BiomeSourceWithConfig refbs) { if (!refbs.getTogetherConfig().sameConfig(bs.getTogetherConfig())) { @@ -164,6 +167,12 @@ public class WorldGenUtil { } } } + + if (!didRepair) { + if (loadedStem.generator().getBiomeSource() instanceof ReloadableBiomeSource reload) { + reload.reloadBiomes(); + } + } } return settings; } diff --git a/src/main/java/org/betterx/worlds/together/mixin/common/WorldLoaderMixin.java b/src/main/java/org/betterx/worlds/together/mixin/common/WorldLoaderMixin.java new file mode 100644 index 00000000..d2ea695a --- /dev/null +++ b/src/main/java/org/betterx/worlds/together/mixin/common/WorldLoaderMixin.java @@ -0,0 +1,22 @@ +package org.betterx.worlds.together.mixin.common; + +import org.betterx.worlds.together.world.event.WorldBootstrap; + +import net.minecraft.core.RegistryAccess; +import net.minecraft.server.WorldLoader; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +@Mixin(WorldLoader.class) +public class WorldLoaderMixin { + //this is the place a new Registry access gets first istantiated + //either when a new Datapack was added to a world on the create-screen + //or because we did start world loading + @ModifyArg(method = "load", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/ReloadableServerResources;loadResources(Lnet/minecraft/server/packs/resources/ResourceManager;Lnet/minecraft/core/RegistryAccess$Frozen;Lnet/minecraft/commands/Commands$CommandSelection;ILjava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)Ljava/util/concurrent/CompletableFuture;")) + private static RegistryAccess.Frozen wt_newRegistry(RegistryAccess.Frozen frozen) { + WorldBootstrap.InGUI.registryReady(frozen); + return frozen; + } +} diff --git a/src/main/java/org/betterx/worlds/together/surfaceRules/SurfaceRuleRegistry.java b/src/main/java/org/betterx/worlds/together/surfaceRules/SurfaceRuleRegistry.java index 6f465c83..6aba4351 100644 --- a/src/main/java/org/betterx/worlds/together/surfaceRules/SurfaceRuleRegistry.java +++ b/src/main/java/org/betterx/worlds/together/surfaceRules/SurfaceRuleRegistry.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.ApiStatus; public class SurfaceRuleRegistry { public static final ResourceKey> SURFACE_RULES_REGISTRY = - createRegistryKey(WorldsTogether.makeID("worldgen/surface_rules")); + createRegistryKey(WorldsTogether.makeID("worldgen/betterx/surface_rules")); public static final Predicate> NON_MANAGED_DIMENSIONS = dim -> dim != LevelStem.NETHER && dim != LevelStem.END; public static final Predicate> ALL_DIMENSIONS = dim -> true; diff --git a/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java b/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java index fd64e9b9..a87d5db2 100644 --- a/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java +++ b/src/main/java/org/betterx/worlds/together/world/event/WorldBootstrap.java @@ -154,6 +154,10 @@ public class WorldBootstrap { } } + public static void registryReady(RegistryAccess access) { + Helpers.onRegistryReady(access); + } + public static void setupNewWorld( Optional levelStorageAccess, WorldGenSettingsComponent worldGenSettingsComponent diff --git a/src/main/resources/bclib.accesswidener b/src/main/resources/bclib.accesswidener index f79bad60..35c028ec 100644 --- a/src/main/resources/bclib.accesswidener +++ b/src/main/resources/bclib.accesswidener @@ -11,10 +11,12 @@ accessible class net/minecraft/world/level/levelgen/SurfaceRules$SequenceRuleSou accessible class net/minecraft/world/level/levelgen/presets/WorldPresets$Bootstrap extendable class net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator accessible class net/minecraft/data/BuiltinRegistries$RegistryBootstrap +accessible class net/minecraft/core/Registry$RegistryBootstrap accessible class net/minecraft/world/level/levelgen/SurfaceRules$SequenceRuleSource #Methods accessible method net/minecraft/client/gui/screens/worldselection/WorldGenSettingsComponent updateSettings (Lnet/minecraft/client/gui/screens/worldselection/WorldCreationContext$Updater;)V accessible method net/minecraft/world/level/storage/loot/LootPool ([Lnet/minecraft/world/level/storage/loot/entries/LootPoolEntryContainer;[Lnet/minecraft/world/level/storage/loot/predicates/LootItemCondition;[Lnet/minecraft/world/level/storage/loot/functions/LootItemFunction;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;Lnet/minecraft/world/level/storage/loot/providers/number/NumberProvider;)V accessible method net/minecraft/world/entity/ai/village/poi/PoiTypes register (Lnet/minecraft/core/Registry;Lnet/minecraft/resources/ResourceKey;Ljava/util/Set;II)Lnet/minecraft/world/entity/ai/village/poi/PoiType; -accessible method net/minecraft/world/level/levelgen/SurfaceRules$SequenceRuleSource (Ljava/util/List;)V \ No newline at end of file +accessible method net/minecraft/world/level/levelgen/SurfaceRules$SequenceRuleSource (Ljava/util/List;)V +accessible method net/minecraft/core/Registry registerSimple (Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/core/Registry$RegistryBootstrap;)Lnet/minecraft/core/Registry; \ No newline at end of file diff --git a/src/main/resources/bclib.mixins.common.json b/src/main/resources/bclib.mixins.common.json index 8b7bf1aa..538b02ed 100644 --- a/src/main/resources/bclib.mixins.common.json +++ b/src/main/resources/bclib.mixins.common.json @@ -10,6 +10,7 @@ "BiomeMixin", "BiomeSourceMixin", "BoneMealItemMixin", + "BuiltinRegistriesMixin", "ChunkGeneratorAccessor", "ChunkGeneratorMixin", "ChunkGeneratorsMixin", @@ -28,6 +29,7 @@ "PotionBrewingAccessor", "RecipeManagerAccessor", "RecipeManagerMixin", + "RegistryAccessMixin", "ServerLevelMixin", "ShovelItemAccessor", "StructuresAccessor", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ea76eab7..ef506323 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "bclib", - "version": "2.0.10", + "version": "2.0.11", "name": "BCLib", "description": "A library for BetterX team mods", "authors": [ diff --git a/src/main/resources/together.mixins.common.json b/src/main/resources/together.mixins.common.json index 75e009db..45f965d9 100644 --- a/src/main/resources/together.mixins.common.json +++ b/src/main/resources/together.mixins.common.json @@ -17,6 +17,7 @@ "RegistryOpsAccessor", "TagLoaderMixin", "WorldGenPropertiesMixin", + "WorldLoaderMixin", "WorldPresetAccessor", "WorldPresetMixin", "WorldPresetsBootstrapMixin"