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

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

package personthecat.catlib.data;

import com.mojang.serialization.Codec;
import lombok.*;
import lombok.experimental.FieldNameConstants;
import net.minecraft.class_2791;
import net.minecraft.class_2818;
import net.minecraft.class_2874;
import net.minecraft.class_2960;
import net.minecraft.class_4538;
import net.minecraft.class_5363;
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.registry.DynamicRegistries;
import personthecat.catlib.serialization.codec.CodecUtils;
import personthecat.catlib.util.DimInjector;

import javax.annotation.concurrent.NotThreadSafe;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
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.defaulted;
import static personthecat.catlib.serialization.codec.FieldDescriptor.defaultGet;

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

    @With private final boolean blacklist;

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

    @Nullable private Set compiled;

    private int registryTracker;

    public static final DimensionPredicate ALL_DIMENSIONS = builder().build();

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

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

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

    public boolean test(final class_5363 stem) {
        return this.test(stem.method_29566().comp_349());
    }

    public boolean test(final class_4538 level) {
        return this.test(level.method_8597());
    }

    public boolean test(final class_2791 chunk) {
        if (chunk instanceof DimInjector) {
            final class_2874 type = ((DimInjector) chunk).getType();
            if (type != null) {
                return this.test(type);
            }
        } else if (chunk instanceof class_2818) {
            return this.test(((class_2818) chunk).method_12200());
        }
        return this.isEmpty();
    }

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

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

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

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

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

    public boolean matches(final class_2874 type, final class_2960 id) {
        if (this.isEmpty()) return true;
        return this.names.contains(id) || this.mods.contains(id.method_12836());
    }

    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 isNamesOnly() {
        return !this.blacklist && this.mods.isEmpty();
    }

    public DimensionPredicate simplify() {
        if (this.equals(ALL_DIMENSIONS)) {
            return ALL_DIMENSIONS;
        }
        return this;
    }

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

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

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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy