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

com.yungnickyoung.minecraft.yungsapi.world.structure.condition.PieceInRangeCondition Maven / Gradle / Ivy

The newest version!
package com.yungnickyoung.minecraft.yungsapi.world.structure.condition;

import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.yungnickyoung.minecraft.yungsapi.YungsApiCommon;
import com.yungnickyoung.minecraft.yungsapi.mixin.accessor.SinglePoolElementAccessor;
import com.yungnickyoung.minecraft.yungsapi.world.structure.context.StructureContext;
import com.yungnickyoung.minecraft.yungsapi.world.structure.jigsaw.PieceEntry;
import com.yungnickyoung.minecraft.yungsapi.world.structure.jigsaw.element.YungJigsawSinglePoolElement;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.world.level.levelgen.structure.PoolElementStructurePiece;
import net.minecraft.world.level.levelgen.structure.pools.SinglePoolElement;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplateManager;

import java.util.ArrayList;
import java.util.List;

/**
 * Searches a specified number of blocks from a given position and checks for a structure piece.
 * Passes if a structure piece is found matching one of the entries from the given list.
 * Note that "yungsapi:all" is an acceptable entry for matching any piece.
 */
public class PieceInRangeCondition extends StructureCondition {
    private static final ResourceLocation ALL = ResourceLocation.fromNamespaceAndPath(YungsApiCommon.MOD_ID, "all");

    public static final MapCodec CODEC = RecordCodecBuilder.mapCodec((builder) -> builder
            .group(
                    ResourceLocation.CODEC.listOf().optionalFieldOf("pieces", new ArrayList<>()).forGetter(conditon -> conditon.matchPieces),
                    Codec.INT.optionalFieldOf("above_range", 0).forGetter(conditon -> conditon.aboveRange),
                    Codec.INT.optionalFieldOf("horizontal_range", 0).forGetter(conditon -> conditon.horizontalRange),
                    Codec.INT.optionalFieldOf("below_range", 0).forGetter(conditon -> conditon.belowRange))
            .apply(builder, PieceInRangeCondition::new));

    private final List matchPieces;

    private final Integer aboveRange;
    private final Integer horizontalRange;
    private final Integer belowRange;

    public PieceInRangeCondition(List pieces, int aboveRange, int horizontalRange, int belowRange) {
        this.matchPieces = pieces;
        this.aboveRange = aboveRange;
        this.horizontalRange = horizontalRange;
        this.belowRange = belowRange;
        if (matchPieces.isEmpty()) {
            matchPieces.add(ALL); // No pieces specified -> match all pieces
        }
    }

    @Override
    public StructureConditionType type() {
        return StructureConditionType.PIECE_IN_RANGE;
    }

    @Override
    public boolean passes(StructureContext ctx) {
        // Extract args from context
        StructureTemplateManager templateManager = ctx.structureTemplateManager();
        List pieces = ctx.pieces();
        PieceEntry pieceEntry = ctx.pieceEntry();

        // Abort if missing any args
        if (templateManager == null) YungsApiCommon.LOGGER.error("Missing required field 'structureTemplateManager' for piece_in_range condition!");
        if (pieces == null) YungsApiCommon.LOGGER.error("Missing required field 'pieces' for piece_in_range condition!");
        if (pieceEntry == null) YungsApiCommon.LOGGER.error("Missing required field 'pieceEntry' for piece_in_horizontal_direction condition!");
        if (templateManager == null || pieces == null || pieceEntry == null) return false;

        PoolElementStructurePiece piece = pieceEntry.getPiece();
        BoundingBox searchBox = new BoundingBox(
                piece.getBoundingBox().minX() - this.horizontalRange,
                piece.getBoundingBox().minY() - this.belowRange,
                piece.getBoundingBox().minZ() - this.horizontalRange,
                piece.getBoundingBox().maxX() + this.horizontalRange,
                piece.getBoundingBox().maxY() + this.aboveRange,
                piece.getBoundingBox().maxZ() + this.horizontalRange);

        // Check for any matching pieces that satisfy the positional criteria
        for (PieceEntry otherPieceEntry : pieces) {
            PoolElementStructurePiece otherPiece = otherPieceEntry.getPiece();
            if (otherPiece.getElement() instanceof SinglePoolElement || otherPiece.getElement() instanceof YungJigsawSinglePoolElement) {
                // If otherPiece has the same bounding box as our starting piece, skip over it, as
                // it is likely just the same piece.
                if (otherPiece.getBoundingBox().equals(piece.getBoundingBox())) {
                    continue;
                }

                StructureTemplate otherStructureTemplate = otherPiece.getElement() instanceof SinglePoolElement
                        ? ((SinglePoolElementAccessor) otherPiece.getElement()).callGetTemplate(templateManager)
                        : ((YungJigsawSinglePoolElement) otherPiece.getElement()).getTemplate(templateManager);

                // Iterate our target pieces and check for a match with otherPiece
                for (ResourceLocation matchPieceId : matchPieces) {
                    StructureTemplate structureTemplate = templateManager.getOrCreate(matchPieceId);
                    if (otherStructureTemplate == structureTemplate || matchPieceId.equals(ALL)) {
                        // This is one of the pieces we're searching for, so we test its bounding box.
                        // It must intersect the search box, but not be within the current piece's bounding box.
                        if (otherPiece.getBoundingBox().intersects(searchBox) && !otherPiece.getBoundingBox().intersects(piece.getBoundingBox())) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy