[Change] Removed BCLBiomeSource

This commit is contained in:
Frank 2023-09-12 13:50:23 +02:00
parent 3973a1a78f
commit e80004efcf
19 changed files with 0 additions and 2383 deletions

View file

@ -2,9 +2,6 @@ package org.betterx.bclib;
import org.betterx.bclib.api.v2.dataexchange.DataExchangeAPI;
import org.betterx.bclib.api.v2.dataexchange.handler.autosync.*;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
import org.betterx.bclib.api.v2.generator.GeneratorOptions;
import org.betterx.bclib.api.v2.levelgen.LevelGenEvents;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiomeRegistry;
import org.betterx.bclib.api.v2.levelgen.structures.BCLStructurePoolElementTypes;
@ -73,10 +70,7 @@ public class BCLib implements ModInitializer {
BlockPredicates.ensureStaticInitialization();
BCLBiomeRegistry.register();
BaseRegistry.register();
GeneratorOptions.init();
BaseBlockEntities.register();
BCLibEndBiomeSource.register();
BCLibNetherBiomeSource.register();
CraftingRecipes.init();
BCLStructurePoolElementTypes.ensureStaticallyLoaded();
WorldConfig.registerModCache(MOD_ID);

View file

@ -1,286 +0,0 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
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.worlds.together.biomesource.BiomeSourceHelper;
import org.betterx.worlds.together.biomesource.MergeableBiomeSource;
import org.betterx.worlds.together.biomesource.ReloadableBiomeSource;
import org.betterx.worlds.together.world.BiomeSourceWithNoiseRelatedSettings;
import org.betterx.worlds.together.world.BiomeSourceWithSeed;
import org.betterx.worlds.together.world.event.WorldBootstrap;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.levelgen.NoiseGeneratorSettings;
import java.util.*;
import java.util.stream.Stream;
import org.jetbrains.annotations.NotNull;
public abstract class BCLBiomeSource extends BiomeSource implements BiomeSourceWithSeed, MergeableBiomeSource<BCLBiomeSource>, BiomeSourceWithNoiseRelatedSettings, ReloadableBiomeSource {
@FunctionalInterface
public interface PickerAdder {
boolean add(BCLBiome bclBiome, BiomeAPI.BiomeType type, BiomePicker picker);
}
@FunctionalInterface
public interface CustomTypeFinder {
BiomeAPI.BiomeType find(ResourceKey<Biome> biomeKey, BiomeAPI.BiomeType defaultType);
}
protected long currentSeed;
protected int maxHeight;
private boolean didCreatePickers;
Set<Holder<Biome>> dynamicPossibleBiomes;
protected BCLBiomeSource(long seed) {
super();
this.dynamicPossibleBiomes = Set.of();
this.currentSeed = seed;
this.didCreatePickers = false;
}
@Override
protected Stream<Holder<Biome>> collectPossibleBiomes() {
reloadBiomes();
return dynamicPossibleBiomes.stream();
}
@Override
public Set<Holder<Biome>> possibleBiomes() {
return dynamicPossibleBiomes;
}
protected boolean wasBound() {
return didCreatePickers;
}
final public void setSeed(long seed) {
if (seed != currentSeed) {
BCLib.LOGGER.debug(this + "\n --> new seed = " + seed);
this.currentSeed = seed;
initMap(seed);
}
}
/**
* Set world height
*
* @param maxHeight height of the World.
*/
final public void setMaxHeight(int maxHeight) {
if (this.maxHeight != maxHeight) {
BCLib.LOGGER.debug(this + "\n --> new height = " + maxHeight);
this.maxHeight = maxHeight;
onHeightChange(maxHeight);
}
}
protected final void initMap(long seed) {
BCLib.LOGGER.debug(this + "\n --> Map Update");
onInitMap(seed);
}
protected abstract void onInitMap(long newSeed);
protected abstract void onHeightChange(int newHeight);
@NotNull
protected String getNamespaces() {
return BiomeSourceHelper.getNamespaces(possibleBiomes());
}
protected boolean addToPicker(BCLBiome bclBiome, BiomeAPI.BiomeType type, BiomePicker picker) {
picker.addBiome(bclBiome);
return true;
}
protected BiomeAPI.BiomeType typeForUnknownBiome(ResourceKey<Biome> biomeKey, BiomeAPI.BiomeType defaultType) {
return defaultType;
}
protected static Set<Holder<Biome>> populateBiomePickers(
Map<BiomeAPI.BiomeType, BiomePicker> acceptedBiomeTypes,
BiomeAPI.BiomeType exclusionListType,
PickerAdder pickerAdder,
CustomTypeFinder typeFinder
) {
final RegistryAccess access = WorldBootstrap.getLastRegistryAccess();
if (access == null) {
if (Configs.MAIN_CONFIG.verboseLogging() && !BCLib.isDatagen()) {
BCLib.LOGGER.info("Unable to build Biome List yet");
}
return null;
}
final Set<Holder<Biome>> allBiomes = new HashSet<>();
final Map<BiomeAPI.BiomeType, List<String>> includeMap = Configs.BIOMES_CONFIG.getBiomeIncludeMap();
final List<String> excludeList = Configs.BIOMES_CONFIG.getExcludeMatching(exclusionListType);
final Registry<Biome> biomes = access.registryOrThrow(Registries.BIOME);
final Registry<BCLBiome> bclBiomes = access.registryOrThrow(BCLBiomeRegistry.BCL_BIOMES_REGISTRY);
final List<Map.Entry<ResourceKey<Biome>, Biome>> sortedList = biomes
.entrySet()
.stream()
.sorted(Comparator.comparing(a -> a.getKey().location().toString()))
.toList();
for (Map.Entry<ResourceKey<Biome>, Biome> biomeEntry : sortedList) {
if (excludeList.contains(biomeEntry.getKey().location())) continue;
BiomeAPI.BiomeType type = BiomeAPI.BiomeType.NONE;
boolean foundBCLBiome = false;
if (BCLBiomeRegistry.hasBiome(biomeEntry.getKey(), bclBiomes)) {
foundBCLBiome = true;
type = BCLBiomeRegistry.getBiome(biomeEntry.getKey(), bclBiomes).getIntendedType();
} else {
type = typeFinder.find(biomeEntry.getKey(), type);
}
type = getBiomeType(includeMap, biomeEntry.getKey(), type);
for (Map.Entry<BiomeAPI.BiomeType, BiomePicker> pickerEntry : acceptedBiomeTypes.entrySet()) {
if (type.is(pickerEntry.getKey())) {
BCLBiome bclBiome;
if (foundBCLBiome) {
bclBiome = BCLBiomeRegistry.getBiome(biomeEntry.getKey(), bclBiomes);
} else {
//create and register a biome wrapper
bclBiome = new BCLBiome(biomeEntry.getKey().location(), type);
BCLBiomeRegistry.register(bclBiome);
foundBCLBiome = true;
}
boolean isPossible;
if (!bclBiome.hasParentBiome()) {
isPossible = pickerAdder.add(bclBiome, pickerEntry.getKey(), pickerEntry.getValue());
} else {
isPossible = true;
}
if (isPossible) {
allBiomes.add(biomes.getHolderOrThrow(biomeEntry.getKey()));
}
}
}
}
return allBiomes;
}
protected abstract BiomeAPI.BiomeType defaultBiomeType();
protected abstract Map<BiomeAPI.BiomeType, BiomePicker> createFreshPickerMap();
public abstract String toShortString();
protected void onFinishBiomeRebuild(Map<BiomeAPI.BiomeType, BiomePicker> pickerMap) {
for (var picker : pickerMap.values()) {
picker.rebuild();
}
}
protected final void rebuildBiomes(boolean force) {
if (!force && didCreatePickers) return;
if (Configs.MAIN_CONFIG.verboseLogging()) {
BCLib.LOGGER.info("Updating Pickers for " + this.toShortString());
}
Map<BiomeAPI.BiomeType, BiomePicker> pickerMap = createFreshPickerMap();
this.dynamicPossibleBiomes = populateBiomePickers(
pickerMap,
defaultBiomeType(),
this::addToPicker,
this::typeForUnknownBiome
);
if (this.dynamicPossibleBiomes == null) {
this.dynamicPossibleBiomes = Set.of();
} else {
this.didCreatePickers = true;
}
onFinishBiomeRebuild(pickerMap);
}
@Override
public BCLBiomeSource mergeWithBiomeSource(BiomeSource inputBiomeSource) {
final RegistryAccess access = WorldBootstrap.getLastRegistryAccess();
if (access == null) {
BCLib.LOGGER.error("Unable to merge Biomesources!");
return this;
}
final Map<BiomeAPI.BiomeType, List<String>> includeMap = Configs.BIOMES_CONFIG.getBiomeIncludeMap();
final List<String> excludeList = Configs.BIOMES_CONFIG.getExcludeMatching(defaultBiomeType());
final Registry<BCLBiome> bclBiomes = access.registryOrThrow(BCLBiomeRegistry.BCL_BIOMES_REGISTRY);
try {
for (Holder<Biome> possibleBiome : inputBiomeSource.possibleBiomes()) {
ResourceKey<Biome> key = possibleBiome.unwrapKey().orElse(null);
if (key != null) {
//skip over all biomes that were excluded in the config
if (excludeList.contains(key.location())) continue;
//this is a biome that has no type entry => create a new one for the default type of this registry
if (!BCLBiomeRegistry.hasBiome(key, bclBiomes)) {
BiomeAPI.BiomeType type = typeForUnknownBiome(key, defaultBiomeType());
//check if there was an override defined in the configs
type = getBiomeType(includeMap, key, type);
//create and register a biome wrapper
BCLBiome bclBiome = new BCLBiome(key.location(), type);
BCLBiomeRegistry.register(bclBiome);
}
}
}
} catch (RuntimeException e) {
BCLib.LOGGER.error("Error while rebuilding Biomesources!", e);
} catch (Exception e) {
BCLib.LOGGER.error("Error while rebuilding Biomesources!", e);
}
this.reloadBiomes();
return this;
}
private static BiomeAPI.BiomeType getBiomeType(
Map<BiomeAPI.BiomeType, List<String>> includeMap,
ResourceKey<Biome> biomeKey,
BiomeAPI.BiomeType defaultType
) {
for (Map.Entry<BiomeAPI.BiomeType, List<String>> includeList : includeMap.entrySet()) {
if (includeList.getValue().contains(biomeKey.location().toString())) {
return includeList.getKey();
}
}
return defaultType;
}
public void onLoadGeneratorSettings(NoiseGeneratorSettings generator) {
this.setMaxHeight(generator.noiseSettings().height());
}
protected void reloadBiomes(boolean force) {
rebuildBiomes(force);
this.initMap(currentSeed);
}
@Override
public void reloadBiomes() {
reloadBiomes(true);
}
}

View file

@ -1,330 +0,0 @@
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.BiomeAPI;
import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.levelgen.DensityFunction;
import java.awt.*;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.NotNull;
public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig<BCLibEndBiomeSource, BCLEndBiomeSourceConfig> {
public static Codec<BCLibEndBiomeSource> CODEC
= RecordCodecBuilder.create((instance) -> instance
.group(
Codec
.LONG
.fieldOf("seed")
.stable()
.forGetter(source -> source.currentSeed),
BCLEndBiomeSourceConfig
.CODEC
.fieldOf("config")
.orElse(BCLEndBiomeSourceConfig.DEFAULT)
.forGetter(o -> o.config)
)
.apply(
instance,
instance.stable(BCLibEndBiomeSource::new)
)
);
private final Point pos;
private BiomeMap mapLand;
private BiomeMap mapVoid;
private BiomeMap mapCenter;
private BiomeMap mapBarrens;
private BiomePicker endLandBiomePicker;
private BiomePicker endVoidBiomePicker;
private BiomePicker endCenterBiomePicker;
private BiomePicker endBarrensBiomePicker;
private List<BiomeDecider> deciders;
private BCLEndBiomeSourceConfig config;
private BCLibEndBiomeSource(
long seed,
BCLEndBiomeSourceConfig config
) {
this(seed, config, true);
}
public BCLibEndBiomeSource(
BCLEndBiomeSourceConfig config
) {
this(0, config, false);
}
private BCLibEndBiomeSource(
long seed,
BCLEndBiomeSourceConfig config,
boolean initMaps
) {
super(seed);
this.config = config;
rebuildBiomes(false);
this.pos = new Point();
if (initMaps) {
initMap(seed);
}
}
@Override
protected BiomeAPI.BiomeType defaultBiomeType() {
return BiomeAPI.BiomeType.END_LAND;
}
@Override
protected Map<BiomeAPI.BiomeType, BiomePicker> createFreshPickerMap() {
this.deciders = BiomeDecider.DECIDERS.stream()
.filter(d -> d.canProvideFor(this))
.map(d -> d.createInstance(this))
.toList();
this.endLandBiomePicker = new BiomePicker();
this.endVoidBiomePicker = new BiomePicker();
this.endCenterBiomePicker = new BiomePicker();
this.endBarrensBiomePicker = new BiomePicker();
return Map.of(
BiomeAPI.BiomeType.END_LAND, endLandBiomePicker,
BiomeAPI.BiomeType.END_VOID, endVoidBiomePicker,
BiomeAPI.BiomeType.END_CENTER, endCenterBiomePicker,
BiomeAPI.BiomeType.END_BARRENS, endBarrensBiomePicker
);
}
protected boolean addToPicker(BCLBiome bclBiome, BiomeAPI.BiomeType type, BiomePicker picker) {
if (!config.withVoidBiomes) {
if (bclBiome.getID().equals(Biomes.SMALL_END_ISLANDS.location())) {
return false;
}
}
for (BiomeDecider decider : deciders) {
if (decider.addToPicker(bclBiome)) {
return true;
}
}
return super.addToPicker(bclBiome, type, picker);
}
@Override
protected BiomeAPI.BiomeType typeForUnknownBiome(ResourceKey<Biome> biomeKey, BiomeAPI.BiomeType defaultType) {
if (TheEndBiomesHelper.canGenerateAsMainIslandBiome(biomeKey)) {
return BiomeAPI.BiomeType.END_CENTER;
} else if (TheEndBiomesHelper.canGenerateAsHighlandsBiome(biomeKey)) {
if (!config.withVoidBiomes) return BiomeAPI.BiomeType.END_VOID;
return BiomeAPI.BiomeType.END_LAND;
} else if (TheEndBiomesHelper.canGenerateAsEndBarrens(biomeKey)) {
return BiomeAPI.BiomeType.END_BARRENS;
} else if (TheEndBiomesHelper.canGenerateAsSmallIslandsBiome(biomeKey)) {
return BiomeAPI.BiomeType.END_VOID;
} else if (TheEndBiomesHelper.canGenerateAsEndMidlands(biomeKey)) {
return BiomeAPI.BiomeType.END_LAND;
}
return super.typeForUnknownBiome(biomeKey, defaultType);
}
@Override
protected void onFinishBiomeRebuild(Map<BiomeAPI.BiomeType, BiomePicker> pickerMap) {
super.onFinishBiomeRebuild(pickerMap);
for (BiomeDecider decider : deciders) {
decider.rebuild();
}
if (endVoidBiomePicker.isEmpty()) {
if (Configs.MAIN_CONFIG.verboseLogging() && !BCLib.isDatagen())
BCLib.LOGGER.info("No Void Biomes found. Disabling by using barrens");
endVoidBiomePicker = endBarrensBiomePicker;
}
if (endBarrensBiomePicker.isEmpty()) {
if (Configs.MAIN_CONFIG.verboseLogging() && !BCLib.isDatagen())
BCLib.LOGGER.info("No Barrens Biomes found. Disabling by using land Biomes");
endBarrensBiomePicker = endLandBiomePicker;
endVoidBiomePicker = endLandBiomePicker;
}
if (endCenterBiomePicker.isEmpty()) {
if (Configs.MAIN_CONFIG.verboseLogging() && !BCLib.isDatagen())
BCLib.LOGGER.warning("No Center Island Biomes found. Forcing use of vanilla center.");
endCenterBiomePicker.addBiome(BiomeAPI.THE_END);
endCenterBiomePicker.rebuild();
if (endCenterBiomePicker.isEmpty()) {
if (Configs.MAIN_CONFIG.verboseLogging() && !BCLib.isDatagen())
BCLib.LOGGER.error("Unable to force vanilla central Island. Falling back to land Biomes...");
endCenterBiomePicker = endLandBiomePicker;
}
}
}
public static void register() {
Registry.register(BuiltInRegistries.BIOME_SOURCE, BCLib.makeID("end_biome_source"), CODEC);
}
@Override
protected void onInitMap(long seed) {
for (BiomeDecider decider : deciders) {
decider.createMap((picker, size) -> config.mapVersion.mapBuilder.create(
seed,
size <= 0 ? config.landBiomesSize : size,
picker
));
}
this.mapLand = config.mapVersion.mapBuilder.create(
seed,
config.landBiomesSize,
endLandBiomePicker
);
this.mapVoid = config.mapVersion.mapBuilder.create(
seed,
config.voidBiomesSize,
endVoidBiomePicker
);
this.mapCenter = config.mapVersion.mapBuilder.create(
seed,
config.centerBiomesSize,
endCenterBiomePicker
);
this.mapBarrens = config.mapVersion.mapBuilder.create(
seed,
config.barrensBiomesSize,
endBarrensBiomePicker
);
}
@Override
protected void onHeightChange(int newHeight) {
}
@Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.@NotNull Sampler sampler) {
if (!wasBound()) reloadBiomes(false);
if (mapLand == null || mapVoid == null || mapCenter == null || mapBarrens == null)
return this.possibleBiomes().stream().findFirst().orElseThrow();
int posX = QuartPos.toBlock(biomeX);
int posY = QuartPos.toBlock(biomeY);
int posZ = QuartPos.toBlock(biomeZ);
long dist = Math.abs(posX) + Math.abs(posZ) > (long) config.innerVoidRadiusSquared
? ((long) config.innerVoidRadiusSquared + 1)
: (long) posX * (long) posX + (long) posZ * (long) posZ;
if ((biomeX & 63) == 0 || (biomeZ & 63) == 0) {
mapLand.clearCache();
mapVoid.clearCache();
mapCenter.clearCache();
mapVoid.clearCache();
for (BiomeDecider decider : deciders) {
decider.clearMapCache();
}
}
BiomeAPI.BiomeType suggestedType;
int x = (SectionPos.blockToSectionCoord(posX) * 2 + 1) * 8;
int z = (SectionPos.blockToSectionCoord(posZ) * 2 + 1) * 8;
double d = sampler.erosion().compute(new DensityFunction.SinglePointContext(x, posY, z));
if (dist <= (long) config.innerVoidRadiusSquared) {
suggestedType = BiomeAPI.BiomeType.END_CENTER;
} else {
if (d > 0.25) {
suggestedType = BiomeAPI.BiomeType.END_LAND; //highlands
} else if (d >= -0.0625) {
suggestedType = BiomeAPI.BiomeType.END_LAND; //midlands
} else {
suggestedType = d < -0.21875
? BiomeAPI.BiomeType.END_VOID //small islands
: (config.withVoidBiomes
? BiomeAPI.BiomeType.END_BARRENS
: BiomeAPI.BiomeType.END_LAND); //barrens
}
}
final BiomeAPI.BiomeType originalType = suggestedType;
for (BiomeDecider decider : deciders) {
suggestedType = decider
.suggestType(originalType, suggestedType, d, maxHeight, posX, posY, posZ, biomeX, biomeY, biomeZ);
}
BiomePicker.ActualBiome result;
for (BiomeDecider decider : deciders) {
if (decider.canProvideBiome(suggestedType)) {
result = decider.provideBiome(suggestedType, posX, posY, posZ);
if (result != null) return result.biome;
}
}
if (suggestedType.is(BiomeAPI.BiomeType.END_CENTER)) return mapCenter.getBiome(posX, posY, posZ).biome;
if (suggestedType.is(BiomeAPI.BiomeType.END_VOID)) return mapVoid.getBiome(posX, posY, posZ).biome;
if (suggestedType.is(BiomeAPI.BiomeType.END_BARRENS)) return mapBarrens.getBiome(posX, posY, posZ).biome;
return mapLand.getBiome(posX, posY, posZ).biome;
}
@Override
protected Codec<? extends BiomeSource> codec() {
return CODEC;
}
@Override
public String toShortString() {
return "BCLib - The End BiomeSource (" + Integer.toHexString(hashCode()) + ")";
}
@Override
public String toString() {
return "\n" + toShortString() +
"\n biomes = " + possibleBiomes().size() +
"\n namespaces = " + getNamespaces() +
"\n seed = " + currentSeed +
"\n height = " + maxHeight +
"\n deciders = " + deciders.size() +
"\n config = " + config;
}
@Override
public BCLEndBiomeSourceConfig getTogetherConfig() {
return config;
}
@Override
public void setTogetherConfig(BCLEndBiomeSourceConfig newConfig) {
this.config = newConfig;
rebuildBiomes(true);
this.initMap(currentSeed);
}
}

View file

@ -1,170 +0,0 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.config.BCLNetherBiomeSourceConfig;
import org.betterx.bclib.api.v2.generator.config.MapBuilderFunction;
import org.betterx.bclib.api.v2.generator.map.MapStack;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import net.fabricmc.fabric.api.biome.v1.NetherBiomes;
import java.util.Map;
public class BCLibNetherBiomeSource extends BCLBiomeSource implements BiomeSourceWithConfig<BCLibNetherBiomeSource, BCLNetherBiomeSourceConfig> {
public static final Codec<BCLibNetherBiomeSource> CODEC = RecordCodecBuilder
.create(instance -> instance
.group(
Codec
.LONG
.fieldOf("seed")
.stable()
.forGetter(source -> {
return source.currentSeed;
}),
BCLNetherBiomeSourceConfig
.CODEC
.fieldOf("config")
.orElse(BCLNetherBiomeSourceConfig.DEFAULT)
.forGetter(o -> o.config)
)
.apply(instance, instance.stable(BCLibNetherBiomeSource::new))
);
private BiomeMap biomeMap;
private BiomePicker biomePicker;
private BCLNetherBiomeSourceConfig config;
public BCLibNetherBiomeSource(
BCLNetherBiomeSourceConfig config
) {
this(0, config, false);
}
private BCLibNetherBiomeSource(
long seed,
BCLNetherBiomeSourceConfig config
) {
this(seed, config, true);
}
private BCLibNetherBiomeSource(
long seed,
BCLNetherBiomeSourceConfig config,
boolean initMaps
) {
super(seed);
this.config = config;
rebuildBiomes(false);
if (initMaps) {
initMap(seed);
}
}
@Override
protected BiomeAPI.BiomeType defaultBiomeType() {
return BiomeAPI.BiomeType.NETHER;
}
@Override
protected Map<BiomeAPI.BiomeType, BiomePicker> createFreshPickerMap() {
this.biomePicker = new BiomePicker();
return Map.of(defaultBiomeType(), this.biomePicker);
}
@Override
protected BiomeAPI.BiomeType typeForUnknownBiome(ResourceKey<Biome> biomeKey, BiomeAPI.BiomeType defaultType) {
//
if (NetherBiomes.canGenerateInNether(biomeKey)) {
return BiomeAPI.BiomeType.NETHER;
}
return super.typeForUnknownBiome(biomeKey, defaultType);
}
public static void register() {
Registry.register(BuiltInRegistries.BIOME_SOURCE, BCLib.makeID("nether_biome_source"), CODEC);
}
@Override
public Holder<Biome> getNoiseBiome(int biomeX, int biomeY, int biomeZ, Climate.Sampler var4) {
if (!wasBound()) reloadBiomes(false);
if (biomeMap == null)
return this.possibleBiomes().stream().findFirst().get();
if ((biomeX & 63) == 0 && (biomeZ & 63) == 0) {
biomeMap.clearCache();
}
BiomePicker.ActualBiome bb = biomeMap.getBiome(biomeX << 2, biomeY << 2, biomeZ << 2);
return bb.biome;
}
@Override
protected Codec<? extends BiomeSource> codec() {
return CODEC;
}
@Override
protected void onInitMap(long seed) {
MapBuilderFunction mapConstructor = config.mapVersion.mapBuilder;
if (maxHeight > config.biomeSizeVertical * 1.5 && config.useVerticalBiomes) {
this.biomeMap = new MapStack(
seed,
config.biomeSize,
biomePicker,
config.biomeSizeVertical,
maxHeight,
mapConstructor
);
} else {
this.biomeMap = mapConstructor.create(
seed,
config.biomeSize,
biomePicker
);
}
}
@Override
protected void onHeightChange(int newHeight) {
initMap(currentSeed);
}
@Override
public String toShortString() {
return "BCLib - Nether BiomeSource (" + Integer.toHexString(hashCode()) + ")";
}
@Override
public String toString() {
return "\n" + toShortString() +
"\n biomes = " + possibleBiomes().size() +
"\n namespaces = " + getNamespaces() +
"\n seed = " + currentSeed +
"\n height = " + maxHeight +
"\n config = " + config;
}
@Override
public BCLNetherBiomeSourceConfig getTogetherConfig() {
return config;
}
@Override
public void setTogetherConfig(BCLNetherBiomeSourceConfig newConfig) {
this.config = newConfig;
initMap(currentSeed);
}
}

View file

@ -1,266 +0,0 @@
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.interfaces.BiomeMap;
import net.minecraft.core.HolderGetter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import java.util.LinkedList;
import java.util.List;
/**
* Used to extend the BiomePlacement in the {@link BCLBiomeSource}
*/
public abstract class BiomeDecider {
/**
* used to create new {@link BiomeMap} instances
*/
@FunctionalInterface
public interface BiomeMapBuilderFunction {
/**
* Constructs a new {@link BiomeMap}
*
* @param picker The picker the BiomeMap should use
* @param biomeSize The biomeSize the map will use or -1 for the default size
* @return a new {@link BiomeMap} instance
*/
BiomeMap create(BiomePicker picker, int biomeSize);
}
/**
* used to determine wether or not a decider can provide this biome
*/
@FunctionalInterface
public interface BiomePredicate {
boolean test(BCLBiome biome);
}
protected BiomePicker picker;
protected BiomeMap map;
private final BiomePredicate predicate;
static List<BiomeDecider> DECIDERS = new LinkedList<>();
/**
* Register a high priority Decider for the {@link BCLibEndBiomeSource}.
* Normally you should not need to register a high priority decider and instead use
* {@link BiomeDecider#registerDecider(ResourceLocation, BiomeDecider)}.
* BetterEnd (for example) will add
*
* @param location The {@link ResourceLocation} for the decider
* @param decider The initial decider Instance. Each Instance of the {@link BCLibEndBiomeSource}
* will call {@link BiomeDecider#createInstance(BCLBiomeSource)} to build a
* new instance of this decider
*/
public static void registerHighPriorityDecider(ResourceLocation location, BiomeDecider decider) {
if (DECIDERS.size() == 0) DECIDERS.add(decider);
else DECIDERS.add(0, decider);
}
/**
* Register a new Decider for the {@link BCLibEndBiomeSource}
*
* @param location The {@link ResourceLocation} for the decider
* @param decider The initial decider Instance. Each Instance of the {@link BCLibEndBiomeSource}
* will call {@link BiomeDecider#createInstance(BCLBiomeSource)} to build a
* new instance of this decider
*/
public static void registerDecider(ResourceLocation location, BiomeDecider decider) {
DECIDERS.add(decider);
}
protected BiomeDecider(BiomePredicate predicate) {
this(null, predicate);
}
/**
* @param biomeRegistry The biome registry assigned to the creating BiomeSource
* @param predicate A predicate that decides if a given Biome can be provided by this decider
*/
protected BiomeDecider(
HolderGetter<Biome> biomeRegistry, BiomePredicate predicate
) {
this.predicate = predicate;
this.map = null;
if (biomeRegistry == null) {
this.picker = null;
} else {
this.picker = new BiomePicker(biomeRegistry);
}
}
/**
* Called to test, if a decider is suitable for the given BiomeSource.
*
* @param source The BiomeSource that wants to use the decider
* @return true, if this decider is usable by that source
*/
public abstract boolean canProvideFor(BiomeSource source);
/**
* Called from the BiomeSource whenever it needs to create a new instance of this decider.
* <p>
* Inheriting classes should overwrite this method and return Instances of the class. For
* the base {@link BiomeDecider} you would return <em>new BiomeDecider(biomeSource.biomeRegistry, this.predicate);</em>
*
* @param biomeSource The biome source this decider is used from
* @return A new instance
*/
public abstract BiomeDecider createInstance(BCLBiomeSource biomeSource);
/**
* Called when the BiomeSources needs to construct a new {@link BiomeMap} for the picker.
* <p>
* The default implementation creates a new map with the instances picker and a default biome size
*
* @param mapBuilder A function you can use to create a new {@link BiomeMap} that conforms to the settings
* of the current BiomeSource.
*/
public void createMap(BiomeMapBuilderFunction mapBuilder) {
this.map = mapBuilder.create(picker, -1);
}
/**
* called whenever the BiomeSource needs to clear caches
*/
public void clearMapCache() {
map.clearCache();
}
/**
* This method get's called whenever the BiomeSource populates the Biome Pickers. You need to
* determine if the passed Biome is valid for your picker.
* <p>
* If this method returns false, the Biome wil not get added to any other Deciders/Pickers.
* <p>
* The default implementation will use the instances {@link BiomeDecider#predicate} to determine if
* a biome should get added and return true if it was added.
*
* @param biome The biome that should get added if it matches the criteria of the picker
* @return false, if other pickers/deciders are allowed to use the biome as well
*/
public boolean addToPicker(BCLBiome biome) {
if (predicate.test(biome)) {
picker.addBiome(biome);
return true;
}
return false;
}
/**
* Called whenever the picker needs to rebuild it's contents
*/
public void rebuild() {
//TODO: 1.19.3 test if this rebuilds once we have biomes
if (picker != null)
picker.rebuild();
}
/**
* Called from the BiomeSource to determine the type of Biome it needs to place.
*
* @param originalType The original biome type the source did select
* @param suggestedType The currently suggested type. This will differ from <em>originalType</em> if other
* {@link BiomeDecider} instances already had a new suggestion. You implementation should return the
* <em>suggestedType</em> if it does not want to provide the Biome for this location
* @param maxHeight The maximum terrain height for this world
* @param blockX The block coordinate where we are at
* @param blockY The block coordinate where we are at
* @param blockZ The block coordinate where we are at
* @param quarterX The quarter Block Coordinate (which is blockX/4)
* @param quarterY The quarter Block Coordinate (which is blockY/4)
* @param quarterZ The quarter Block Coordinate (which is blockZ/4)
* @return The <em>suggestedType</em> if this decider does not plan to provide a Biome, or a unique BiomeType.
* The Biome Source will call {@link BiomeDecider#canProvideBiome(BiomeAPI.BiomeType)} with the finally chosen type
* for all available Deciders.
*/
public BiomeAPI.BiomeType suggestType(
BiomeAPI.BiomeType originalType,
BiomeAPI.BiomeType suggestedType,
int maxHeight,
int blockX,
int blockY,
int blockZ,
int quarterX,
int quarterY,
int quarterZ
) {
return suggestType(
originalType,
suggestedType,
0,
maxHeight,
blockX,
blockY,
blockZ,
quarterX,
quarterY,
quarterZ
);
}
/**
* Called from the BiomeSource to determine the type of Biome it needs to place.
*
* @param originalType The original biome type the source did select
* @param suggestedType The currently suggested type. This will differ from <em>originalType</em> if other
* {@link BiomeDecider} instances already had a new suggestion. You implementation should return the
* <em>suggestedType</em> if it does not want to provide the Biome for this location
* @param density The terrain density at this location. Currently only valid if for {@link BCLibEndBiomeSource}
* that use the {@link org.betterx.bclib.api.v2.generator.config.BCLEndBiomeSourceConfig.EndBiomeGeneratorType#VANILLA}
* @param maxHeight The maximum terrain height for this world
* @param blockX The block coordinate where we are at
* @param blockY The block coordinate where we are at
* @param blockZ The block coordinate where we are at
* @param quarterX The quarter Block Coordinate (which is blockX/4)
* @param quarterY The quarter Block Coordinate (which is blockY/4)
* @param quarterZ The quarter Block Coordinate (which is blockZ/4)
* @param maxHeight
* @return The <em>suggestedType</em> if this decider does not plan to provide a Biome, or a unique BiomeType.
* The Biome Source will call {@link BiomeDecider#canProvideBiome(BiomeAPI.BiomeType)} with the finally chosen type
* for all available Deciders.
*/
public abstract BiomeAPI.BiomeType suggestType(
BiomeAPI.BiomeType originalType,
BiomeAPI.BiomeType suggestedType,
double density,
int maxHeight,
int blockX,
int blockY,
int blockZ,
int quarterX,
int quarterY,
int quarterZ
);
/**
* Called to check if this decider can place a biome for the specified type
*
* @param suggestedType The type of biome we need to place
* @return true, if this type of biome can be provided by the current picker. If true
* is returned, the BiomeSource will call {@link BiomeDecider#provideBiome(BiomeAPI.BiomeType, int, int, int)}
* next
*/
public abstract boolean canProvideBiome(BiomeAPI.BiomeType suggestedType);
/**
* Called to check if this decider can place a biome for the specified type
* <p>
* The default implementation will return <em>map.getBiome(posX, posY, posZ)</em>
*
* @param suggestedType The type of biome we need to place
* @return The methode should return a Biome from its {@link BiomeMap}. If null is returned, the next
* decider (or the default map) will provide the biome
*/
public BiomePicker.ActualBiome provideBiome(BiomeAPI.BiomeType suggestedType, int posX, int posY, int posZ) {
return map.getBiome(posX, posY, posZ);
}
}

View file

@ -1,5 +0,0 @@
package org.betterx.bclib.api.v2.generator;
public enum BiomeType {
LAND, VOID
}

View file

@ -1,22 +0,0 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.config.Configs;
public class GeneratorOptions {
//private static BiFunction<Point, Integer, Boolean> endLandFunction;
private static boolean fixEndBiomeSource = true;
private static boolean fixNetherBiomeSource = true;
public static void init() {
fixEndBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixEndBiomeSource", true);
fixNetherBiomeSource = Configs.GENERATOR_CONFIG.getBoolean("options.biomeSource", "fixNetherBiomeSource", true);
}
public static boolean fixEndBiomeSource() {
return fixEndBiomeSource;
}
public static boolean fixNetherBiomeSource() {
return fixNetherBiomeSource;
}
}

View file

@ -1,92 +0,0 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.jetbrains.annotations.ApiStatus;
/**
* Helper class until FAPI integrates <a href="https://github.com/FabricMC/fabric/pull/2369">this PR</a>
*/
public class TheEndBiomesHelper {
@ApiStatus.Internal
private static Map<BiomeAPI.BiomeType, Set<ResourceKey<Biome>>> END_BIOMES = new HashMap<>();
@ApiStatus.Internal
public static void add(BiomeAPI.BiomeType type, ResourceKey<Biome> biome) {
if (biome == null) return;
END_BIOMES.computeIfAbsent(type, t -> new HashSet<>()).add(biome);
}
private static boolean has(BiomeAPI.BiomeType type, ResourceKey<Biome> biome) {
if (biome == null) return false;
Set<ResourceKey<Biome>> set = END_BIOMES.get(type);
if (set == null) return false;
return set.contains(biome);
}
/**
* Returns true if the given biome was added as a main end Biome in the end, considering the Vanilla end biomes,
* and any biomes added to the End by mods.
*
* @param biome The biome to search for
*/
public static boolean canGenerateAsMainIslandBiome(ResourceKey<Biome> biome) {
return has(BiomeAPI.BiomeType.END_CENTER, biome);
}
/**
* Returns true if the given biome was added as a small end islands Biome in the end, considering the Vanilla end biomes,
* and any biomes added to the End by mods.
*
* @param biome The biome to search for
*/
public static boolean canGenerateAsSmallIslandsBiome(ResourceKey<Biome> biome) {
return has(BiomeAPI.BiomeType.END_VOID, biome);
}
/**
* Returns true if the given biome was added as a Highland Biome in the end, considering the Vanilla end biomes,
* and any biomes added to the End by mods.
*
* @param biome The biome to search for
*/
public static boolean canGenerateAsHighlandsBiome(ResourceKey<Biome> biome) {
return has(BiomeAPI.BiomeType.END_LAND, biome);
}
/**
* Returns true if the given biome was added as midland biome in the end, considering the Vanilla end biomes,
* and any biomes added to the End as midland biome by mods.
*
* @param biome The biome to search for
*/
public static boolean canGenerateAsEndMidlands(ResourceKey<Biome> biome) {
return false;
}
/**
* Returns true if the given biome was added as barrens biome in the end, considering the Vanilla end biomes,
* and any biomes added to the End as barrens biome by mods.
*
* @param biome The biome to search for
*/
public static boolean canGenerateAsEndBarrens(ResourceKey<Biome> biome) {
return has(BiomeAPI.BiomeType.END_BARRENS, biome);
}
public static boolean canGenerateInEnd(ResourceKey<Biome> biome) {
return canGenerateAsHighlandsBiome(biome)
|| canGenerateAsEndBarrens(biome)
|| canGenerateAsEndMidlands(biome)
|| canGenerateAsSmallIslandsBiome(biome)
|| canGenerateAsMainIslandBiome(biome);
}
}

View file

@ -1,24 +0,0 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import net.minecraft.core.HolderGetter;
import net.minecraft.world.level.biome.Biome;
public abstract class TypeBiomeDecider extends BiomeDecider {
protected final BiomeAPI.BiomeType assignedType;
public TypeBiomeDecider(BiomeAPI.BiomeType assignedType) {
this(null, assignedType);
}
protected TypeBiomeDecider(HolderGetter<Biome> biomeRegistry, BiomeAPI.BiomeType assignedType) {
super(biomeRegistry, (biome) -> biome.getIntendedType().is(assignedType));
this.assignedType = assignedType;
}
@Override
public boolean canProvideBiome(BiomeAPI.BiomeType suggestedType) {
return suggestedType.equals(assignedType);
}
}

View file

@ -1,268 +0,0 @@
package org.betterx.bclib.api.v2.generator.config;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.worlds.together.biomesource.config.BiomeSourceConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Mth;
import net.minecraft.util.StringRepresentable;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
public class BCLEndBiomeSourceConfig implements BiomeSourceConfig<BCLibEndBiomeSource> {
public static final BCLEndBiomeSourceConfig VANILLA = new BCLEndBiomeSourceConfig(
EndBiomeMapType.VANILLA,
EndBiomeGeneratorType.VANILLA,
true,
4096,
128,
128,
128,
128
);
public static final BCLEndBiomeSourceConfig MINECRAFT_17 = new BCLEndBiomeSourceConfig(
EndBiomeMapType.SQUARE,
EndBiomeGeneratorType.PAULEVS,
true,
VANILLA.innerVoidRadiusSquared * 16 * 16,
256,
256,
256,
256
);
public static final BCLEndBiomeSourceConfig MINECRAFT_18 = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
BCLib.RUNS_NULLSCAPE ? EndBiomeGeneratorType.VANILLA : EndBiomeGeneratorType.PAULEVS,
BCLib.RUNS_NULLSCAPE ? false : true,
MINECRAFT_17.innerVoidRadiusSquared,
MINECRAFT_17.centerBiomesSize,
MINECRAFT_17.voidBiomesSize,
MINECRAFT_17.landBiomesSize,
MINECRAFT_17.barrensBiomesSize
);
public static final BCLEndBiomeSourceConfig MINECRAFT_18_LARGE = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
BCLib.RUNS_NULLSCAPE ? EndBiomeGeneratorType.VANILLA : EndBiomeGeneratorType.PAULEVS,
BCLib.RUNS_NULLSCAPE ? false : true,
MINECRAFT_18.innerVoidRadiusSquared,
MINECRAFT_18.centerBiomesSize,
MINECRAFT_18.voidBiomesSize * 2,
MINECRAFT_18.landBiomesSize * 4,
MINECRAFT_18.barrensBiomesSize * 2
);
public static final BCLEndBiomeSourceConfig MINECRAFT_18_AMPLIFIED = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
EndBiomeGeneratorType.PAULEVS,
true,
MINECRAFT_18.innerVoidRadiusSquared,
MINECRAFT_18.centerBiomesSize,
MINECRAFT_18.voidBiomesSize,
MINECRAFT_18.landBiomesSize,
MINECRAFT_18.barrensBiomesSize
);
public static final BCLEndBiomeSourceConfig MINECRAFT_20 = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
EndBiomeGeneratorType.VANILLA,
BCLib.RUNS_NULLSCAPE ? false : true,
MINECRAFT_17.innerVoidRadiusSquared,
MINECRAFT_17.centerBiomesSize,
MINECRAFT_17.voidBiomesSize,
MINECRAFT_17.landBiomesSize,
MINECRAFT_17.barrensBiomesSize
);
public static final BCLEndBiomeSourceConfig MINECRAFT_20_LARGE = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
EndBiomeGeneratorType.VANILLA,
BCLib.RUNS_NULLSCAPE ? false : true,
MINECRAFT_18.innerVoidRadiusSquared,
MINECRAFT_18.centerBiomesSize,
MINECRAFT_18.voidBiomesSize * 2,
MINECRAFT_18.landBiomesSize * 4,
MINECRAFT_18.barrensBiomesSize * 2
);
public static final BCLEndBiomeSourceConfig MINECRAFT_20_AMPLIFIED = new BCLEndBiomeSourceConfig(
EndBiomeMapType.HEX,
EndBiomeGeneratorType.VANILLA,
true,
MINECRAFT_18.innerVoidRadiusSquared,
MINECRAFT_18.centerBiomesSize,
MINECRAFT_18.voidBiomesSize,
MINECRAFT_18.landBiomesSize,
MINECRAFT_18.barrensBiomesSize
);
public static final BCLEndBiomeSourceConfig DEFAULT = MINECRAFT_20;
public static final Codec<BCLEndBiomeSourceConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
EndBiomeMapType.CODEC
.fieldOf("map_type")
.orElse(DEFAULT.mapVersion)
.forGetter(o -> o.mapVersion),
EndBiomeGeneratorType.CODEC
.fieldOf("generator_version")
.orElse(DEFAULT.generatorVersion)
.forGetter(o -> o.generatorVersion),
Codec.BOOL
.fieldOf("with_void_biomes")
.orElse(DEFAULT.withVoidBiomes)
.forGetter(o -> o.withVoidBiomes),
Codec.INT
.fieldOf("inner_void_radius_squared")
.orElse(DEFAULT.innerVoidRadiusSquared)
.forGetter(o -> o.innerVoidRadiusSquared),
Codec.INT
.fieldOf("center_biomes_size")
.orElse(DEFAULT.centerBiomesSize)
.forGetter(o -> o.centerBiomesSize),
Codec.INT
.fieldOf("void_biomes_size")
.orElse(DEFAULT.voidBiomesSize)
.forGetter(o -> o.voidBiomesSize),
Codec.INT
.fieldOf("land_biomes_size")
.orElse(DEFAULT.landBiomesSize)
.forGetter(o -> o.landBiomesSize),
Codec.INT
.fieldOf("barrens_biomes_size")
.orElse(DEFAULT.barrensBiomesSize)
.forGetter(o -> o.barrensBiomesSize)
)
.apply(instance, BCLEndBiomeSourceConfig::new));
public BCLEndBiomeSourceConfig(
@NotNull EndBiomeMapType mapVersion,
@NotNull EndBiomeGeneratorType generatorVersion,
boolean withVoidBiomes,
int innerVoidRadiusSquared,
int centerBiomesSize,
int voidBiomesSize,
int landBiomesSize,
int barrensBiomesSize
) {
this.mapVersion = mapVersion;
this.generatorVersion = generatorVersion;
this.withVoidBiomes = withVoidBiomes;
this.innerVoidRadiusSquared = innerVoidRadiusSquared;
this.barrensBiomesSize = Mth.clamp(barrensBiomesSize, 1, 8192);
this.voidBiomesSize = Mth.clamp(voidBiomesSize, 1, 8192);
this.centerBiomesSize = Mth.clamp(centerBiomesSize, 1, 8192);
this.landBiomesSize = Mth.clamp(landBiomesSize, 1, 8192);
}
public enum EndBiomeMapType implements StringRepresentable {
VANILLA("vanilla", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker)),
SQUARE("square", (seed, biomeSize, picker) -> new SquareBiomeMap(seed, biomeSize, picker)),
HEX("hex", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker));
public static final Codec<EndBiomeMapType> CODEC = StringRepresentable.fromEnum(EndBiomeMapType::values);
public final String name;
public final @NotNull MapBuilderFunction mapBuilder;
EndBiomeMapType(String name, @NotNull MapBuilderFunction mapBuilder) {
this.name = name;
this.mapBuilder = mapBuilder;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public enum EndBiomeGeneratorType implements StringRepresentable {
VANILLA("vanilla"),
PAULEVS("paulevs");
public static final Codec<EndBiomeGeneratorType> CODEC = StringRepresentable.fromEnum(EndBiomeGeneratorType::values);
public final String name;
EndBiomeGeneratorType(String name) {
this.name = name;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
public final @NotNull EndBiomeMapType mapVersion;
public final @NotNull EndBiomeGeneratorType generatorVersion;
public final boolean withVoidBiomes;
public final int innerVoidRadiusSquared;
public final int voidBiomesSize;
public final int centerBiomesSize;
public final int landBiomesSize;
public final int barrensBiomesSize;
@Override
public String toString() {
return "BCLEndBiomeSourceConfig{" +
"mapVersion=" + mapVersion +
", generatorVersion=" + generatorVersion +
", withVoidBiomes=" + withVoidBiomes +
", innerVoidRadiusSquared=" + innerVoidRadiusSquared +
", voidBiomesSize=" + voidBiomesSize +
", centerBiomesSize=" + centerBiomesSize +
", landBiomesSize=" + landBiomesSize +
", barrensBiomesSize=" + barrensBiomesSize +
'}';
}
@Override
public boolean couldSetWithoutRepair(BiomeSourceConfig<?> input) {
if (input instanceof BCLEndBiomeSourceConfig cfg) {
return withVoidBiomes == cfg.withVoidBiomes && mapVersion == cfg.mapVersion && generatorVersion == cfg.generatorVersion;
}
return false;
}
@Override
public boolean sameConfig(BiomeSourceConfig<?> input) {
return this.equals(input);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
BCLEndBiomeSourceConfig that = (BCLEndBiomeSourceConfig) o;
return withVoidBiomes == that.withVoidBiomes && innerVoidRadiusSquared == that.innerVoidRadiusSquared && voidBiomesSize == that.voidBiomesSize && centerBiomesSize == that.centerBiomesSize && landBiomesSize == that.landBiomesSize && barrensBiomesSize == that.barrensBiomesSize && mapVersion == that.mapVersion && generatorVersion == that.generatorVersion;
}
@Override
public int hashCode() {
return Objects.hash(
mapVersion,
generatorVersion,
withVoidBiomes,
innerVoidRadiusSquared,
voidBiomesSize,
centerBiomesSize,
landBiomesSize,
barrensBiomesSize
);
}
}

View file

@ -1,157 +0,0 @@
package org.betterx.bclib.api.v2.generator.config;
import org.betterx.bclib.api.v2.generator.BCLibNetherBiomeSource;
import org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap;
import org.betterx.bclib.api.v2.generator.map.square.SquareBiomeMap;
import org.betterx.worlds.together.biomesource.config.BiomeSourceConfig;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.util.Mth;
import net.minecraft.util.StringRepresentable;
import java.util.Objects;
import org.jetbrains.annotations.NotNull;
public class BCLNetherBiomeSourceConfig implements BiomeSourceConfig<BCLibNetherBiomeSource> {
public static final BCLNetherBiomeSourceConfig VANILLA = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.VANILLA,
256,
86,
false,
false
);
public static final BCLNetherBiomeSourceConfig MINECRAFT_17 = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.SQUARE,
256,
86,
true,
false
);
public static final BCLNetherBiomeSourceConfig MINECRAFT_18 = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.HEX,
MINECRAFT_17.biomeSize,
MINECRAFT_17.biomeSizeVertical,
MINECRAFT_17.useVerticalBiomes,
MINECRAFT_17.amplified
);
public static final BCLNetherBiomeSourceConfig MINECRAFT_18_LARGE = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.HEX,
MINECRAFT_18.biomeSize * 4,
MINECRAFT_18.biomeSizeVertical * 2,
MINECRAFT_18.useVerticalBiomes,
MINECRAFT_17.amplified
);
public static final BCLNetherBiomeSourceConfig MINECRAFT_18_AMPLIFIED = new BCLNetherBiomeSourceConfig(
NetherBiomeMapType.HEX,
MINECRAFT_18.biomeSize,
128,
true,
true
);
public static final BCLNetherBiomeSourceConfig DEFAULT = MINECRAFT_18;
public static final Codec<BCLNetherBiomeSourceConfig> CODEC = RecordCodecBuilder.create(instance -> instance
.group(
BCLNetherBiomeSourceConfig.NetherBiomeMapType.CODEC
.fieldOf("map_type")
.orElse(DEFAULT.mapVersion)
.forGetter(o -> o.mapVersion),
Codec.INT.fieldOf("biome_size").orElse(DEFAULT.biomeSize).forGetter(o -> o.biomeSize),
Codec.INT.fieldOf("biome_size_vertical")
.orElse(DEFAULT.biomeSizeVertical)
.forGetter(o -> o.biomeSizeVertical),
Codec.BOOL.fieldOf("use_vertical_biomes")
.orElse(DEFAULT.useVerticalBiomes)
.forGetter(o -> o.useVerticalBiomes),
Codec.BOOL.fieldOf("amplified")
.orElse(DEFAULT.amplified)
.forGetter(o -> o.amplified)
)
.apply(instance, BCLNetherBiomeSourceConfig::new));
public final @NotNull NetherBiomeMapType mapVersion;
public final int biomeSize;
public final int biomeSizeVertical;
public final boolean useVerticalBiomes;
public final boolean amplified;
public BCLNetherBiomeSourceConfig(
@NotNull NetherBiomeMapType mapVersion,
int biomeSize,
int biomeSizeVertical,
boolean useVerticalBiomes,
boolean amplified
) {
this.mapVersion = mapVersion;
this.biomeSize = Mth.clamp(biomeSize, 1, 8192);
this.biomeSizeVertical = Mth.clamp(biomeSizeVertical, 1, 8192);
this.useVerticalBiomes = useVerticalBiomes;
this.amplified = amplified;
}
@Override
public String toString() {
return "BCLibNetherBiomeSourceConfig{" +
"mapVersion=" + mapVersion +
", useVerticalBiomes=" + useVerticalBiomes +
", amplified=" + amplified +
", biomeSize=" + biomeSize +
", biomeSizeVertical=" + biomeSizeVertical +
'}';
}
@Override
public boolean couldSetWithoutRepair(BiomeSourceConfig<?> input) {
if (input instanceof BCLNetherBiomeSourceConfig cfg) {
return mapVersion == cfg.mapVersion;
}
return false;
}
@Override
public boolean sameConfig(BiomeSourceConfig<?> input) {
return this.equals(input);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof BCLNetherBiomeSourceConfig)) return false;
BCLNetherBiomeSourceConfig that = (BCLNetherBiomeSourceConfig) o;
return mapVersion == that.mapVersion;
}
@Override
public int hashCode() {
return Objects.hash(mapVersion);
}
public enum NetherBiomeMapType implements StringRepresentable {
VANILLA("vanilla", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker)),
SQUARE("square", (seed, biomeSize, picker) -> new SquareBiomeMap(seed, biomeSize, picker)),
HEX("hex", (seed, biomeSize, picker) -> new HexBiomeMap(seed, biomeSize, picker));
public static final Codec<NetherBiomeMapType> CODEC = StringRepresentable.fromEnum(NetherBiomeMapType::values);
public final String name;
public final MapBuilderFunction mapBuilder;
NetherBiomeMapType(String name, MapBuilderFunction mapBuilder) {
this.name = name;
this.mapBuilder = mapBuilder;
}
@Override
public String getSerializedName() {
return name;
}
@Override
public String toString() {
return name;
}
}
}

View file

@ -1,9 +0,0 @@
package org.betterx.bclib.api.v2.generator.config;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.interfaces.BiomeMap;
@FunctionalInterface
public interface MapBuilderFunction {
BiomeMap create(long seed, int biomeSize, BiomePicker picker);
}

View file

@ -1,116 +0,0 @@
package org.betterx.bclib.api.v2.generator.map;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.api.v2.generator.config.MapBuilderFunction;
import org.betterx.bclib.interfaces.BiomeChunk;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TriConsumer;
import org.betterx.bclib.noise.OpenSimplexNoise;
import net.minecraft.util.Mth;
import java.util.Random;
public class MapStack implements BiomeMap {
private final OpenSimplexNoise noise;
private final BiomeMap[] maps;
private final double layerDistortion;
private final int worldHeight;
private final int minValue;
private final int maxValue;
private final int maxIndex;
public MapStack(
long seed,
int size,
BiomePicker picker,
int mapHeight,
int worldHeight,
MapBuilderFunction mapConstructor
) {
final int mapCount = Mth.ceil((float) worldHeight / mapHeight);
this.maxIndex = mapCount - 1;
this.worldHeight = worldHeight;
this.layerDistortion = mapHeight * 0.1;
minValue = Mth.floor(mapHeight * 0.5F + 0.5F);
maxValue = Mth.floor(worldHeight - mapHeight * 0.5F + 0.5F);
maps = new BiomeMap[mapCount];
Random random = new Random(seed);
for (int i = 0; i < mapCount; i++) {
maps[i] = mapConstructor.create(random.nextLong(), size, picker);
maps[i].setChunkProcessor(this::onChunkCreation);
}
noise = new OpenSimplexNoise(random.nextInt());
}
@Override
public void clearCache() {
for (BiomeMap map : maps) {
map.clearCache();
}
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
}
@Override
public BiomeChunk getChunk(int cx, int cz, boolean update) {
return null;
}
@Override
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
int mapIndex;
if (y < minValue) {
mapIndex = 0;
} else if (y > maxValue) {
mapIndex = maxIndex;
} else {
mapIndex = Mth.floor((y + noise.eval(
x * 0.03,
z * 0.03
) * layerDistortion) / worldHeight * maxIndex + 0.5F);
mapIndex = Mth.clamp(mapIndex, 0, maxIndex);
}
return maps[mapIndex].getBiome(x, y, z);
}
private void onChunkCreation(int cx, int cz, int side) {
BiomePicker.ActualBiome[][] biomeMap = new BiomePicker.ActualBiome[side][side];
BiomeChunk[] chunks = new BiomeChunk[maps.length];
boolean isNoEmpty = false;
for (int i = 0; i < maps.length; i++) {
chunks[i] = maps[i].getChunk(cx, cz, false);
for (int x = 0; x < side; x++) {
for (int z = 0; z < side; z++) {
if (biomeMap[x][z] == null) {
BiomePicker.ActualBiome biome = chunks[i].getBiome(x, z);
if (biome == null) {
biome = chunks[i].getBiome(x, z);
}
if (biome.bclBiome.settings.isVertical()) {
biomeMap[x][z] = biome;
isNoEmpty = true;
}
}
}
}
}
if (isNoEmpty) {
for (int i = 0; i < maps.length; i++) {
for (int x = 0; x < side; x++) {
for (int z = 0; z < side; z++) {
if (biomeMap[x][z] != null) {
chunks[i].setBiome(x, z, biomeMap[x][z]);
}
}
}
}
}
}
}

View file

@ -1,171 +0,0 @@
package org.betterx.bclib.api.v2.generator.map.hex;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.interfaces.BiomeChunk;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import java.util.Arrays;
public class HexBiomeChunk implements BiomeChunk {
private static final short SIDE = 32;
private static final byte SIDE_PRE = 4;
private static final short SIZE = SIDE * SIDE;
private static final short MAX_SIDE = SIZE - SIDE;
private static final byte SCALE_PRE = SIDE / SIDE_PRE;
private static final byte SIZE_PRE = SIDE_PRE * SIDE_PRE;
private static final byte SIDE_MASK = SIDE - 1;
private static final byte SIDE_PRE_MASK = SIDE_PRE - 1;
private static final byte SIDE_OFFSET = (byte) Math.round(Math.log(SIDE) / Math.log(2));
private static final byte SIDE_PRE_OFFSET = (byte) Math.round(Math.log(SIDE_PRE) / Math.log(2));
private static final short[][] NEIGHBOURS;
private final BiomePicker.ActualBiome[] biomes = new BiomePicker.ActualBiome[SIZE];
public HexBiomeChunk(WorldgenRandom random, BiomePicker picker) {
BiomePicker.ActualBiome[][] buffers = new BiomePicker.ActualBiome[2][SIZE];
for (BiomePicker.ActualBiome[] buffer : buffers) {
Arrays.fill(buffer, null);
}
for (byte index = 0; index < SIZE_PRE; index++) {
byte px = (byte) (index >> SIDE_PRE_OFFSET);
byte pz = (byte) (index & SIDE_PRE_MASK);
px = (byte) (px * SCALE_PRE + random.nextInt(SCALE_PRE));
pz = (byte) (pz * SCALE_PRE + random.nextInt(SCALE_PRE));
circle(buffers[0], getIndex(px, pz), picker.getBiome(random), null);
}
boolean hasEmptyCells = true;
byte bufferIndex = 0;
while (hasEmptyCells) {
BiomePicker.ActualBiome[] inBuffer = buffers[bufferIndex];
bufferIndex = (byte) ((bufferIndex + 1) & 1);
BiomePicker.ActualBiome[] outBuffer = buffers[bufferIndex];
hasEmptyCells = false;
for (short index = SIDE; index < MAX_SIDE; index++) {
byte z = (byte) (index & SIDE_MASK);
if (z == 0 || z == SIDE_MASK) {
continue;
}
if (inBuffer[index] != null) {
outBuffer[index] = inBuffer[index];
short[] neighbours = getNeighbours(index & SIDE_MASK);
short indexSide = (short) (index + neighbours[random.nextInt(6)]);
if (indexSide >= 0 && indexSide < SIZE && outBuffer[indexSide] == null) {
outBuffer[indexSide] = inBuffer[index];
}
} else {
hasEmptyCells = true;
}
}
}
BiomePicker.ActualBiome[] outBuffer = buffers[bufferIndex];
byte preN = (byte) (SIDE_MASK - 2);
for (byte index = 0; index < SIDE; index++) {
outBuffer[getIndex(index, (byte) 0)] = outBuffer[getIndex(index, (byte) 2)];
outBuffer[getIndex((byte) 0, index)] = outBuffer[getIndex((byte) 2, index)];
outBuffer[getIndex(index, SIDE_MASK)] = outBuffer[getIndex(index, preN)];
outBuffer[getIndex(SIDE_MASK, index)] = outBuffer[getIndex(preN, index)];
}
int lastAction = -1;
BiomePicker.ActualBiome lBiome = null;
for (short index = 0; index < SIZE; index++) {
if (outBuffer[index] == null) {
lastAction = 0;
lBiome = null;
outBuffer[index] = picker.getBiome(random);
} else if (random.nextInt(4) == 0) {
lastAction = 1;
lBiome = outBuffer[index];
circle(outBuffer, index, outBuffer[index].getSubBiome(random), outBuffer[index]);
}
if (outBuffer[index] == null) {
BCLib.LOGGER.error("Invalid Biome at " + index + ", " + lastAction + ", " + lBiome);
}
}
System.arraycopy(outBuffer, 0, this.biomes, 0, SIZE);
}
private void circle(
BiomePicker.ActualBiome[] buffer,
short center,
BiomePicker.ActualBiome biome,
BiomePicker.ActualBiome mask
) {
if (buffer[center] == mask) {
buffer[center] = biome;
}
short[] neighbours = getNeighbours(center & SIDE_MASK);
for (short i : neighbours) {
short index = (short) (center + i);
if (index >= 0 && index < SIZE && buffer[index] == mask) {
buffer[index] = biome;
}
}
}
private static byte wrap(int value) {
return (byte) (value & SIDE_MASK);
}
private short getIndex(byte x, byte z) {
return (short) ((short) x << SIDE_OFFSET | z);
}
@Override
public BiomePicker.ActualBiome getBiome(int x, int z) {
return biomes[getIndex(wrap(x), wrap(z))];
}
@Override
public void setBiome(int x, int z, BiomePicker.ActualBiome biome) {
biomes[getIndex(wrap(x), wrap(z))] = biome;
}
@Override
public int getSide() {
return SIDE;
}
public static int scaleCoordinate(int value) {
return value >> SIDE_OFFSET;
}
public static boolean isBorder(int value) {
return wrap(value) == SIDE_MASK;
}
private short[] getNeighbours(int z) {
return NEIGHBOURS[z & 1];
}
public static float scaleMap(float size) {
return size / (SIDE >> 2);
}
static {
NEIGHBOURS = new short[2][6];
NEIGHBOURS[0][0] = 1;
NEIGHBOURS[0][1] = -1;
NEIGHBOURS[0][2] = SIDE;
NEIGHBOURS[0][3] = -SIDE;
NEIGHBOURS[0][4] = SIDE + 1;
NEIGHBOURS[0][5] = SIDE - 1;
NEIGHBOURS[1][0] = 1;
NEIGHBOURS[1][1] = -1;
NEIGHBOURS[1][2] = SIDE;
NEIGHBOURS[1][3] = -SIDE;
NEIGHBOURS[1][4] = -SIDE + 1;
NEIGHBOURS[1][5] = -SIDE - 1;
}
}

View file

@ -1,187 +0,0 @@
package org.betterx.bclib.api.v2.generator.map.hex;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.interfaces.BiomeChunk;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TriConsumer;
import org.betterx.bclib.noise.OpenSimplexNoise;
import org.betterx.bclib.util.MHelper;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Random;
public class HexBiomeMap implements BiomeMap {
private static final float RAD_INNER = (float) Math.sqrt(3.0) * 0.5F;
private static final float COEF = 0.25F * (float) Math.sqrt(3.0);
private static final float COEF_HALF = COEF * 0.5F;
private static final float SIN = (float) Math.sin(0.4);
private static final float COS = (float) Math.cos(0.4);
private static final float[] EDGE_CIRCLE_X;
private static final float[] EDGE_CIRCLE_Z;
private final Map<ChunkPos, HexBiomeChunk> chunks = Maps.newConcurrentMap();
private final BiomePicker picker;
private final OpenSimplexNoise[] noises = new OpenSimplexNoise[2];
private TriConsumer<Integer, Integer, Integer> processor;
private final byte noiseIterations;
private final float scale;
private final int seed;
public HexBiomeMap(long seed, int size, BiomePicker picker) {
this.picker = picker;
this.scale = HexBiomeChunk.scaleMap(size);
Random random = new Random(seed);
noises[0] = new OpenSimplexNoise(random.nextInt());
noises[1] = new OpenSimplexNoise(random.nextInt());
noiseIterations = (byte) Math.min(Math.ceil(Math.log(scale) / Math.log(2)), 5);
this.seed = random.nextInt();
}
@Override
public void clearCache() {
if (chunks.size() > 127) {
chunks.clear();
}
}
@Override
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
BiomePicker.ActualBiome biome = getRawBiome(x, z);
BiomePicker.ActualBiome edge = biome.getEdge();
int size = biome.bclBiome.settings.getEdgeSize();
if (edge == null && biome.getParentBiome() != null) {
edge = biome.getParentBiome().getEdge();
size = biome.getParentBiome().bclBiome.settings.getEdgeSize();
}
if (edge == null) {
return biome;
}
for (byte i = 0; i < 8; i++) {
if (!getRawBiome(x + size * EDGE_CIRCLE_X[i], z + size * EDGE_CIRCLE_Z[i]).isSame(biome)) {
return edge;
}
}
return biome;
}
@Override
public BiomeChunk getChunk(final int cx, final int cz, final boolean update) {
final ChunkPos pos = new ChunkPos(cx, cz);
HexBiomeChunk chunk = chunks.get(pos);
if (chunk == null) {
WorldgenRandom random = new WorldgenRandom(RandomSource.create(MHelper.getSeed(seed, cx, cz)));
chunk = new HexBiomeChunk(random, picker);
if (update && processor != null) {
processor.accept(cx, cz, chunk.getSide());
}
chunks.put(pos, chunk);
}
return chunk;
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
this.processor = processor;
}
private BiomePicker.ActualBiome getRawBiome(double x, double z) {
double px = x / scale * RAD_INNER;
double pz = z / scale;
double dx = rotateX(px, pz);
double dz = rotateZ(px, pz);
px = dx;
pz = dz;
dx = getNoise(px, pz, (byte) 0) * 0.2F;
dz = getNoise(pz, px, (byte) 1) * 0.2F;
px += dx;
pz += dz;
int cellZ = (int) Math.floor(pz);
boolean offset = (cellZ & 1) == 1;
if (offset) {
px += 0.5;
}
int cellX = (int) Math.floor(px);
float pointX = (float) (px - cellX - 0.5);
float pointZ = (float) (pz - cellZ - 0.5);
if (Math.abs(pointZ) < 0.3333F) {
return getChunkBiome(cellX, cellZ);
}
if (insideHexagon(0, 0, 1.1555F, pointZ * RAD_INNER, pointX)) {
return getChunkBiome(cellX, cellZ);
}
cellX = pointX < 0 ? (offset ? cellX - 1 : cellX) : (offset ? cellX : cellX + 1);
cellZ = pointZ < 0 ? cellZ - 1 : cellZ + 1;
return getChunkBiome(cellX, cellZ);
}
private BiomePicker.ActualBiome getChunkBiome(int x, int z) {
int cx = HexBiomeChunk.scaleCoordinate(x);
int cz = HexBiomeChunk.scaleCoordinate(z);
if (((z >> 2) & 1) == 0 && HexBiomeChunk.isBorder(x)) {
x = 0;
cx += 1;
} else if (((x >> 2) & 1) == 0 && HexBiomeChunk.isBorder(z)) {
z = 0;
cz += 1;
}
return getChunk(cx, cz, true).getBiome(x, z);
}
private boolean insideHexagon(float centerX, float centerZ, float radius, float x, float z) {
double dx = Math.abs(x - centerX) / radius;
double dy = Math.abs(z - centerZ) / radius;
return (dy <= COEF) && (COEF * dx + 0.25F * dy <= COEF_HALF);
}
private double getNoise(double x, double z, byte state) {
double result = 0;
for (byte i = 1; i <= noiseIterations; i++) {
OpenSimplexNoise noise = noises[state];
state = (byte) ((state + 1) & 1);
result += noise.eval(x * i, z * i) / i;
}
return result;
}
private double rotateX(double x, double z) {
return x * COS - z * SIN;
}
private double rotateZ(double x, double z) {
return x * SIN + z * COS;
}
static {
EDGE_CIRCLE_X = new float[8];
EDGE_CIRCLE_Z = new float[8];
for (byte i = 0; i < 8; i++) {
float angle = i / 4F * (float) Math.PI;
EDGE_CIRCLE_X[i] = (float) Math.sin(angle);
EDGE_CIRCLE_Z[i] = (float) Math.cos(angle);
}
}
}

View file

@ -1,66 +0,0 @@
package org.betterx.bclib.api.v2.generator.map.square;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.interfaces.BiomeChunk;
import net.minecraft.world.level.levelgen.WorldgenRandom;
public class SquareBiomeChunk implements BiomeChunk {
private static final int BIT_OFFSET = 4;
protected static final int WIDTH = 1 << BIT_OFFSET;
private static final int SM_WIDTH = WIDTH >> 1;
private static final int SM_BIT_OFFSET = BIT_OFFSET >> 1;
private static final int MASK_OFFSET = SM_WIDTH - 1;
protected static final int MASK_WIDTH = WIDTH - 1;
private static final int SM_CAPACITY = SM_WIDTH * SM_WIDTH;
private static final int CAPACITY = WIDTH * WIDTH;
private final BiomePicker.ActualBiome[] biomes;
public SquareBiomeChunk(WorldgenRandom random, BiomePicker picker) {
BiomePicker.ActualBiome[] PreBio = new BiomePicker.ActualBiome[SM_CAPACITY];
biomes = new BiomePicker.ActualBiome[CAPACITY];
for (int x = 0; x < SM_WIDTH; x++) {
int offset = x << SM_BIT_OFFSET;
for (int z = 0; z < SM_WIDTH; z++) {
PreBio[offset | z] = picker.getBiome(random);
}
}
for (int x = 0; x < WIDTH; x++) {
int offset = x << BIT_OFFSET;
for (int z = 0; z < WIDTH; z++) {
biomes[offset | z] = PreBio[getSmIndex(offsetXZ(x, random), offsetXZ(z, random))].getSubBiome(random);
}
}
}
@Override
public BiomePicker.ActualBiome getBiome(int x, int z) {
return biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)];
}
@Override
public void setBiome(int x, int z, BiomePicker.ActualBiome biome) {
biomes[getIndex(x & MASK_WIDTH, z & MASK_WIDTH)] = biome;
}
@Override
public int getSide() {
return WIDTH;
}
private int offsetXZ(int x, WorldgenRandom random) {
return ((x + random.nextInt(2)) >> 1) & MASK_OFFSET;
}
private int getIndex(int x, int z) {
return x << BIT_OFFSET | z;
}
private int getSmIndex(int x, int z) {
return x << SM_BIT_OFFSET | z;
}
}

View file

@ -1,143 +0,0 @@
package org.betterx.bclib.api.v2.generator.map.square;
import org.betterx.bclib.api.v2.generator.BiomePicker;
import org.betterx.bclib.interfaces.BiomeChunk;
import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TriConsumer;
import org.betterx.bclib.noise.OpenSimplexNoise;
import org.betterx.bclib.util.MHelper;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.levelgen.LegacyRandomSource;
import net.minecraft.world.level.levelgen.WorldgenRandom;
import com.google.common.collect.Maps;
import java.util.Map;
public class SquareBiomeMap implements BiomeMap {
private final Map<ChunkPos, SquareBiomeChunk> maps = Maps.newHashMap();
private final OpenSimplexNoise noiseX;
private final OpenSimplexNoise noiseZ;
private final WorldgenRandom random;
private final BiomePicker picker;
private final int sizeXZ;
private final int depth;
private final int size;
private TriConsumer<Integer, Integer, Integer> processor;
public SquareBiomeMap(long seed, int size, BiomePicker picker) {
random = new WorldgenRandom(new LegacyRandomSource(seed));
noiseX = new OpenSimplexNoise(random.nextLong());
noiseZ = new OpenSimplexNoise(random.nextLong());
this.sizeXZ = size;
depth = (int) Math.ceil(Math.log(size) / Math.log(2)) - 2;
this.size = 1 << depth;
this.picker = picker;
}
@Override
public void clearCache() {
if (maps.size() > 32) {
maps.clear();
}
}
@Override
public BiomePicker.ActualBiome getBiome(double x, double y, double z) {
BiomePicker.ActualBiome biome = getRawBiome(x, z);
if (biome.getEdge() != null || (biome.getParentBiome() != null && biome.getParentBiome().getEdge() != null)) {
BiomePicker.ActualBiome search = biome;
if (biome.getParentBiome() != null) {
search = biome.getParentBiome();
}
int size = search.bclBiome.settings.getEdgeSize();
boolean edge = !search.isSame(getRawBiome(x + size, z));
edge = edge || !search.isSame(getRawBiome(x - size, z));
edge = edge || !search.isSame(getRawBiome(x, z + size));
edge = edge || !search.isSame(getRawBiome(x, z - size));
edge = edge || !search.isSame(getRawBiome(x - 1, z - 1));
edge = edge || !search.isSame(getRawBiome(x - 1, z + 1));
edge = edge || !search.isSame(getRawBiome(x + 1, z - 1));
edge = edge || !search.isSame(getRawBiome(x + 1, z + 1));
if (edge) {
biome = search.getEdge();
}
}
return biome;
}
@Override
public void setChunkProcessor(TriConsumer<Integer, Integer, Integer> processor) {
this.processor = processor;
}
@Override
public BiomeChunk getChunk(int cx, int cz, boolean update) {
ChunkPos cpos = new ChunkPos(cx, cz);
SquareBiomeChunk chunk = maps.get(cpos);
if (chunk == null) {
synchronized (random) {
random.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
chunk = new SquareBiomeChunk(random, picker);
}
maps.put(cpos, chunk);
if (update && processor != null) {
processor.accept(cx, cz, chunk.getSide());
}
}
return chunk;
}
private BiomePicker.ActualBiome getRawBiome(double bx, double bz) {
double x = bx * size / sizeXZ;
double z = bz * size / sizeXZ;
double px = bx * 0.2;
double pz = bz * 0.2;
for (int i = 0; i < depth; i++) {
double nx = (x + noiseX.eval(px, pz)) / 2F;
double nz = (z + noiseZ.eval(px, pz)) / 2F;
x = nx;
z = nz;
px = px / 2 + i;
pz = pz / 2 + i;
}
int ix = MHelper.floor(x);
int iz = MHelper.floor(z);
if ((ix & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
x += (iz / 2) & 1;
}
if ((iz & SquareBiomeChunk.MASK_WIDTH) == SquareBiomeChunk.MASK_WIDTH) {
z += (ix / 2) & 1;
}
ChunkPos cpos = new ChunkPos(
MHelper.floor(x / SquareBiomeChunk.WIDTH),
MHelper.floor(z / SquareBiomeChunk.WIDTH)
);
SquareBiomeChunk chunk = maps.get(cpos);
if (chunk == null) {
synchronized (random) {
random.setLargeFeatureWithSalt(0, cpos.x, cpos.z, 0);
chunk = new SquareBiomeChunk(random, picker);
}
maps.put(cpos, chunk);
}
return chunk.getBiome(MHelper.floor(x), MHelper.floor(z));
}
}

View file

@ -1,64 +0,0 @@
package org.betterx.bclib.mixin.common;
import org.betterx.bclib.api.v2.generator.TheEndBiomesHelper;
import org.betterx.bclib.api.v2.levelgen.biomes.BCLBiome;
import org.betterx.bclib.api.v2.levelgen.biomes.InternalBiomeAPI;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.fabricmc.fabric.api.biome.v1.TheEndBiomes;
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;
@Mixin(value = TheEndBiomes.class, remap = false)
public class TheEndBiomesMixin {
@Inject(method = "addBarrensBiome", at = @At("HEAD"))
private static void bcl_registerBarrens(
ResourceKey<Biome> highlands,
ResourceKey<Biome> barrens,
double weight,
CallbackInfo ci
) {
TheEndBiomesHelper.add(InternalBiomeAPI.OTHER_END_BARRENS, barrens);
}
@Inject(method = "addMidlandsBiome", at = @At("HEAD"))
private static void bcl_registerMidlands(
ResourceKey<Biome> highlands,
ResourceKey<Biome> midlands,
double weight,
CallbackInfo ci
) {
BCLBiome highland = InternalBiomeAPI.wrapNativeBiome(highlands, InternalBiomeAPI.OTHER_END_LAND);
BCLBiome midland = InternalBiomeAPI.wrapNativeBiome(midlands, InternalBiomeAPI.OTHER_END_LAND);
if (highland != null) {
highland.addEdge(midland);
}
TheEndBiomesHelper.add(InternalBiomeAPI.OTHER_END_LAND, midlands);
}
@Inject(method = "addSmallIslandsBiome", at = @At("HEAD"))
private static void bcl_registerSmallIslands(
ResourceKey<Biome> biome, double weight, CallbackInfo ci
) {
TheEndBiomesHelper.add(InternalBiomeAPI.OTHER_END_VOID, biome);
}
@Inject(method = "addHighlandsBiome", at = @At("HEAD"))
private static void bcl_registerHighlands(
ResourceKey<Biome> biome, double weight, CallbackInfo ci
) {
TheEndBiomesHelper.add(InternalBiomeAPI.OTHER_END_LAND, biome);
}
@Inject(method = "addMainIslandBiome", at = @At("HEAD"))
private static void bcl_registerMainIsnalnd(
ResourceKey<Biome> biome, double weight, CallbackInfo ci
) {
TheEndBiomesHelper.add(InternalBiomeAPI.OTHER_END_CENTER, biome);
}
}

View file

@ -29,7 +29,6 @@
"ServerLevelMixin",
"ShovelItemAccessor",
"SurfaceRulesContextAccessor",
"TheEndBiomesMixin",
"WorldGenRegionMixin",
"boat.BoatItemMixin",
"boat.BoatMixin",