Use key-based detection of End-Biomes (#11)

This commit is contained in:
Frank 2022-06-30 13:52:34 +02:00
parent 473ed9a165
commit 185453b0c4
2 changed files with 128 additions and 46 deletions

View file

@ -7,7 +7,6 @@ import org.betterx.bclib.api.v2.levelgen.biomes.BiomeAPI;
import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry; import org.betterx.bclib.config.ConfigKeeper.StringArrayEntry;
import org.betterx.bclib.config.Configs; import org.betterx.bclib.config.Configs;
import org.betterx.bclib.interfaces.BiomeMap; import org.betterx.bclib.interfaces.BiomeMap;
import org.betterx.bclib.interfaces.TheEndBiomeDataAccessor;
import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig; import org.betterx.worlds.together.biomesource.BiomeSourceWithConfig;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
@ -17,6 +16,7 @@ import net.minecraft.core.QuartPos;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos; import net.minecraft.core.SectionPos;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.BiomeTags; import net.minecraft.tags.BiomeTags;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
@ -25,8 +25,6 @@ import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.biome.Climate; import net.minecraft.world.level.biome.Climate;
import net.minecraft.world.level.levelgen.DensityFunction; import net.minecraft.world.level.levelgen.DensityFunction;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -110,34 +108,44 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi
StringArrayEntry.class StringArrayEntry.class
).getValue(); ).getValue();
this.possibleBiomes().forEach(biome -> { this.possibleBiomes().forEach(biome -> {
ResourceLocation key = biome.unwrapKey().orElseThrow().location(); ResourceKey<Biome> key = biome.unwrapKey().orElseThrow();
ResourceLocation biomeID = key.location();
if (!BiomeAPI.hasBiome(key)) { if (!BiomeAPI.hasBiome(biomeID)) {
BCLBiome bclBiome = new BCLBiome(key, biome.value()); BCLBiome bclBiome = new BCLBiome(biomeID, biome.value());
if (includeVoid.contains(key.toString())) { if (includeVoid.contains(biomeID.toString())) {
endVoidBiomePicker.addBiome(bclBiome); endVoidBiomePicker.addBiome(bclBiome);
} else { } else {
endLandBiomePicker.addBiome(bclBiome); endLandBiomePicker.addBiome(bclBiome);
} }
} else { } else {
BCLBiome bclBiome = BiomeAPI.getBiome(key); BCLBiome bclBiome = BiomeAPI.getBiome(biomeID);
if (bclBiome != BiomeAPI.EMPTY_BIOME) { if (bclBiome != BiomeAPI.EMPTY_BIOME) {
if (bclBiome.getParentBiome() == null) { if (bclBiome.getParentBiome() == null) {
if (config.withVoidBiomes) { if (config.withVoidBiomes) {
if (BiomeAPI.wasRegisteredAsEndVoidBiome(key) || includeVoid.contains(key.toString())) { if (BiomeAPI.wasRegisteredAsEndVoidBiome(biomeID)
|| TheEndBiomesHelper.isIntendedForEndBarrens(key)
|| includeVoid.contains(biomeID.toString())
) {
endVoidBiomePicker.addBiome(bclBiome); endVoidBiomePicker.addBiome(bclBiome);
} else if (BiomeAPI.wasRegisteredAsEndLandBiome(key) || includeLand.contains(key.toString())) { } else if (BiomeAPI.wasRegisteredAsEndLandBiome(biomeID)
|| TheEndBiomesHelper.isIntendedForEndLand(key)
|| includeLand.contains(biomeID.toString())
) {
endLandBiomePicker.addBiome(bclBiome); endLandBiomePicker.addBiome(bclBiome);
} }
} else { } else {
if (BiomeAPI.wasRegisteredAsEndLandBiome(key) || includeLand.contains(key.toString())) { if (BiomeAPI.wasRegisteredAsEndLandBiome(biomeID)
|| TheEndBiomesHelper.isIntendedForEndLand(key)
|| includeLand.contains(biomeID.toString())
) {
endLandBiomePicker.addBiome(bclBiome); endLandBiomePicker.addBiome(bclBiome);
endVoidBiomePicker.addBiome(bclBiome); endVoidBiomePicker.addBiome(bclBiome);
} }
if (!key.equals(Biomes.SMALL_END_ISLANDS.location()) && !key.equals(Biomes.THE_END.location()) if (!biomeID.equals(Biomes.SMALL_END_ISLANDS.location()) && !biomeID.equals(Biomes.THE_END.location())
&& (BiomeAPI.wasRegisteredAsEndVoidBiome(key) || includeVoid.contains(key.toString())) && (BiomeAPI.wasRegisteredAsEndVoidBiome(biomeID) || includeVoid.contains(biomeID.toString()))
) { ) {
endVoidBiomePicker.addBiome(bclBiome); endVoidBiomePicker.addBiome(bclBiome);
} }
@ -186,24 +194,12 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi
"end_void_biomes", "end_void_biomes",
StringArrayEntry.class StringArrayEntry.class
).getValue()); ).getValue());
if (TheEndBiomeData.createOverrides(biomeRegistry) instanceof TheEndBiomeDataAccessor acc) { return getBiomes(
return getBiomes( biomeRegistry,
biomeRegistry, new ArrayList<>(0),
new ArrayList<>(0), include,
include, BCLibEndBiomeSource::isValidNonVanillaEndBiome
(biome, location) -> );
BCLibEndBiomeSource.isValidNonVanillaEndBiome(biome, location) ||
acc.bcl_isNonVanillaAndCanGenerateInEnd(biome.unwrapKey().orElseThrow())
);
} else {
return getBiomes(
biomeRegistry,
new ArrayList<>(0),
include,
BCLibEndBiomeSource::isValidNonVanillaEndBiome
);
}
} }
private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) { private static List<Holder<Biome>> getBiomes(Registry<Biome> biomeRegistry) {
@ -218,31 +214,21 @@ public class BCLibEndBiomeSource extends BCLBiomeSource implements BiomeSourceWi
StringArrayEntry.class StringArrayEntry.class
).getValue()); ).getValue());
if (TheEndBiomeData.createOverrides(biomeRegistry) instanceof TheEndBiomeDataAccessor acc) { return getBiomes(biomeRegistry, new ArrayList<>(0), include, BCLibEndBiomeSource::isValidEndBiome);
return getBiomes(
biomeRegistry,
new ArrayList<>(0),
include,
(biome, location) ->
BCLibEndBiomeSource.isValidEndBiome(biome, location) || acc.bcl_canGenerateInEnd(
biome.unwrapKey().orElseThrow())
);
} else {
return getBiomes(biomeRegistry, new ArrayList<>(0), include, BCLibEndBiomeSource::isValidEndBiome);
}
} }
private static boolean isValidEndBiome(Holder<Biome> biome, ResourceLocation location) { private static boolean isValidEndBiome(Holder<Biome> biome, ResourceLocation location) {
return biome.is(BiomeTags.IS_END) || return biome.is(BiomeTags.IS_END) ||
BiomeAPI.wasRegisteredAsEndBiome(location); BiomeAPI.wasRegisteredAsEndBiome(location) ||
TheEndBiomesHelper.isIntendedForAny(biome.unwrapKey().orElse(null));
} }
private static boolean isValidNonVanillaEndBiome(Holder<Biome> biome, ResourceLocation location) { private static boolean isValidNonVanillaEndBiome(Holder<Biome> biome, ResourceLocation location) {
return biome.is(BiomeTags.IS_END) || return biome.is(BiomeTags.IS_END) ||
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_LAND) || BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_LAND) ||
BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_VOID); BiomeAPI.wasRegisteredAs(location, BiomeAPI.BiomeType.BCL_END_VOID) ||
TheEndBiomesHelper.isIntendedForAny(biome.unwrapKey().orElse(null));
} }
public static void register() { public static void register() {

View file

@ -0,0 +1,96 @@
package org.betterx.bclib.api.v2.generator;
import org.betterx.bclib.BCLib;
import org.betterx.bclib.interfaces.TheEndBiomeDataAccessor;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
import net.fabricmc.fabric.impl.biome.TheEndBiomeData;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
/**
* Helper class until FAPI integrates https://github.com/FabricMC/fabric/pull/2369
*/
public class TheEndBiomesHelper {
public static TheEndBiomeDataAccessor INSTANCE;
private static TheEndBiomeDataAccessor get() {
if (INSTANCE == null) {
try {
Class<TheEndBiomeData> cl = TheEndBiomeData.class;
Constructor constr = Arrays.stream(cl.getDeclaredConstructors())
.filter(c -> c.getParameterCount() == 0)
.findFirst()
.orElseThrow();
constr.setAccessible(true);
INSTANCE = (TheEndBiomeDataAccessor) constr.newInstance();
} catch (NoClassDefFoundError cnf) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
}
if (INSTANCE == null) {
BCLib.LOGGER.warning("Unable to access internal End-Biome API from Fabric. Using Fallback behaviour.");
INSTANCE = new TheEndBiomeDataAccessor() {
@Override
public boolean bcl_canGenerateAsEndBiome(ResourceKey<Biome> key) {
return true;
}
@Override
public boolean bcl_canGenerateAsEndMidlandBiome(ResourceKey<Biome> key) {
return false;
}
@Override
public boolean bcl_canGenerateAsEndBarrensBiome(ResourceKey<Biome> key) {
return false;
}
};
}
}
return INSTANCE;
}
/**
* Returns true if the given biome was added in the end, considering the Vanilla end biomes,
* and any biomes added to the End by mods.
*/
public static boolean isIntendedForEndBiome(ResourceKey<Biome> biome) {
return get().bcl_canGenerateAsEndBiome(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.
*/
public static boolean isIntendedForEndMidlands(ResourceKey<Biome> biome) {
return get().bcl_canGenerateAsEndMidlandBiome(biome);
}
/**
* 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.
*/
public static boolean isIntendedForEndBarrens(ResourceKey<Biome> biome) {
return get().bcl_canGenerateAsEndBarrensBiome(biome);
}
public static boolean isIntendedForEndLand(ResourceKey<Biome> biome) {
return isIntendedForEndBiome(biome) || isIntendedForEndMidlands(biome);
}
public static boolean isIntendedForAny(ResourceKey<Biome> biome) {
return isIntendedForEndBiome(biome) || isIntendedForEndMidlands(biome) || isIntendedForEndBarrens(biome);
}
}