Skip to content

Commit

Permalink
Initial work on code implementation of Biome Properties loot condition
Browse files Browse the repository at this point in the history
  • Loading branch information
GirafiStudios committed Sep 20, 2020
1 parent 03813b6 commit bacb9b0
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,41 @@
import com.google.gson.JsonObject;
import com.teammetallurgy.aquaculture.Aquaculture;
import net.minecraft.advancements.criterion.MinMaxBounds;
import net.minecraft.util.IStringSerializable;
import net.minecraft.util.JSONUtils;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.registries.ForgeRegistries;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.stream.Collectors;

public class BiomePropertiesPredicate {
private static final BiomePropertiesPredicate ANY = new BiomePropertiesPredicate(MinMaxBounds.FloatBound.UNBOUNDED, MinMaxBounds.FloatBound.UNBOUNDED, MinMaxBounds.FloatBound.UNBOUNDED, Lists.newArrayList(), Lists.newArrayList(), false);
private static final List<Biome.Category> INVALID_TAGS = Arrays.asList(Biome.Category.NETHER, Biome.Category.THEEND, Biome.Category.NONE);
private static final BiomePropertiesPredicate ANY = new BiomePropertiesPredicate(MinMaxBounds.FloatBound.UNBOUNDED, MinMaxBounds.FloatBound.UNBOUNDED, MinMaxBounds.FloatBound.UNBOUNDED, Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList(), Lists.newArrayList());
private static final List<Biome.Category> INVALID_CATEGORIES = Arrays.asList(Biome.Category.NETHER, Biome.Category.THEEND, Biome.Category.NONE);
private final MinMaxBounds.FloatBound x;
private final MinMaxBounds.FloatBound y;
private final MinMaxBounds.FloatBound z;
private final List<Biome.Category> include;
private final List<Biome.Category> exclude;
public final boolean and;
private final List<TemperatureTypes> temperatureTypes;
private final List<Biome.RainType> rainTypes;

public BiomePropertiesPredicate(MinMaxBounds.FloatBound x, MinMaxBounds.FloatBound y, MinMaxBounds.FloatBound z, List<Biome.Category> include, List<Biome.Category> exclude, boolean and) {
public BiomePropertiesPredicate(MinMaxBounds.FloatBound x, MinMaxBounds.FloatBound y, MinMaxBounds.FloatBound z, List<Biome.Category> include, List<Biome.Category> exclude, List<TemperatureTypes> temperatureTypes, List<Biome.RainType> rainTypes) {
this.x = x;
this.y = y;
this.z = z;
this.include = include;
this.exclude = exclude;
this.and = and;
this.temperatureTypes = temperatureTypes;
this.rainTypes = rainTypes;
}

public boolean test(ServerWorld world, float x, float y, float z) {
Expand All @@ -46,47 +54,61 @@ public boolean test(ServerWorld world, float x, float y, float z) {
} else {
BlockPos pos = new BlockPos(x, y, z);
Biome biome = world.getBiome(pos);
return getValidBiomes(this.include, this.exclude, this.and).contains(biome);
Biome biomeFromRegistry = ForgeRegistries.BIOMES.getValue(world.func_241828_r().getRegistry(Registry.BIOME_KEY).getKey(biome));
return getValidBiomes(this.include, this.exclude, this.temperatureTypes, this.rainTypes).contains(biomeFromRegistry);
}
}

public static List<Biome> getValidBiomes(List<Biome.Category> includeList, List<Biome.Category> excludeList, boolean and) {
List<Biome> biomes = Lists.newArrayList();
public static List<Biome> getValidBiomes(List<Biome.Category> includeList, List<Biome.Category> excludeList, List<TemperatureTypes> temperatureTypes, List<Biome.RainType> rainTypes) { //Can't add biome as a parameter, since this called elsewhere where world is not available
List<Biome> registryBiomes = Lists.newArrayList(ForgeRegistries.BIOMES.getValues());
List<Biome> biomes = Lists.newArrayList(registryBiomes);

if (includeList.isEmpty() && !excludeList.isEmpty()) { //Add all Biome Categories, when only excluding biomes
boolean includeIsEmpty = includeList.isEmpty();
boolean excludeIsEmpty = excludeList.isEmpty();

if (includeIsEmpty && !excludeIsEmpty) { //Add all Biome Categories, when only excluding biomes
includeList.addAll(Arrays.asList(Biome.Category.values()));
excludeList.addAll(INVALID_TAGS);
excludeList.addAll(INVALID_CATEGORIES);
}

/*if (!includeList.isEmpty()) {
List<Biome> addBiomes = Lists.newArrayList();
for (Biome.Category category : includeList) {
addBiomes.addAll(BiomeDictionary.getBiomes(category));
}
if (includeIsEmpty && excludeIsEmpty) { //Exclude invalid Biome Categories, when only temperature and/or rain type is specified
excludeList.addAll(INVALID_CATEGORIES);
}

if (and) {
for (Biome.Category category : includeList) {
addBiomes.removeIf(biome -> !BiomeDictionary.hasType(biome, category));
}
if (!includeIsEmpty) {
if (includeList.stream().noneMatch(INVALID_CATEGORIES::contains)) { //Exclude invalid tags, as long as they're not specified in include
excludeList.addAll(INVALID_CATEGORIES);
}
}

if (includeList.stream().noneMatch(INVALID_TAGS::contains)) { //Exclude invalid tags, as long as they're not specified in include
excludeList.addAll(INVALID_TAGS);
}
for (Biome addBiome : addBiomes) {
if (!biomes.contains(addBiome)) {
biomes.add(addBiome);
}
}
if (!includeIsEmpty) {
biomes.removeIf(biome -> !includeList.contains(biome.getCategory()));
}
if (!excludeList.isEmpty()) {
for (BiomeDictionary.Type type : excludeList) {
biomes.removeAll(BiomeDictionary.getBiomes(type));
}
}*/
if (!excludeIsEmpty) {
biomes.removeIf(biome -> excludeList.contains(biome.getCategory()));
}

if (!temperatureTypes.isEmpty()) {
biomes.removeIf(biome -> !temperatureTypes.contains(getTemperatureType(biome.getTemperature())));
}

if (!rainTypes.isEmpty()) {
biomes.removeIf(biome -> !rainTypes.contains(biome.getPrecipitation()));
}

return biomes;
}

public static TemperatureTypes getTemperatureType(float temp) {
if (temp < 0.15F) {
return TemperatureTypes.COLD;
} else if (temp >= 0.15F && temp < 1.0F) {
return TemperatureTypes.TEMPERATE;
} else {
return TemperatureTypes.HOT;
}
}

public JsonElement serialize() {
if (this == ANY) {
return JsonNull.INSTANCE;
Expand All @@ -109,7 +131,16 @@ public JsonElement serialize() {
object.add("exclude", object.getAsJsonArray(category.getName()));
}
}
object.addProperty("and", object.getAsBoolean());
if (this.temperatureTypes != null) {
for (TemperatureTypes temperatureTypes : this.temperatureTypes) {
object.add("temperature", object.getAsJsonArray(temperatureTypes.getName()));
}
}
if (this.rainTypes != null) {
for (Biome.RainType rainType : this.rainTypes) {
object.add("rain_type", object.getAsJsonArray(rainType.getName()));
}
}
return object;
}
}
Expand All @@ -129,8 +160,9 @@ public static BiomePropertiesPredicate deserialize(@Nullable JsonElement element
Biome.Category category = Biome.Category.byName(name);
if (category == null) {
Aquaculture.LOG.error("Failed to include Biome Category: " + name + ". Please check your loot tables");
} else {
include.add(category);
}
include.add(category);
}
}

Expand All @@ -142,18 +174,73 @@ public static BiomePropertiesPredicate deserialize(@Nullable JsonElement element
Biome.Category category = Biome.Category.byName(name);
if (category == null) {
Aquaculture.LOG.error("Failed to exclude Biome Category: " + name + ". Please check your loot tables");
} else {
exclude.add(category);
}
}
}

List<TemperatureTypes> temperatureTypes = Lists.newArrayList();
if (location.has("temperature")) {
JsonArray temperatureArray = JSONUtils.getJsonArray(location, "temperature");
for (int entry = 0; entry < temperatureArray.size(); entry++) {
String name = temperatureArray.get(entry).getAsString().toLowerCase(Locale.ROOT);
TemperatureTypes temperatureType = TemperatureTypes.getTemperatureType(name);
if (temperatureType == null) {
Aquaculture.LOG.error("Could not find Biome Temperature Type: " + name + ". Please check your loot tables");
} else {
temperatureTypes.add(temperatureType);
}
exclude.add(category);
}
}

boolean and = false;
if (location.has("and")) {
and = JSONUtils.getBoolean(location, "and");
List<Biome.RainType> rainTypes = Lists.newArrayList();
if (location.has("rain_type")) {
JsonArray rainTypeArray = JSONUtils.getJsonArray(location, "rain_type");
for (int entry = 0; entry < rainTypeArray.size(); entry++) {
String name = rainTypeArray.get(entry).getAsString().toLowerCase(Locale.ROOT);
Biome.RainType rainType = Biome.RainType.getRainType(name);
if (rainType == null) {
Aquaculture.LOG.error("Could not find Biome Rain Type: " + name + ". Please check your loot tables");
} else {
rainTypes.add(rainType);
}
}
}
return new BiomePropertiesPredicate(x, y, z, include, exclude, and);
/*System.out.println("include: " + include);
System.out.println("exclude: " + exclude);
System.out.println("temp: " + temperatureTypes);
System.out.println("rain: " + rainTypes);*/
return new BiomePropertiesPredicate(x, y, z, include, exclude, temperatureTypes, rainTypes);
} else {
return ANY;
}
}

public enum TemperatureTypes implements IStringSerializable {
COLD("cold"),
TEMPERATE("temperate"),
HOT("hot");

private static final Map<String, TemperatureTypes> BY_NAME = Arrays.stream(values()).collect(Collectors.toMap(TemperatureTypes::getName, (precipitation) -> precipitation));
private final String name;

private TemperatureTypes(String name) {
this.name = name;
}

public String getName() {
return this.name;
}

public static TemperatureTypes getTemperatureType(String name) {
return BY_NAME.get(name);
}

@Override
@Nonnull
public String getString() {
return this.name;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,8 @@ private static List<Biome> getSpawnableBiomes(JsonElement predicate) {
List<Biome> biomes = Lists.newArrayList();
List<Biome.Category> includeList = Lists.newArrayList();
List<Biome.Category> excludeList = Lists.newArrayList();
boolean and = false;

if (predicate.getAsJsonObject().has("and")) {
and = predicate.getAsJsonObject().get("and").getAsBoolean();
}
List<BiomePropertiesPredicate.TemperatureTypes> temperatureTypes = Lists.newArrayList();
List<Biome.RainType> rainTypes = Lists.newArrayList();

if (predicate.getAsJsonObject().has("include")) {
JsonArray include = predicate.getAsJsonObject().get("include").getAsJsonArray();
Expand All @@ -103,7 +100,19 @@ private static List<Biome> getSpawnableBiomes(JsonElement predicate) {
excludeList.add(Biome.Category.byName(exclude.get(entry).getAsString()));
}
}
biomes.addAll(BiomePropertiesPredicate.getValidBiomes(includeList, excludeList, and));
if (predicate.getAsJsonObject().has("temperature")) {
JsonArray temperature = predicate.getAsJsonObject().get("temperature").getAsJsonArray();
for (int entry = 0; entry < temperature.size(); entry++) {
temperatureTypes.add(BiomePropertiesPredicate.TemperatureTypes.getTemperatureType(temperature.get(entry).getAsString()));
}
}
if (predicate.getAsJsonObject().has("rain_type")) {
JsonArray rain = predicate.getAsJsonObject().get("rain_type").getAsJsonArray();
for (int entry = 0; entry < rain.size(); entry++) {
rainTypes.add(Biome.RainType.getRainType(rain.get(entry).getAsString()));
}
}
biomes.addAll(BiomePropertiesPredicate.getValidBiomes(includeList, excludeList, temperatureTypes, rainTypes));
return biomes;
}

Expand All @@ -125,9 +134,9 @@ public static void addFishSpawns() {
int weight = FISH_WEIGHT_MAP.get(fish) / 3;
int maxGroupSize = MathHelper.clamp((FISH_WEIGHT_MAP.get(fish) / 10), 1, 8);
if (weight < 1) weight = 1;
if (AquaConfig.BASIC_OPTIONS.debugMode.get()) {
/*if (AquaConfig.BASIC_OPTIONS.debugMode.get()) { //TODO Uncomment
Aquaculture.LOG.info(fish.getRegistryName() + " spawn debug = loottable weight: " + FISH_WEIGHT_MAP.get(fish) + " | weight : " + weight + " | maxGroupSize: " + maxGroupSize);
}
}*/
/*for (Biome biome : FISH_BIOME_MAP.get(fish)) { //TODO
biome.getSpawns(EntityClassification.WATER_CREATURE).add(new Biome.SpawnListEntry(fish, weight, 1, maxGroupSize));
}*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -501,8 +501,8 @@
{
"condition": "aquaculture:biome_properties_check",
"predicate": {
"include": ["TWILIGHT"],
"_COMMENT": "TODO. Maybe move to custom dimension loot condition"
"include": ["NONE"],
"_COMMENT": "TODO. Maybe move to custom dimension loot condition?"
}
}
],
Expand Down

0 comments on commit bacb9b0

Please sign in to comment.