All Downloads are FREE. Search and download functionalities are using the official Maven repository.

personthecat.catlib.data.BiomePredicate Maven / Gradle / Ivy

Go to download

Utilities for serialization, commands, noise generation, IO, and some new data types.

The newest version!
package personthecat.catlib.data;

import com.mojang.serialization.Codec;
import lombok.*;
import lombok.experimental.FieldNameConstants;
import net.minecraft.class_1959;
import net.minecraft.class_2960;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import personthecat.catlib.data.collections.InfinitySet;
import personthecat.catlib.data.collections.InvertibleSet;
import personthecat.catlib.data.collections.MultiValueHashMap;
import personthecat.catlib.data.collections.MultiValueMap;
import personthecat.catlib.registry.DynamicRegistries;
import personthecat.catlib.mixin.BiomeAccessor;
import personthecat.catlib.serialization.codec.CodecUtils;
import personthecat.catlib.util.McUtils;

import javax.annotation.concurrent.NotThreadSafe;
import java.util.*;
import java.util.function.Predicate;

import static personthecat.catlib.serialization.codec.CodecUtils.codecOf;
import static personthecat.catlib.serialization.codec.CodecUtils.simpleEither;
import static personthecat.catlib.serialization.codec.FieldDescriptor.defaultGet;
import static personthecat.catlib.serialization.codec.FieldDescriptor.defaulted;

@Getter
@Builder
@NotThreadSafe
@FieldNameConstants
@AllArgsConstructor
@RequiredArgsConstructor
public class BiomePredicate implements Predicate {

    @With private final boolean blacklist;

    // Todo: additional conditions
    @NotNull private final List names;
    @NotNull private final List mods;
    @NotNull private final List types;

    @Nullable private Set compiled;

    private int registryTracker;

    public static final BiomePredicate ALL_BIOMES = builder().build();

    private static final Codec OBJECT_CODEC = codecOf(
        defaulted(Codec.BOOL, Fields.blacklist, false, BiomePredicate::isBlacklist),
        defaultGet(CodecUtils.ID_LIST, Fields.names, Collections::emptyList, BiomePredicate::getNames),
        defaultGet(CodecUtils.STRING_LIST, Fields.mods, Collections::emptyList, BiomePredicate::getMods),
        defaultGet(CodecUtils.CATEGORY_LIST, Fields.types, Collections::emptyList, BiomePredicate::getTypes),
        BiomePredicate::new
    );

    private static final Codec ID_CODEC =
        CodecUtils.ID_LIST.xmap(ids -> builder().names(ids).build(), BiomePredicate::getNames);

    public static final Codec CODEC = simpleEither(ID_CODEC, OBJECT_CODEC)
        .withEncoder(bp -> bp.isNamesOnly() ? ID_CODEC : OBJECT_CODEC);

    @Override
    public boolean test(final class_1959 biome) {
        return this.getCompiled().contains(biome);
    }

    @NotNull
    @SuppressWarnings("UnusedReturnValue")
    public synchronized Set compile() {
        final Set all = new HashSet<>();
        DynamicRegistries.BIOMES.forEach(all::add);

        if (this.isEmpty()) {
            return new InfinitySet<>(all);
        }
        final Set matching = new HashSet<>();
        DynamicRegistries.BIOMES.forEach((id, biome) -> {
            if (this.matches(biome, id)) {
                matching.add(biome);
            }
        });
        this.registryTracker = DynamicRegistries.BIOMES.getId();
        return this.compiled = new InvertibleSet<>(matching, this.blacklist).optimize(all);
    }

    @NotNull
    public Set getCompiled() {
        if (this.compiled == null || this.registryTracker != DynamicRegistries.BIOMES.getId()) {
            return this.compile();
        }
        return this.compiled;
    }

    public boolean isEmpty() {
        return this.names.isEmpty() && this.types.isEmpty() && this.mods.isEmpty();
    }

    public boolean matches(final class_1959 biome, final class_2960 id) {
        if (this.isEmpty()) return true;
        return this.names.contains(id)
            || this.mods.contains(id.method_12836())
            || this.types.contains(((BiomeAccessor) (Object) biome).getBiomeCategory());
    }

    public boolean matchesName(final class_2960 id) {
        return this.names.isEmpty() || this.names.contains(id);
    }

    public boolean matchesMod(final class_2960 id) {
        return this.mods.isEmpty() || this.mods.contains(id.method_12836());
    }

    public boolean matchesType(final class_1959.class_1961 type) {
        return this.types.isEmpty() || this.types.contains(type);
    }

    public boolean isNamesOnly() {
        return !this.blacklist && this.mods.isEmpty() && this.types.isEmpty();
    }

    public BiomePredicate simplify() {
        if (this.equals(ALL_BIOMES)) {
            return ALL_BIOMES;
        }
        final InvertibleSet biomes = this.reconstruct();
        final MultiValueMap categories = categorize(biomes);
        final List names = new ArrayList<>();
        final List types = new ArrayList<>();

        for (final Map.Entry> entry : categories.entrySet()) {
            final List possible = McUtils.getBiomes(entry.getKey());
            if (possible.size() == entry.getValue().size()) {
                types.add(entry.getKey());
            } else {
                for (final class_1959 biome : entry.getValue()) {
                    names.add(DynamicRegistries.BIOMES.getKey(biome));
                }
            }
        }
        return new BiomePredicate(biomes.isBlacklist(), names, Collections.emptyList(), types);
    }

    private InvertibleSet reconstruct() {
        final Set compiled = this.compiled != null ? this.compiled : this.compile();
        final Set all = new HashSet<>();
        DynamicRegistries.BIOMES.forEach(all::add);
        if (compiled.size() > all.size() / 2) {
            final Set inverted = new HashSet<>(all);
            inverted.removeAll(compiled);
            return InvertibleSet.wrap(inverted).blacklist(true);
        }
        return InvertibleSet.wrap(compiled);
    }

    private static MultiValueMap categorize(final Collection biomes) {
        final MultiValueMap categories = new MultiValueHashMap<>();
        for (final class_1959 biome : biomes) {
            categories.add(((BiomeAccessor) (Object) biome).getBiomeCategory(), biome);
        }
        return categories;
    }

    @Override
    public int hashCode() {
        return this.getCompiled().hashCode();
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) {
            return true;
        }
        if (o instanceof BiomePredicate) {
            return this.getCompiled().equals(((BiomePredicate) o).getCompiled());
        }
        return false;
    }

    public static class BiomePredicateBuilder {
        @SuppressWarnings("ConstantConditions")
        public BiomePredicate build() {
            if (this.names == null) this.names = Collections.emptyList();
            if (this.mods == null) this.mods = Collections.emptyList();
            if (this.types == null) this.types = Collections.emptyList();
            return new BiomePredicate(this.blacklist, this.names, this.mods, this.types);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy